2

Verwenden von R auf einem Windows-Rechner, ich bin zur Zeit eine geschachtelte Schleife auf einem 3D-Array läuft (720x360x1368), die zyklisch durch d1 und d2 Funktion über d3 anzuwenden und montieren die Ausgabe in ein neues Array ähnlicher Dimensionalität.parallelisieren verschachtelte Für-Schleife auf 3-dimensionales Array in R

Im folgenden reproduzierbaren Beispiel habe ich die Dimensionen 10, um den Faktor reduziert schneller machen Ausführung.

library(SPEI) 

old.array = array(abs(rnorm(50)), dim=c(72,36,136)) 

new.array = array(dim=c(72,36,136)) 

for (i in 1:72) { 
    for (j in 1:36) { 
    new.listoflists <- spi(ts(old.array[i,j,], freq=12, start=c(1901,1)), 1, na.rm = T) 
    new.array[i,j,] = new.listoflists$fitted 
    } 
} 

wo spi() ist eine Funktion aus dem SPEI Paket eine Liste von Listen der Rückkehr, von denen eine bestimmten Liste $fitted der Länge 1368 von jedem Schleifenschritt verwendet wird, um das neue Array cunstruct.

Während diese Schleife einwandfrei funktioniert, dauert es eine ziemlich lange Zeit zu berechnen. Ich habe gelesen, dass foreach verwendet werden kann, um for Schleifen zu parallelisieren.

Aber ich verstehe nicht, wie die Verschachtelung und die Montage des neuen Arrays können so erreicht werden, dass die dimnames der alten und der neuen Array konsistent sind.

(Am Ende, was ich will in der Lage sein, sowohl die alten und das neue Array in einen „flachen“ langen Panel-Datenrahmen mit as.data.frame.table() und kombinieren sie entlang ihrer drei Dimensionen zu transformieren.)

Jede Hilfe, wie ich die gewünschte Ausgabe mit Hilfe von Parallelverarbeitung erreichen kann, wird sehr geschätzt!

Prost
CubicTom

+0

Ich kann nicht wirklich sagen, was Sie (tun wollen [reproduzierbares Beispiel!] (Http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible- Beispiel)) aber haben Sie sich mit 'apply()' beschäftigt, das über n-dimensionale Arrays verallgemeinerbar ist? Das zweite Argument von apply() definiert die Dimensionen zum Anwenden einer Funktion über z.B.'apply (old.array, 1: 2, FUN = Funktion (x) paste0 (x))', um die Funktion 'paste0()' auf die dritte Dimension Ihres Arrays als Beispiel anzuwenden. –

+0

Danke Simon, ich habe deinen Rat befolgt und mein Beispiel reproduzierbar gemacht. – CubicTom

+0

Ich versuchte auch mit anwenden: 'new2.array <- apply (old.array, 1: 2, FUN = Funktion (x) spi (ts (x, freq = 12, Start = c (1901,1)), 1 , na.rm = T)) ', was sehr schnell ist, aber mir nur eine Matrix mit 72 * 36 = 2592 Elementen gibt, von denen jedes eine Liste von 8 ist. Ich bin nur am zweiten von diesen 8 interessiert ($ angepasst), was eine Liste der gewünschten Funktionswerte ist, die jedem Eintrag entlang d3 entsprechen. – CubicTom

Antwort

0

Es wäre mit einem reproduzierbaren Beispiel besser gewesen, hier ist das, was ich komme mit:

Erstellen Sie zunächst die Cluster Sie

cl <- makeCluster(6, type = "SOCK") 
registerDoSNOW(cl) 

Dann erstellen Sie verwenden Schließen der Schleife und der Cluster:

zz <- foreach(i = 1:720, .combine = c) %:% 
foreach(j = 1:360, .combine = c) %dopar% { 
new.listoflists <- FUN(old.array[i,j,]) 
new.array[i,j,] <- new.listoflists$list 
} 
stopCluster(cl) 

Dadurch wird eine Liste zz jede Iteration von new.array [i, j,], dann können Sie sie binden zusammen mit erstellen enthält:

new.obj <- plyr::ldply(zz, data.frame) 

Hoffnung, dies hilft Ihnen!

+1

Danke, tia_0! Dies hat mir sehr geholfen zu verstehen, wie man for-Schleifen in meinem Fall parallelisiert! Ich erkenne das als die richtige Antwort. Für interessierte Leser: @Simons Antwort in einem Kommentar zu meiner ersten Frage funktioniert auch wie ein Zauber. – CubicTom

0

Ich habe nicht so viel von Dimensionen wie Ihre Frage verwenden, weil ich das Verhalten korrekt war, um sicherzustellen, wollte. Also hier verwende ich Mapply, die mehrere Argumente nehmen. Das Ergebnis ist eine Liste der Ergebnisse. Dann habe ich es mit Matrix() umhüllt, um die erhofften Dimensionen zu bekommen. Bitte beachten Sie, dass i wird unter Verwendung von mal und j wiederholt jeder verwenden. Dies ist kritisch, da matrix() Einträge zuerst nach Zeile einfügt und dann in die nächste Spalte springt, wenn die Anzahl der Zeilen erreicht ist.

new.array = array(1:(5*10*4), dim=c(5,10,4)) 

# FUN: function which returns lists of 
FUN <- function(x){ 
    list(lapply(x, rep, times=3)) 
} 

# result of the computation 
result <- matrix(
    mapply(
     function(i,j,...){ 

      FUN(new.array[i,j,]) 
     } 
     ,i = rep(1:nrow(new.array),times=ncol(new.array)) 
     ,j = rep(1:ncol(new.array),each=nrow(new.array)) 
     ,new.array=new.array 
    ) 
    ,nrow=nrow(new.array) 
    ,ncol=ncol(new.array) 
) 
+0

Danke für Ihre Antwort! Ich habe versucht, Ihren Code zu übernehmen, aber seine Ausführung nach einer Stunde ohne Ergebnis gestoppt: 'new3.array = array (dim = c (72,36,136)) # Ergebnis der Berechnung new3.array <- Matrix ( Mapply ( Funktion (i, j, ...)) { spi (ts (alt.array [i, j,], freq = 12, Anfang = c (1901,1)), 1, na.rm = T) } , ich = rep (1: nrow (alt.array), mal = ncol (old.array)) , j = rep (1: ncol (old.array), jedes = nrow (alt. Array)) , old.array old.array = ) , nRow = nRow (old.array) , NcoI = NcoI (old.array) ) ' Fehle ich hier etwas? – CubicTom