Reputation: 8435
Say I have an xts object and return the index via an Rcpp function. Touching the xts object in this way seems to corrupt the xts object.
It can be fixed by forcing a deep copy.
While i do have a work-around, i don't understand why the problem exists -- or why my hack is required?
Using the suggested code from dirk's Rcpp Gallery, the xts object is corrupted once touched.
// [[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
Tweaking the code to force a deep copy prevents the corruption.
// [[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
what's going on?
Upvotes: 1
Views: 103
Reputation: 368261
I cannot reproduce that with a simpler attribute extraction function all is well and xx is not altered:
> 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
>
The function xtsIndex
will create a copy on input (as our xts
object contains an integer sequence as data the NumericMatrix
will surely be a copied object, but it retains the attribute
we can extract).
Note, however, how the Date
sequence from xx
is now displayed in units of a POSIXct
or Datetime
. This looks like a possible error from a coercion which xts
(or possibly Rcpp
but I think it is xts
here) may do here. You are probably better off starting with a POSIXct
time object even if it daily data.
Doing so also allow us to properly type the extractor function for 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
>
Upvotes: 4