我有一个20k x 60k的表用于聚合,我正在尝试使用高内存使用效率和速度效率的方法。我注意到data.table的速度随着列数的增加而急剧下降。例如:
library(data.table)
# a 200 x 1,000 table.
test_dt= data.table(sample= rep(1:100,2), value= matrix(sample(6e07, 2e05), nrow = 200 ))
system.time(test_dt[, lapply(.SD, mean), by= sample, .SDcols= colnames(test_dt)[-1]])
# user system elapsed
# 0.470 0.009 0.117
# a 200 x 10, 000 table
test_dt= data.table(sample= rep(1:100,2), value= matrix(sample(6e07, 2e06), nrow = 200 ))
system.time(test_dt[, lapply(.SD, mean), by= sample, .SDcols= colnames(test_dt)[-1]])
# user system elapsed
# 15.055 0.603 15.334
关于这种非线性(100倍减速超过10倍列)的任何解释都会增加?解决这个问题的一种方法是将其融化为长DT。但是,它会占用更多的内存。有没有办法实现内存使用和速度之间的协调?感谢。
答案 0 :(得分:3)
我看到与OP类似的结果:
# a 200 x 10, 000 table
set.seed(1)
test_dt= data.table(sample= rep(1:100,2), value= matrix(sample(6e07, 2e06), nrow = 200 ))[,
(2:10001) := lapply(.SD, as.numeric), .SDcols=2:10001]
system.time(z <- test_dt[, lapply(.SD, mean), by= sample])
# user system elapsed
# 12.27 0.00 12.26
(我转换为数字,因为它非常清楚,这些将被视为浮点数;并添加set.seed
以便在必要时比较结果更容易。)< / p>
关于这种非线性(100倍减速超过10倍列)的任何解释都会增加?
通常,data.tables和data.frames经过优化,可以支持将行/观察分组在一起,而不是迭代大量的列。我猜你的方法已经达到RAM限制并使用交换内存......虽然我对此并不是很了解。
我认为如果您想从data.table包的速度中充分受益,您可能需要遵循其自然存储格式。如下所示,它有显着的不同。
解决这个问题的一种方法是将其融入长DT。但是,它会占用更多的内存。有没有办法实现内存使用和速度之间的协调?
我认为最好的方法是获得更多内存并保持数据的长篇。我看到熔化的表大约是两倍大小,但计算速度却快了100倍。
test_mdt = melt(test_dt, id = "sample")[, variable := match(variable, unique(variable))]
system.time(mz <- test_mdt[, .(res = mean(value)), by=.(sample, variable)])
# user system elapsed
# 0.11 0.00 0.11
object.size(test_dt) # 17.8 MB
object.size(test_mdt) # 32.0 MB
或者,如果每个样本具有相同的大小,请使用矩阵列表或数组:
test_dt[, g := rowid(sample)]
test_mats = lapply( split(test_dt[, !"sample"], by="g", keep.by=FALSE), as.matrix )
system.time(matz <- Reduce(`+`, test_mats)/length(test_mats))
# user system elapsed
# 0 0 0
object.size(test_mats) # 17.3 MB