2012-05-04 53 views
0

衆所周知,R並不是運行大量分析的最有效的平臺。 如果我有包含三個參數的大數據幀:在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 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

它可以並行化的方式很大程度上取決於計算的類型嗎? –

+5

您是否故意嘗試儘可能地做到儘可能慢?我不確定你是否可以寫得更低效。 –

+0

+1給Josh的評論。循環內部的「rbind」經常出現,也許R本身可以檢測並警告它。警告信息可能是「在for循環的最後一行中檢測到的,這可能非常慢。請參閱XYZ參考以獲得建議。「。在解析器中需要一個if()語句,也許吧? –

回答

5

首先,R不一定是緩慢的。它的速度在很大程度上取決於正確使用它,就像任何語言一樣。有幾件事可以在不改變很多的情況下加速代碼:在開始之前預先分配您的數據幀;使用列表和矩陣或向量構造而不是data.frame;切換到使用data.table;名單繼續,但The R Inferno是一個很好的開始。

另外,看看here。它對如何利用多核機器提供了一個很好的總結。

的「清潔[R模式」是簡明扼要地哈德利Wickam他plyr包解決具體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 
} 
+0

R Inferno看起來不錯,非常感謝你的提示!這將很好寫一個R教程的Java/C程序員,顯示出主要區別... – Mulone

2

我認爲你是緩慢部分原因是由於下面會給你的非[R編程的R.每組你的相關性(我用的mtcars數據集和共青團組劃分的話)並做到這一點非常快:

by(mtcars, mtcars$cyl, cor) 
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中執行類似操作。

+0

我並沒有真正關注rbind部分,這確實很慢,但是在slowStuff部分。這就是爲什麼我想要平行計算。我不打算爲更快的線性方法,但對於並行的方法 – Mulone

+1

@Mulone:我會鼓勵你在拋出更多的核心問題之前對你的代碼進行剖析,你可能會驚訝地發現,更快的線性方法是仍然比並行方法更快。 –