众所周知,R不是运行大型分析的最有效平台。 如果我有一个包含三个参数的大型数据框:
GROUP X Y
A 1 2
A 2 2
A 2 3
...
B 1 1
B 2 3
B 1 4
...
millions of rows
我希望在每个组上运行计算(例如,在X,Y上计算Pearson的r)并将结果存储在一个新的数据框中,我可以这样做:
df = loadDataFrameFrom( someFile )
results = data.frame()
for ( g in unique( df$GROUP)) ){
gdf <- subset( df, df$GROUP == g )
partialRes <- slowStuff( gdf$X,gdf$Y )
results = rbind( results, data.frame( GROUP = g, RES = partialRes ) )
}
// results contains all the results here.
useResults(results)
显而易见的问题是,即使在强大的多核机器上,这也非常慢。
我的问题是:是否有可能将此计算并行化,例如为每个组或一组组创建一个单独的线程? 是否有一个干净的R模式来解决这个简单的除法和问题?
谢谢, Mulone
答案 0 :(得分:6)
首先,R不一定慢。它的速度在很大程度上取决于正确使用它,就像任何语言一样。有一些方法可以在不改变的情况下加快代码速度:在开始之前预先分配results
data.frame;使用列表和矩阵或向量构造而不是data.frame;切换到使用data.table
;列表继续,但The R Inferno是一个很好的起点。
另外,看看here。它提供了有关如何利用多核机器的良好总结。
Hadley Wickam用他的plyr
包裹,特别是ddply
简洁地解决了“干净的R模式”:
library(plyr)
library(doMC)
registerDoMC()
ddply(df, .(GROUP), your.function, .parallel=TRUE)
然而,它并不一定快。你可以使用类似的东西:
library(parallel)
mclapply(unique(df$GRUOP), function(x, df) ...)
或者最后,您可以使用foreach
包:
foreach(g = unique(df$Group), ...) %dopar$ {
your.analysis
}
答案 1 :(得分:5)
备份我的评论:1000万行,26组。完成于&lt;单核3.3Ghz CPU上3秒。仅使用基础R.不需要并行化。
> set.seed(21)
> x <- data.frame(GROUP=sample(LETTERS,1e7,TRUE),X=runif(1e7),Y=runif(1e7))
> system.time( y <- do.call(rbind, lapply(split(x,x$GROUP),
+ function(d) data.frame(GROUP=d$GROUP[1],cor=cor(d$X,d$Y)))) )
user system elapsed
2.37 0.56 2.94
> y
GROUP cor
A A 2.311493e-03
B B -1.020239e-03
C C -1.735044e-03
D D 1.355110e-03
E E -8.027199e-04
F F 8.234086e-04
G G 2.337217e-04
H H -5.861781e-04
I I 7.799191e-04
J J 1.063772e-04
K K 7.174137e-04
L L 4.151059e-04
M M 4.440694e-04
N N 2.568411e-03
O O -3.827366e-04
P P -1.239380e-03
Q Q -1.057020e-03
R R 1.079676e-03
S S -1.819232e-03
T T -3.577533e-04
U U -1.084114e-03
V V 6.686503e-05
W W -1.631912e-03
X X 8.668508e-04
Y Y -6.460281e-04
Z Z 1.614978e-03
顺便说一下,只有当slowStuff
函数成为瓶颈时,并行化才有用。您在循环中使用rbind
可能是瓶颈,除非您在slowStuff
中执行类似操作。
答案 2 :(得分:2)
我认为你的缓慢部分是由于你在R中的非R编程。以下将给出每组的相关性(我使用mtcars数据集并将其除以cyl group)并且非常快速地执行:
by(mtcars, mtcars$cyl, cor)