2016-11-29 3 views
0

Ich versuche eine Schleife in r zu optimieren, die die Anzahl der Zeichenfolgenübereinstimmungen jedes Elements in einem Vektor in Bezug auf jede Zeile in einem Datenrahmen zählt. In kleinen Datensätzen funktioniert es ziemlich gut (~ 15 min; 11 Spalten, 914 Zeilen). Es dauert jedoch Tage, um in riesigen Datensätzen (914 Spalten, 18.000 Zeilen) zu laufen. Hier ist meine sehr einfach Schleife:Schneller r-loop string match (Vektor vs. dat.frame)

for (j in 1: dim(pddbnh)[1]){ 
    for (i in 1:dim(pidf)[1]){ 
    richa[i,j] <- length(pidf[i,][pidf[i,] == row.names(pddbnh)[j] ]) 
    } 
} 

Ich frage mich, ob jemand weiß, wie man diese Schleife mit anderem Ansatz zu optimieren (z Vektorisierung). Jede Lösung würde sehr geschätzt werden!

UPDATE Hier ist ein kleiner Datensatz. Das ist die schnellste

df<-data.frame(replicate(10,sample(c("sp1", "sp2"),10,rep=TRUE))) 
vec<-c("sp1", "sp2") 
richa <- data.frame() 

    for (j in 1:length(vec)){ 
    for (i in 1:dim(df)[1]){ 
    richa[i,j] <- length(df[i,][df[i,] == vec[j] ]) 
    } 
    } 
+1

Ja, ich weiß wahrscheinlich, wie das geht. Bitte geben Sie ein minimales reproduzierbares Beispiel zum Testen an. – Roland

+0

Danke! Hier sind die zwei Dateien: https://www.dropbox.com/s/vvksp7c1kerqjbq/pddbnh.csv?dl=0 https://www.dropbox.com/s/zjt9shku0gjf03t/pidf.csv?dl=0 – CristianR

+0

(Offensichtlich haben Sie noch keine gründliche Suche nach SO gemacht, da es viele Q & A's gibt, um die Performance von for-Schleifen zu verbessern.) Nach '[' to process '[pidf [i,] == row.names (pddbnh) [ j]] würde zum Scheitern verurteilt scheinen. Das Ergebnis dieses Arguments wird entweder 0 oder 1 nach der Nötigung sein (daher sollten Fehler bezüglich der Ersetzung mit der Länge Null auftreten). Vielleicht solltest du erklären, was du eigentlich versuchst. –

Antwort

3

Hier ist ein Verfahren unter Verwendung lapply (siehe unten noch schneller):

richa <- lapply(X = vec, FUN = function(x) rowSums(df == x)) 
richa <- do.call(cbind, richa) 

Eine schnelle microbenchmark auf dem kleinen Datensatz, den Sie haben dies geht hervor, bei etwa 10x schneller als Ihr for Schleifenmethode.

einfach hinzuzufügen, diese leicht multi-threaded für wirklich große Datenmengen als auch sein könnten, entweder parallel::mclapply oder plyr::laply (mit parallel = TRUE) verwendet wird. Es dauert ein wenig mehr Arbeit, aber könnte sich für diese 18000 x 914 Datensätze, die Sie haben, lohnen.

BEARBEITEN HINZUFÜGEN: Da Sie ein paar für Schleifen dorthin gehen (und da ich Rcpp zu lernen, und gerne üben) hier ist eine noch schnellere Lösung mit Rcpp. Hier ist die Funktionsdefinition (die einmal kompiliert werden muss):

Rcpp::cppFunction(' IntegerMatrix charCrossCheck(CharacterMatrix df, 
          CharacterVector vec) { 

       IntegerMatrix output(df.nrow(), vec.size()); 

       for (int j=0; j < vec.size(); ++j){ 
        for (int i=0; i < df.nrow(); ++i){ 
         int count = 0; 
         for(int k=0; k < df.ncol(); k++){ 
          if(df(i,k) == vec[j]) { 
           count++; 
          } 
         } 
         output(i,j) = count; 
        } 
       } 
       return output; 

       } ') 

Dann können Sie diese Funktion aufrufen, mit:

richa <- charCrossCheck(as.matrix(df), vec) 

Rcpp sehr schnell hier. -Micro auf sehr kleine Probe zeigt es mehr als 3x schneller als meine lapply Lösung über und über 38x schneller als for Schleifen in R.

Interessanterweise heraus zu einer df Größe der Eingangsdaten erweitert 4000x4000 und eine vec von Länge 10, vervollständigen die beiden Methoden Rcpp und lapply die Arbeit in sehr ähnlichen Zeiten (3,4 bzw. 3,9 Sekunden). Auf einem Datensatz die Größe, die Sie erwähnen (18000 Zeilen x 914 Spalten, mit vec Länge 2), beide Lösungen sind deutlich unter 1 Sekunde. Nicht schlecht so oder so!

+0

beide Methoden sind ziemlich schneller! Das ist unglaublich und hilft mir sehr. Ich werde versuchen, die Details beider Implementierungen herauszufinden. Ich bin überrascht! – CristianR

+0

@CristianR Großartig! Bitte markieren Sie die Antwort als akzeptiert, wenn es zur Lösung Ihres Problems beigetragen hat. – rosscova