我有一个 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
关于这种非线性(10 倍列减速 100 倍)随时间增加的任何解释?解决此问题的一种方法是将其融化为长 DT。但是,它会消耗许多倍的内存。有没有办法在内存使用和速度之间实现协调?谢谢。
最佳答案
我看到与 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
以便在必要时更容易比较结果。)Any explanation about this non-linear (100 times slow-down over 10 times column) increase in time?
通常,data.tables 和 data.frames 被优化以支持将行/观察分组在一起,而不是在大量列上进行迭代。我猜你的方法正在运行到你的 RAM 限制并使用交换内存......尽管我对此知之甚少。
我认为如果你想充分受益于 data.table 包的速度,你可能需要符合它的自然存储格式。如下所示,它产生了显着的差异。
One way to solve this is to melt it into long DT. However, it eats many folds more memory. Is there a way to achieve a reconciliation between the memory usage and speed?
我认为最好的方法是获得更多 RAM 并以长格式保存数据。我看到熔化的 table 大小大约是原来的两倍,但那里的计算速度快了 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
关于r - data.table lapply .SD 随着列数的增加而大幅减慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44470273/