例如,当我需要对未来几年进行预测时,我经常在data.table中使用回收。每年以后我都会重复原始数据。
这可能会导致类似的结果:
library(data.table)
dt <- data.table(cbind(1:500000, 500000:1))
dt2 <- dt[, c(.SD, .(year = 1:10)), by = 1:nrow(dt) ]
但是我经常不得不处理数百万行,并且比这个玩具示例中的列要多得多。时间增加了..试试这个:
library(data.table)
dt <- data.table(cbind(1:50000000, 50000000:1))
dt2 <- dt[, c(.SD, .(year = 1:10)), by = 1:nrow(dt) ]
我的问题是:有没有更有效的方法来实现这一目的?
感谢您的帮助!
我将这个问题视为交叉联接。没有内置的方法可以在两个数据表之间进行交叉联接(CJ
函数对向量有效),但是从讨论on this issue来看,此函数很好用:
CJDT <- function(...) {
Reduce(function(DT1, DT2) cbind(DT1, DT2[rep(1:.N, each=nrow(DT1))]), list(...))
}
使用您的大型示例,这对我有用:
years = data.table(year = 1:10, key = "year")
setkey(dt)
dt3 = CJDT(dt, years)
您的方法需要更长的时间才能耗尽内存。
如评论中所述,我怀疑问题的前提可能是可疑。无论如何,这是一个更快的替代方法:
dt[CJ(V1, year = 1:10), on = "V1"]
基准测试:
data.table(cbind(1:50000000, 50000000:1))
microbenchmark::microbenchmark(
op = dt[, c(.SD, .(year = 1:10)), by = 1:nrow(dt) ],
sb = dt[CJ(V1, year = 1:10), on = "V1"],
times = 4
)
Unit: milliseconds
expr min lq mean median uq max neval
op 724.7858 726.5420 890.5499 840.6526 1054.5578 1156.1085 4
sb 197.3953 201.4305 235.6163 206.1864 269.8021 332.6971 4