Frage

Bei der Erstellung von Funktionen, dass die Verwendung strsplit, Vektoreingaben verhalten sich nicht wie gewünscht, und sapply Bedürfnisse verwendet werden. Dies ist auf die Liste ausgegeben, dass strsplit erzeugt. Gibt es eine Möglichkeit, den Prozess zu vektorisieren - das ist, erzeugt die Funktion das richtige Element in der Liste für jedes der Elemente des Eingangs

?

Um zum Beispiel die Längen der Wörter in einem Zeichenvektor zu zählen:

words <- c("a","quick","brown","fox")

> length(strsplit(words,""))
[1] 4 # The number of words (length of the list)

> length(strsplit(words,"")[[1]])
[1] 1 # The length of the first word only

> sapply(words,function (x) length(strsplit(x,"")[[1]]))
a quick brown   fox 
1     5     5     3 
# Success, but potentially very slow

Im Idealfall, so etwas wie length(strsplit(words,"")[[.]]) wo . als sein dem entsprechenden Teil des Eingangsvektors interpretiert wird.

War es hilfreich?

Lösung

In der Regel sollten Sie versuchen, eine vektorisiert Funktion zu verwenden, um mit zu beginnen. strsplit verwendet, wird häufig eine Art von Iteration erfordert danach (die langsamer sein wird), so versuchen Sie es zu vermeiden, wenn möglich. In Ihrem Beispiel sollten Sie nchar statt:

> nchar(words)
[1] 1 5 5 3

Generell nehmen sich die Tatsache zunutze, dass strsplit eine Liste und Verwendung lapply zurückgibt:

> as.numeric(lapply(strsplit(words,""), length))
[1] 1 5 5 3

Oder Gebrauch eine l*ply Familie Funktion von plyr. Zum Beispiel:

> laply(strsplit(words,""), length)
[1] 1 5 5 3

Edit:

Zu Ehren Bloomsday , entschied ich mich, die Leistung zu testen diese Ansätze Joyces Ulysses mit:

joyce <- readLines("http://www.gutenberg.org/files/4300/4300-8.txt")
joyce <- unlist(strsplit(joyce, " "))

Nun, da ich alle Worte haben, können wir unsere Zählungen tun:

> # original version
> system.time(print(summary(sapply(joyce, function (x) length(strsplit(x,"")[[1]])))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
   2.65    0.03    2.73 
> # vectorized function
> system.time(print(summary(nchar(joyce))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
   0.05    0.00    0.04 
> # with lapply
> system.time(print(summary(as.numeric(lapply(strsplit(joyce,""), length)))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
    0.8     0.0     0.8 
> # with laply (from plyr)
> system.time(print(summary(laply(strsplit(joyce,""), length))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
  17.20    0.05   17.30
> # with ldply (from plyr)
> system.time(print(summary(ldply(strsplit(joyce,""), length))))
       V1        
 Min.   : 0.000  
 1st Qu.: 3.000  
 Median : 4.000  
 Mean   : 4.666  
 3rd Qu.: 6.000  
 Max.   :69.000  
   user  system elapsed 
   7.97    0.00    8.03 

Die vektorisiert Funktion und lapply ist wesentlich schneller als die ursprüngliche Version sapply. Alle Lösungen geben die gleiche Antwort (wie sie in der Zusammenfassung Ausgabe zu sehen ist).

Anscheinend ist die neueste Version von plyr ist schneller (Dies ist eine etwas ältere Version verwenden).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top