为什么 Rcpp 会损坏 xts 对象?
Why does Rcpp corrupt xts object?
假设我有一个 xts 对象和 return 通过 Rcpp 函数的索引。以这种方式接触 xts 对象似乎会损坏 xts 对象。
可以通过强制深拷贝来修复。
虽然我确实有解决方法,但我不明白为什么会存在这个问题——或者为什么需要我的技巧?
使用 dirk Rcpp Gallery 中的建议代码,xts 对象一旦被触及就会损坏。
// [[Rcpp::export]]
DatetimeVector xtsIndex(NumericMatrix X) {
DatetimeVector v(NumericVector(X.attr("index")));
return v;
}
require(xts)
xx <- xts(1:10, order.by = seq.Date(Sys.Date(), by = "day", length.out = 10))
xtsIndex(xx)
...
> print(xx)
Error in Ops.POSIXt(.index(x), 86400) :
'%/%' not defined for "POSIXt" objects
调整代码以强制执行深层复制可防止损坏。
// [[Rcpp::export]]
DatetimeVector xtsIndex_deep(NumericMatrix X) {
DatetimeVector v = clone(NumericVector(X.attr("index")));
return v;
}
> xtsIndex_deep(xx)
[1] "2021-05-13 UTC" "2021-05-14 UTC" "2021-05-15 UTC" "2021-05-16 UTC" "2021-05-17 UTC"
[6] "2021-05-18 UTC" "2021-05-19 UTC" "2021-05-20 UTC" "2021-05-21 UTC" "2021-05-22 UTC"
> xx
[,1] [,2]
2021-05-13 1 10
2021-05-14 2 9
2021-05-15 3 8
2021-05-16 4 7
2021-05-17 5 6
2021-05-18 6 5
2021-05-19 7 4
2021-05-20 8 3
2021-05-21 9 2
2021-05-22 10 1
怎么回事?
我无法用更简单的属性提取函数重现一切都很好并且 xx 没有改变:
> cppFunction("SEXP xtsIndex(NumericMatrix X) { SEXP s = X.attr(\"index\"); return s; } ")
> xx <- xts(1:10, order.by = seq.Date(Sys.Date(), by = "day", length.out = 10))
> head(xx)
[,1]
2021-05-13 1
2021-05-14 2
2021-05-15 3
2021-05-16 4
2021-05-17 5
2021-05-18 6
>
> xtsIndex(xx)
[1] 1620864000 1620950400 1621036800 1621123200 1621209600 1621296000
[7] 1621382400 1621468800 1621555200 1621641600
attr(,"tzone")
[1] "UTC"
attr(,"tclass")
[1] "Date"
>
> head(xx)
[,1]
2021-05-13 1
2021-05-14 2
2021-05-15 3
2021-05-16 4
2021-05-17 5
2021-05-18 6
>
函数 xtsIndex
将在输入时创建一个副本(因为我们的 xts
对象包含一个整数序列作为数据 NumericMatrix
肯定是一个复制的对象,但它保留了attribute
我们可以提取)。
但是请注意,xx
中的 Date
序列现在如何以 POSIXct
或 Datetime
为单位显示。这看起来像是 xts
(或者可能是 Rcpp
,但我认为这里是 xts
)可能会在这里执行的强制转换的可能错误。你最好从 POSIXct
时间对象开始,即使它是每日数据。
这样做还允许我们正确键入 Datetime
:
的提取函数
> cppFunction("DatetimeVector xtsIndex(NumericMatrix X) {
return DatetimeVector(wrap(X.attr(\"index\"))); } ")
> xx <- xts(1:10, order.by = as.POSIXct(seq.Date(Sys.Date(), by = "day", length.out = 10)))
> head(xx)
[,1]
2021-05-12 19:00:00 1
2021-05-13 19:00:00 2
2021-05-14 19:00:00 3
2021-05-15 19:00:00 4
2021-05-16 19:00:00 5
2021-05-17 19:00:00 6
> head(xtsIndex(xx))
[1] "2021-05-12 19:00:00 CDT" "2021-05-13 19:00:00 CDT" "2021-05-14 19:00:00 CDT"
[6] "2021-05-15 19:00:00 CDT" "2021-05-16 19:00:00 CDT" "2021-05-17 19:00:00 CDT"
> head(xx)
[,1]
2021-05-12 19:00:00 1
2021-05-13 19:00:00 2
2021-05-14 19:00:00 3
2021-05-15 19:00:00 4
2021-05-16 19:00:00 5
2021-05-17 19:00:00 6
>
假设我有一个 xts 对象和 return 通过 Rcpp 函数的索引。以这种方式接触 xts 对象似乎会损坏 xts 对象。
可以通过强制深拷贝来修复。
虽然我确实有解决方法,但我不明白为什么会存在这个问题——或者为什么需要我的技巧?
使用 dirk Rcpp Gallery 中的建议代码,xts 对象一旦被触及就会损坏。
// [[Rcpp::export]]
DatetimeVector xtsIndex(NumericMatrix X) {
DatetimeVector v(NumericVector(X.attr("index")));
return v;
}
require(xts)
xx <- xts(1:10, order.by = seq.Date(Sys.Date(), by = "day", length.out = 10))
xtsIndex(xx)
...
> print(xx)
Error in Ops.POSIXt(.index(x), 86400) :
'%/%' not defined for "POSIXt" objects
调整代码以强制执行深层复制可防止损坏。
// [[Rcpp::export]]
DatetimeVector xtsIndex_deep(NumericMatrix X) {
DatetimeVector v = clone(NumericVector(X.attr("index")));
return v;
}
> xtsIndex_deep(xx)
[1] "2021-05-13 UTC" "2021-05-14 UTC" "2021-05-15 UTC" "2021-05-16 UTC" "2021-05-17 UTC"
[6] "2021-05-18 UTC" "2021-05-19 UTC" "2021-05-20 UTC" "2021-05-21 UTC" "2021-05-22 UTC"
> xx
[,1] [,2]
2021-05-13 1 10
2021-05-14 2 9
2021-05-15 3 8
2021-05-16 4 7
2021-05-17 5 6
2021-05-18 6 5
2021-05-19 7 4
2021-05-20 8 3
2021-05-21 9 2
2021-05-22 10 1
怎么回事?
我无法用更简单的属性提取函数重现一切都很好并且 xx 没有改变:
> cppFunction("SEXP xtsIndex(NumericMatrix X) { SEXP s = X.attr(\"index\"); return s; } ")
> xx <- xts(1:10, order.by = seq.Date(Sys.Date(), by = "day", length.out = 10))
> head(xx)
[,1]
2021-05-13 1
2021-05-14 2
2021-05-15 3
2021-05-16 4
2021-05-17 5
2021-05-18 6
>
> xtsIndex(xx)
[1] 1620864000 1620950400 1621036800 1621123200 1621209600 1621296000
[7] 1621382400 1621468800 1621555200 1621641600
attr(,"tzone")
[1] "UTC"
attr(,"tclass")
[1] "Date"
>
> head(xx)
[,1]
2021-05-13 1
2021-05-14 2
2021-05-15 3
2021-05-16 4
2021-05-17 5
2021-05-18 6
>
函数 xtsIndex
将在输入时创建一个副本(因为我们的 xts
对象包含一个整数序列作为数据 NumericMatrix
肯定是一个复制的对象,但它保留了attribute
我们可以提取)。
但是请注意,xx
中的 Date
序列现在如何以 POSIXct
或 Datetime
为单位显示。这看起来像是 xts
(或者可能是 Rcpp
,但我认为这里是 xts
)可能会在这里执行的强制转换的可能错误。你最好从 POSIXct
时间对象开始,即使它是每日数据。
这样做还允许我们正确键入 Datetime
:
> cppFunction("DatetimeVector xtsIndex(NumericMatrix X) {
return DatetimeVector(wrap(X.attr(\"index\"))); } ")
> xx <- xts(1:10, order.by = as.POSIXct(seq.Date(Sys.Date(), by = "day", length.out = 10)))
> head(xx)
[,1]
2021-05-12 19:00:00 1
2021-05-13 19:00:00 2
2021-05-14 19:00:00 3
2021-05-15 19:00:00 4
2021-05-16 19:00:00 5
2021-05-17 19:00:00 6
> head(xtsIndex(xx))
[1] "2021-05-12 19:00:00 CDT" "2021-05-13 19:00:00 CDT" "2021-05-14 19:00:00 CDT"
[6] "2021-05-15 19:00:00 CDT" "2021-05-16 19:00:00 CDT" "2021-05-17 19:00:00 CDT"
> head(xx)
[,1]
2021-05-12 19:00:00 1
2021-05-13 19:00:00 2
2021-05-14 19:00:00 3
2021-05-15 19:00:00 4
2021-05-16 19:00:00 5
2021-05-17 19:00:00 6
>