2013-09-26 119 views
9

我正在使用split()對數據幀進行分區,以便使用parLapply()並行調用每個分區上的函數。數據幀有130萬行和20列。我分裂/分成兩列,兩種字符類型。看起來像〜47K獨特的ID和〜12K獨特的代碼,但不是每個ID和代碼的配對匹配。由此產生的分區數量是〜250K。這裏是split()行:然後快速替代分割R

system.time(pop_part <- split(pop, list(pop$ID, pop$code))) 

該分區將被送入parLapply()如下:

cl <- makeCluster(detectCores()) 
system.time(par_pop <- parLapply(cl, pop_part, func)) 
stopCluster(cl) 

我讓split()代碼單獨運行近一個小時,並沒有完成。我可以通過身份證分開,這需要大約10分鐘。此外,R studio和工作線程正在消耗大約6GB的RAM。

我知道分區結果數量的原因是我在30秒內(對於整個程序,而不僅僅是「拆分」代碼)運行Pentaho數據集成(PDI)中的等效代碼。我不希望與R這種類型的表現,但可能在10 - 15分鐘內完成的最壞情況。

主要問題:是否有更好的選擇拆分?我也試過ddply().parallel = TRUE,但它也跑了一個多小時,從未完成。

回答

9

分割指數爲pop

idx <- split(seq_len(nrow(pop)), list(pop$ID, pop$code)) 

分裂是不慢,例如,

> system.time(split(seq_len(1300000), sample(250000, 1300000, TRUE))) 
    user system elapsed 
    1.056 0.000 1.058 

所以,如果你是我想有數據的某些方面是會減慢速度,例如,IDcode都是具有多個級別的因素,因此它們的完整交互作用(而不是數據集中出現的級別組合)是計算得出的

> 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 

或者您的內存不足。

使用mclapply而不是parLapply如果您在非Windows計算機上使用進程(我猜是這種情況,因爲您要求detectCores())。

par_pop <- mclapply(idx, function(i, pop, fun) fun(pop[i,]), pop, func) 

概念上,它聽起來就像你真正瞄準pvec(分佈在處理器的矢量運算),而不是mclapply(迭代超過各行的數據幀)。

此外,真的作爲第一步,請考慮在func中確定瓶頸;數據很大,但並不那麼大,所以可能不需要並行評估 - 也許您已經編寫了PDI代碼而不是R代碼?注意數據框中的數據類型,例如因素與字符。在寫得不好的和有效的R代碼之間獲得100倍的加速並不罕見,而並行評估至多與內核數量成正比。

+0

謝謝,我會試試看。哈,我實際上最初編寫了R代碼,然後將其移植到PDI(我對R比PDI更有經驗)。 – argoneus

+0

我運行了你發佈的'split()'代碼,並且等了將近一個小時,但它從未完成。 – argoneus

+0

在拆分周圍添加了一些其他建議,這應該在一秒或更短的時間內完成。也許因素也導致func也變慢了? –

2

斯普利特(X,F)是緩慢的,如果x是一個因素,F包含了很多不同的元素

因此,如果快速驗證碼:

system.time(split(seq_len(1300000), sample(250000, 1300000, TRUE))) 

但是,這是非常緩慢:

system.time(split(factor(seq_len(1300000)), sample(250000, 1300000, TRUE))) 

而這又是快的,因爲只有25組

system.time(split(factor(seq_len(1300000)), sample(25, 1300000, TRUE)))