arg*_*eus 10 split r pentaho lapply
我正在对数据帧进行分区split(),以便用于parLapply()并行调用每个分区上的函数.数据框有130万行和20列.我正在拆分/分区两列,都是字符类型.看起来有~47K唯一ID和~12K唯一代码,但不是每个ID和代码配对都匹配.得到的分区数量约为250K.这是split()一行:
system.time(pop_part <- split(pop, list(pop$ID, pop$code)))
Run Code Online (Sandbox Code Playgroud)
然后将分区输入parLapply()如下:
cl <- makeCluster(detectCores())
system.time(par_pop <- parLapply(cl, pop_part, func))
stopCluster(cl)
Run Code Online (Sandbox Code Playgroud)
我让split()代码单独运行差不多一个小时就完成了.我可以单独拆分ID,大约需要10分钟.此外,R studio和工作线程消耗约6GB的RAM.
我知道得到的分区数量的原因是我在Pentaho数据集成(PDI)中有相同的代码,它在30秒内运行(对于整个程序,而不仅仅是"拆分"代码).我并不希望R具有这种性能,但最坏的情况可能在10-15分钟内完成.
主要问题:是否有更好的替代分裂?我也尝试ddply()过.parallel = TRUE,但它也运行了一个多小时,从未完成.
Mar*_*gan 11
将索引拆分为 pop
idx <- split(seq_len(nrow(pop)), list(pop$ID, pop$code))
Run Code Online (Sandbox Code Playgroud)
拆分并不慢,例如,
> system.time(split(seq_len(1300000), sample(250000, 1300000, TRUE)))
user system elapsed
1.056 0.000 1.058
Run Code Online (Sandbox Code Playgroud)
所以,如果你的,我猜你的数据的某些方面会降低速度,例如,ID并且code都是具有多个级别的因素,因此它们的完整交互,而不是数据集中出现的级别组合,都会被计算出来
> length(split(1:10, list(factor(1:10), factor(10:1))))
[1] 100
> length(split(1:10, paste(letters[1:10], letters[1:10], sep="-")))
[1] 10
Run Code Online (Sandbox Code Playgroud)
或者你的内存不足.
使用mclapply而不是parLapply在非Windows机器上使用进程(我猜你应该这样做detectCores()).
par_pop <- mclapply(idx, function(i, pop, fun) fun(pop[i,]), pop, func)
Run Code Online (Sandbox Code Playgroud)
从概念上讲,它听起来像是你真正的目标pvec(在处理器上分配矢量化计算)而不是mclapply(迭代数据帧中的各个行).
此外,真正作为第一步,考虑识别瓶颈func; 数据很大但不是很大,所以也许不需要并行评估 - 也许你已经编写了PDI代码而不是R代码?注意数据框中的数据类型,例如因子与字符.在写得不好和效率高的R代码之间获得100倍的加速并不罕见,而并行评估最多与内核数量成正比.
小智 5
如果 x 是一个因子并且 f 包含许多不同的元素,则 Split(x,f) 会很慢
所以,这段代码如果很快的话:
system.time(split(seq_len(1300000), sample(250000, 1300000, TRUE)))
Run Code Online (Sandbox Code Playgroud)
但是,这非常慢:
system.time(split(factor(seq_len(1300000)), sample(250000, 1300000, TRUE)))
Run Code Online (Sandbox Code Playgroud)
这又很快了,因为只有 25 个组
system.time(split(factor(seq_len(1300000)), sample(25, 1300000, TRUE)))
Run Code Online (Sandbox Code Playgroud)