2013-07-01 1 views
14

Ich verwende foreach mit einer .combine = rbindlist. Das scheint nicht zu funktionieren, obwohl es funktioniert, wenn ich .combine = rbind verwende.R foreach mit .combine = rbindlist

Nur zur Veranschaulichung ein einfaches Beispiel mit -

> t2 <- data.table(col1=c(1,2,3)) 
> foreach (i=1:3, .combine=rbind) %dopar% unique(t2) 
    col1 
1: 1 
2: 2 
3: 3 
4: 1 
5: 2 
6: 3 
7: 1 
8: 2 
9: 3 

# But using rbindlist gives an error 

> foreach (i=1:3, .combine=rbindlist) %dopar% unique(t2) 
error calling combine function: 
<simpleError in fun(result.1, result.2): unused argument(s) (result.2)> 
NULL 

Hat jemand in der Lage gewesen, diese Arbeit zu machen?

Vielen Dank im Voraus.

+0

Ich verstehe, dass wir rbindlist auf einem Listenobjekt aufrufen sollten - rbindlist (Liste (dt1, dt2)) ... aber nicht sicher, wie es mit der foreach .combine-Funktion auszuführen. – xbsd

Antwort

16

Es ist im Grunde, was Sie gesagt - rbindlist nimmt eine list Argument, und der Fehler, Sie bekommen die gleiche ist wie diese:

result.1 = data.table(blah = 23) 
result.2 = data.table(blah = 34) 

rbindlist(result.1, result.2) 
#Error in rbindlist(result.1, result.2) : unused argument (result.2) 

Wenn Sie rbindlist nutzen wollen, die Art und Weise, es zu tun würde dies:

rbindlist(foreach (i = 1:3) %dopar% unique(t2)) 

oder dies:

foreach (i=1:3, .combine=function(x,y)rbindlist(list(x,y))) %dopar% unique(t2) 
+0

Danke! Funktioniert sehr gut. – xbsd

+0

Ihre erste Lösung mit '.combine = list' schlägt fehl, wenn mehr als 100 Ergebnisse vorliegen, da Sie in diesem Fall eine verschachtelte Liste erhalten. Lassen Sie die Argumente '.combine' und' .multicombine' einfach weg und es funktioniert gut, da das Standardverhalten darin besteht, die Ergebnisse in einer Liste zurückzugeben. Ich mag deine zweite Lösung am besten und sie funktioniert mit einer beliebigen Anzahl von Ergebnissen. –

+0

@SteveWeston siehe den .maxcombine-Kommentar und? Foreach – eddi

11

Hier ist ein Weg, um sowohl den Einsatz rbindlist als .combine Funktion und haben .multicombine=TRUE:

foreach (i=1:3, 
     .combine=function(...) rbindlist(list(...)), 
     .multicombine=TRUE) %dopar% unique(t2) 

Wenn Sie eine anständige Menge an seperate Ergebnisse haben zu aggregieren, dies schneller ziemlich viel sein könnte, als nur die Kombination von zwei-at -eine Zeit.

Für eine einzelne foreach-Anweisung führt dies zum gleichen Ergebnis wie foreach default .combine zum Auflisten und Umbrechen mit rbindlist, wie in Eddis erster Lösung. Ich bin mir nicht sicher, was schneller ist, obwohl ich erwarte, dass sie in der Nähe sind.

Für kleine, ein- foreach Jobs, die ich mit rbindlist Einwickeln mag, aber wenn mehrere foreach s zusammen‘Chaining mit %:% ich denke, die oben Ansatz (wahrscheinlich in den ersten foreach) sieht sauberer.

+2

Diese Art der Kombinationsfunktion funktioniert gut mit einem parallelen Backend, das die Kombinationsfunktion on-the-fly aufruft. Dies ermöglicht dem Master, eine Nachbearbeitung parallel zu den Arbeitern durchzuführen. Es ist noch nützlicher, wenn die Kombinationsfunktion eine Reduzierung durchführt. –

+2

Sie können 'rbindlist' auch direkt als" .final "-Funktion mit der Standard-Kombinationsfunktion verwenden, da dies eine Liste erzeugt. Das ist eine sehr saubere Lösung, aber ich würde Ihre Kombinationsfunktion verwenden. –

+1

Ah ich wusste nicht über '.final'! Ich habe ein paar Orte, die sauberer aussehen werden. Was Ihren ersten Kommentar angeht, so habe ich das Paket 'doMPI' verwendet. Es ist wirklich schön, nicht darauf zu warten, dass alle Kinder fertig sind, bevor die Eltern etwas tun, wenn Sie tausende von Einzeljobs haben. – ClaytonJY