2016-05-22 5 views
1

In R, Ich versuche, eine Zählung Matrix von Elementen innerhalb zahlreicher Datendateien zu erstellen:Leistungsproblem in R

rnames <- c("N","A") 
mymatrix <- matrix(nrow=2,ncol=0,dimnames=list(rnames)) 

#loop through hundreds of large files (MB) 
#make the vector "names" contain all elements within each file 
for(name in names) 
{ 
#if name is already in the matrix increment by 1 the second row 
    if(name %in% colnames(mymatrix)) 
    { 
    mymatrix[2,name] = mymatrix[2,name]+1 
    } 
#else add a column to the matrix with the specified name 
    else 
    { 
    mymatrix <- transform(mymatrix,name) 
    mymatrix[2,name] = 1 
    }  
} 

ich und fand Rprof Befehl ausgeführt wird, dass das Spiel() Funktion wahrscheinlich innerhalb des% eingebettet in% operator ist derjenige, der Leistungsprobleme verursacht (längere Ausführungszeit)

Gibt es eine effizientere Möglichkeit, für jedes Element in einem Vektor zu überprüfen, ob es in meiner Matrix inkrementiert ist, wenn es keine neue Spalte erstellt in der Matrix mit diesem Vektorelement als Spaltenname?

Wenn Sie einen reproduzierbaren Code hier wollen, ist es ... aber bedenken Sie, dass der Name Vektor in meinem Originalcode aus großen Dateien gelesen wird, die Tausende von Variablen enthalten, die mit einer immer steigenden Spaltennummer in mymatrix übereinstimmen führt letztlich zu einer Erhöhung der Laufzeit:

rnames <- c("N","A") 
mymatrix <- matrix(nrow=2,ncol=0,dimnames=list(rnames)) 

#suppose this is what the first file contains 
names <- c("x","y","z","x","x","y","a") 

#suppose this is what the second file contains 
names <- c("x","y","z","x","x","x","x","k") 


    for(name in names) 
    { 
    if(name %in% colnames(mymatrix)) 
    { 
     mymatrix[2,name] = mymatrix[2,name] + 1 
    } 
    else 
    { 
     mymatrix <- transform(mymatrix,name) 
     mymatrix[2,name] = 1 
    } 

    } 


the expected output 
> mymatrix 
    x y z a k 
N NA NA NA NA NA 
A 8 3 2 1 1 
+0

Ich sehe 'Namen' nicht in Ihrem Code. Soll das "Namen" sein? – Gopala

+0

nein, Namen ist ein anderer Vektor, der sich von rnames unterscheidet. Ich habe kommentiert, wie ich diesen Vektor ausfülle, aber wenn Sie den Quellcode haben wollen, kann ich ihn liefern: mydataframe <- readRDS (Datei) Namen <- colnames (mydataframe) – Imlerith

+0

Können Sie ein reproduzierbares Beispiel mit minimaler Eingabe und erwarteter Ausgabe veröffentlichen? Wenn wir den Code nicht ausführen können, ist es schwer, Ihnen zu helfen. – Gopala

Antwort

1

ich weiß nicht, wie man festgestellt, dass match die Engpass war. Es kann sein, aber das Beispiel, das Sie zur Verfügung gestellt haben, zeigt das nicht.

rnames <- c("N","A") 
mymatrix <- matrix(nrow=2, ncol=0, dimnames=list(rnames)) 
set.seed(21) 
names <- sample(letters, 1e6, TRUE) 
Rprof() 
for(name in names) { 
    if(name %in% colnames(mymatrix)) { 
    mymatrix[2,name] <- mymatrix[2,name] + 1 
    } else { 
    mymatrix <- transform(mymatrix,name) 
    mymatrix[2,name] <- 1 
    } 
} 
Rprof(NULL) 

Die nachstehenden Ergebnisse zeigen, dass der Engpass data.frame Methoden sind, die aufgrund Ihrer Nutzung transform genannt werden. transform.default konvertiert Ihre Matrix in einen data.frame und ruft dann transform.data.frame auf, was einen Aufruf an match enthält.

R> lapply(summaryRprof(), head) 
$by.self 
       self.time self.pct total.time total.pct 
"[<-.data.frame"  12.02 26.15  25.90  56.35 
"[.data.frame"  7.22 15.71  13.32  28.98 
"match"    7.20 15.67  11.40  24.80 
"%in%"    2.38  5.18  12.34  26.85 
"anyDuplicated"  2.22  4.83  3.08  6.70 
"names"    2.16  4.70  2.16  4.70 

$by.total 
       total.time total.pct self.time self.pct 
"[<-"     27.06  58.88  1.16  2.52 
"[<-.data.frame"  25.90  56.35  12.02 26.15 
"["     14.32  31.16  1.00  2.18 
"[.data.frame"  13.32  28.98  7.22 15.71 
"%in%"    12.34  26.85  2.38  5.18 
"match"    11.40  24.80  7.20 15.67 

$sample.interval 
[1] 0.02 

$sampling.time 
[1] 45.96 

Vermeiden Sie den transform Anruf und Ihr Code wird deutlich schneller sein. Und mymatrix2 wird tatsächlich eine Matrix sein, während mymatrix ein data.frame ist.

rnames <- c("N","A") 
mymatrix2 <- matrix(nrow=2, ncol=0, dimnames=list(rnames)) 
set.seed(21) 
names <- sample(letters, 1e6, TRUE) 
Rprof() 
for(name in names) { 
    if(name %in% colnames(mymatrix)) { 
    mymatrix2[2,name] <- mymatrix2[2,name] + 1 
    } else { 
    mymatrix2 <- cbind(mymatrix2, matrix(c(NA,1), 2, 1, dimnames=list(rnames, name))) 
    } 
} 
Rprof(NULL) 
lapply(summaryRprof(), head) 
$by.self 
       self.time self.pct total.time total.pct 
"match"    1.28 41.83  2.70  88.24 
"colnames"   0.78 25.49  1.42  46.41 
"is.data.frame"  0.58 18.95  0.58  18.95 
"%in%"    0.34 11.11  3.04  99.35 
"dimnames"   0.06  1.96  0.06  1.96 
"+"     0.02  0.65  0.02  0.65 

$by.total 
       total.time total.pct self.time self.pct 
"%in%"    3.04  99.35  0.34 11.11 
"match"    2.70  88.24  1.28 41.83 
"colnames"   1.42  46.41  0.78 25.49 
"is.data.frame"  0.58  18.95  0.58 18.95 
"dimnames"   0.06  1.96  0.06  1.96 
"+"     0.02  0.65  0.02  0.65 
identical(mymatrix2, as.matrix(mymatrix)) 
[1] TRUE 
+1

danke für Ihre detaillierte Eingabe, bemerkte ich eine Verbesserung von 7,46s auf 0,92 mit cbind anstelle von transformieren, um die Dateien in nur einem Ordner zu verarbeiten. Ich werde es als nächstes auf dem gesamten Datensatz versuchen – Imlerith