data.table高效回收V2
data.table efficient recycling V2
这是这个问题的后续:
这里的区别是每行的未来年数不一定相同..
我经常在 data.table 中使用回收,例如,当我需要对未来几年进行预测时。我会在未来的每一年重复我的原始数据。
这可能会导致类似的结果:
library(data.table)
dt <- data.table(1:500000, 500000:1, rpois(500000, 240))
dt2 <- dt[, c(.SD, .(year = 1:V3)), by = 1:nrow(dt) ]
但我经常需要处理数百万行和比这个玩具示例中更多的列。时间增加..试试这个:
library(data.table)
dt <- data.table(1:5000000, 5000000:1, rpois(5000000, 240))
dt2 <- dt[, c(.SD, .(year = 1:V3)), by = 1:nrow(dt) ]
我的问题是:有没有更有效的方法来实现这个目的?
感谢您的帮助!
这是一个更快的实现,但由于 data.table
中的 lapply
循环仍然很长
dt2 <- data.table(
rep(dt$V1, dt$V3),
rep(dt$V2, dt$V3),
rep(dt$V3, dt$V3),
unlist(lapply(dt$V3, function(x){1:x}))
)
希望对您有所帮助!
这是另一个答案的略微改进版本。
- 使用非默认值
unlist
rep.int
而不是 rep
seq_len
而不是 :
setDT
而不是 data.table()
- @Cole
建议的 sequence
函数更好
- 以及内部
vecseq
的进一步小改进
放在一起似乎有所不同。
时间...
library(data.table)
f0 = function(dt) {
dt[, c(.SD, .(year = 1:V3)), by = 1:nrow(dt) ]
}
f1 = function(dt) {
dt2 <- data.table(
rep(dt$V1, dt$V3),
rep(dt$V2, dt$V3),
rep(dt$V3, dt$V3),
unlist(lapply(dt$V3, function(x){1:x}))
)
dt2
}
f2 = function(dt) {
dt2 = list(
V1 = rep.int(dt$V1, dt$V3),
V2 = rep.int(dt$V2, dt$V3),
V3 = rep.int(dt$V3, dt$V3),
year = unlist(lapply(dt$V3, seq_len), recursive=FALSE, use.names=FALSE)
)
setDT(dt2)
dt2
}
f3 = function(dt) {
## even better with sequence function suggested by @Cole
dt2 = list(
V1 = rep.int(dt$V1, dt$V3),
V2 = rep.int(dt$V2, dt$V3),
V3 = rep.int(dt$V3, dt$V3),
year = sequence(dt$V3)
)
setDT(dt2)
dt2
}
f4 = function(dt) {
dt[, c(lapply(.SD, rep.int, V3), year = .(sequence(V3)))]
}
f5 = function(dt) {
dt2 = list(
V1 = rep.int(dt$V1, dt$V3),
V2 = rep.int(dt$V2, dt$V3),
V3 = rep.int(dt$V3, dt$V3),
year = data.table:::vecseq(rep.int(1L,length(dt$V3)), dt$V3, NULL)
)
setDT(dt2)
dt2
}
关于“大”数据
dt <- data.table(1:5000000, 5000000:1, rpois(5000000, 240))
system.time(f0(dt))
# user system elapsed
# 22.100 18.914 40.449
system.time(f1(dt))
# user system elapsed
# 35.866 15.607 51.475
system.time(f2(dt))
# user system elapsed
# 22.922 6.839 29.760
system.time(f3(dt))
# user system elapsed
# 6.509 6.723 13.233
system.time(f4(dt))
# user system elapsed
# 12.140 14.114 26.254
system.time(f5(dt))
# user system elapsed
# 6.448 4.057 10.506
无论如何,您应该尝试改进您在扩展数据集上 运行 的流程,因为也许您一开始就不必扩展它。
例如,在 frollmean
函数中有一个参数 adaptive
,它可以计算可变长度 window 上的滚动平均值,通常计算该值需要先扩充数据。
V3
在您的数据中提醒了很多 window 自适应移动平均线的长度。
试试这个:
dt2 <- dt[dt[,rep(1:nrow(dt),V3)],]
dt2[,year:= dt[,sequence(V3)]]
这是这个问题的后续:
这里的区别是每行的未来年数不一定相同..
我经常在 data.table 中使用回收,例如,当我需要对未来几年进行预测时。我会在未来的每一年重复我的原始数据。
这可能会导致类似的结果:
library(data.table)
dt <- data.table(1:500000, 500000:1, rpois(500000, 240))
dt2 <- dt[, c(.SD, .(year = 1:V3)), by = 1:nrow(dt) ]
但我经常需要处理数百万行和比这个玩具示例中更多的列。时间增加..试试这个:
library(data.table)
dt <- data.table(1:5000000, 5000000:1, rpois(5000000, 240))
dt2 <- dt[, c(.SD, .(year = 1:V3)), by = 1:nrow(dt) ]
我的问题是:有没有更有效的方法来实现这个目的?
感谢您的帮助!
这是一个更快的实现,但由于 data.table
lapply
循环仍然很长
dt2 <- data.table(
rep(dt$V1, dt$V3),
rep(dt$V2, dt$V3),
rep(dt$V3, dt$V3),
unlist(lapply(dt$V3, function(x){1:x}))
)
希望对您有所帮助!
这是另一个答案的略微改进版本。
- 使用非默认值
unlist
rep.int
而不是rep
seq_len
而不是:
setDT
而不是data.table()
- @Cole 建议的
- 以及内部
vecseq
的进一步小改进
sequence
函数更好
放在一起似乎有所不同。
时间...
library(data.table)
f0 = function(dt) {
dt[, c(.SD, .(year = 1:V3)), by = 1:nrow(dt) ]
}
f1 = function(dt) {
dt2 <- data.table(
rep(dt$V1, dt$V3),
rep(dt$V2, dt$V3),
rep(dt$V3, dt$V3),
unlist(lapply(dt$V3, function(x){1:x}))
)
dt2
}
f2 = function(dt) {
dt2 = list(
V1 = rep.int(dt$V1, dt$V3),
V2 = rep.int(dt$V2, dt$V3),
V3 = rep.int(dt$V3, dt$V3),
year = unlist(lapply(dt$V3, seq_len), recursive=FALSE, use.names=FALSE)
)
setDT(dt2)
dt2
}
f3 = function(dt) {
## even better with sequence function suggested by @Cole
dt2 = list(
V1 = rep.int(dt$V1, dt$V3),
V2 = rep.int(dt$V2, dt$V3),
V3 = rep.int(dt$V3, dt$V3),
year = sequence(dt$V3)
)
setDT(dt2)
dt2
}
f4 = function(dt) {
dt[, c(lapply(.SD, rep.int, V3), year = .(sequence(V3)))]
}
f5 = function(dt) {
dt2 = list(
V1 = rep.int(dt$V1, dt$V3),
V2 = rep.int(dt$V2, dt$V3),
V3 = rep.int(dt$V3, dt$V3),
year = data.table:::vecseq(rep.int(1L,length(dt$V3)), dt$V3, NULL)
)
setDT(dt2)
dt2
}
关于“大”数据
dt <- data.table(1:5000000, 5000000:1, rpois(5000000, 240))
system.time(f0(dt))
# user system elapsed
# 22.100 18.914 40.449
system.time(f1(dt))
# user system elapsed
# 35.866 15.607 51.475
system.time(f2(dt))
# user system elapsed
# 22.922 6.839 29.760
system.time(f3(dt))
# user system elapsed
# 6.509 6.723 13.233
system.time(f4(dt))
# user system elapsed
# 12.140 14.114 26.254
system.time(f5(dt))
# user system elapsed
# 6.448 4.057 10.506
无论如何,您应该尝试改进您在扩展数据集上 运行 的流程,因为也许您一开始就不必扩展它。
例如,在 frollmean
函数中有一个参数 adaptive
,它可以计算可变长度 window 上的滚动平均值,通常计算该值需要先扩充数据。
V3
在您的数据中提醒了很多 window 自适应移动平均线的长度。
试试这个:
dt2 <- dt[dt[,rep(1:nrow(dt),V3)],]
dt2[,year:= dt[,sequence(V3)]]