diff --git a/NEWS.md b/NEWS.md index f25d3eec68..6f3138180f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -92,6 +92,8 @@ 17. Internal-only `.shallow` now retains keys correctly, [#2336](https://github.com/Rdatatable/data.table/issues/2336). Thanks to @MarkusBonsch for reporting, fixing ([PR #2337](https://github.com/Rdatatable/data.table/pull/2337)) and adding 37 tests. This much advances the journey towards exporting `shallow()`, [#2323](https://github.com/Rdatatable/data.table/issues/2323). 18. `isoweek` calculation is correct regardless of local timezone setting (`Sys.timezone()`), [#2407](https://github.com/Rdatatable/data.table/issues/2407). Thanks to @MoebiusAV and @SimonCoulombe for reporting and @MichaelChirico for fixing. + +19. fixed `as.xts.data.table` to support all xts supported time based index clasess [#2408](https://github.com/Rdatatable/data.table/issues/2408). Thanks to @ebs238 for reporting and for the PR. #### NOTES diff --git a/R/xts.R b/R/xts.R index d60840ebb4..60d27086b6 100644 --- a/R/xts.R +++ b/R/xts.R @@ -9,9 +9,9 @@ as.data.table.xts <- function(x, keep.rownames = TRUE, ...) { as.xts.data.table <- function(x, ...) { stopifnot(requireNamespace("xts"), !missing(x), is.data.table(x)) - if (!any((index_class <- class(x[[1L]])) %in% c("POSIXct","Date"))) stop("data.table must have a POSIXct, Date or IDate column on first position, use `setcolorder` function.") + if (!xts::is.timeBased(x[[1L]])) stop("data.table must have a time based column in first position, use `setcolorder` function to change the order, or see ?timeBased for supported types") colsNumeric = vapply_1b(x, is.numeric)[-1L] # exclude first col, xts index - if (any(!colsNumeric)) warning(paste("Following columns are not numeric and will be omitted:", paste(names(colsNumeric)[!colsNumeric], collapse=", "))) - r = setDF(x[, .SD, .SDcols=names(colsNumeric)[colsNumeric]]) - xts::as.xts(r, order.by=if ("IDate" %in% index_class) as.Date(x[[1L]]) else x[[1L]]) + if (any(!colsNumeric)) warning(paste("Following columns are not numeric and will be omitted:", paste(names(colsNumeric)[!colsNumeric], collapse = ", "))) + r = setDF(x[, .SD, .SDcols = names(colsNumeric)[colsNumeric]]) + return(xts::as.xts(r, order.by = if ("IDate" %in% class(x[[1L]])) as.Date(x[[1L]]) else x[[1L]])) } diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 8b365c0e70..8a15981df6 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -6190,6 +6190,21 @@ if ("package:xts" %in% search()) { xt_dt = as.xts.data.table(dt) test(1465.3, all.equal(dt, dt_xt, check.attributes = FALSE)) test(1465.4, xt, xt_dt) + # index types returned from to.period + dt = data.table(index = as.Date((as.Date("2014-12-12") - 729):as.Date("2014-12-12"), origin = "1970-01-01"), quantity = as.numeric(rep(c(1:5), 73)), value = rep(c(1:73) * 100, 5)) + xt = as.xts(matrix(data = c(dt$quantity, dt$value), ncol = 2, dimnames = list(NULL, c("quantity", "value"))), order.by = dt$index) + xt_w = xts::to.weekly(xt) + xt_dt_xt_w = as.xts.data.table(as.data.table(xt_w)) + xt_m = xts::to.monthly(xt) + xt_dt_xt_m = as.xts.data.table(as.data.table(xt_m)) + xt_q = xts::to.quarterly(xt) + xt_dt_xt_q = as.xts.data.table(as.data.table(xt_q)) + xt_y = xts::to.yearly(xt) + xt_dt_xt_y = as.xts.data.table(as.data.table(xt_y)) + test(1465.5, all.equal(xt_w, xt_dt_xt_w, check.attributes = FALSE)) + test(1465.6, all.equal(xt_m, xt_dt_xt_m, check.attributes = FALSE)) + test(1465.7, all.equal(xt_q, xt_dt_xt_q, check.attributes = FALSE)) + test(1465.8, all.equal(xt_y, xt_dt_xt_y, check.attributes = FALSE)) } # as.data.table.default #969