0

众所周知,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 模式来解决这个简单的除法问题?

谢谢,穆龙

4

3 回答 3

6

首先,R 不一定慢。它的速度很大程度上取决于正确使用它,就像任何语言一样。有几件事可以在不做太多改动的情况下加速你的代码:results在开始之前预先分配你的 data.frame;使用列表和矩阵或向量构造而不是 data.frame;切换使用data.table;名单还在继续,但The R Inferno是一个很好的起点。

另外,看看这里。它很好地总结了如何利用多核机器。

Hadley Wickam 用他的plyr包简洁地解决了“干净的 R 模式”,特别是ddply

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
}
于 2012-05-04T16:15:08.337 回答
5

支持我的评论:1000 万行,26 个组。在单核 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.

于 2012-05-04T16:35:13.067 回答
2

我认为您的缓慢部分是由于您在 R 中的非 R 编程。以下将为您提供每组的相关性(我使用 mtcars 数据集并将其除以 cyl 组)并且做得非常快:

by(mtcars, mtcars$cyl, cor)
于 2012-05-04T16:20:33.193 回答