Wie bereits erwähnt, werden vapply
zwei Dinge ausgeführt:
- Leichte Geschwindigkeitsverbesserung
- Verbessert die Konsistenz durch begrenzte Überprüfung der Rückgabetypen.
Der zweite Punkt ist der größere Vorteil, da er hilft, Fehler zu erkennen, bevor sie auftreten, und zu robusterem Code führt. Diese Rückgabewertprüfung kann separat durchgeführt werden, indem sapply
gefolgt von verwendet wird stopifnot
, um sicherzustellen, dass die Rückgabewerte mit Ihren Erwartungen übereinstimmen. Sie ist jedoch vapply
etwas einfacher (wenn sie eingeschränkter sind, da der benutzerdefinierte Fehlerprüfcode nach Werten innerhalb von Grenzen usw. suchen kann). ).
Hier ist ein Beispiel, wie Sie vapply
sicherstellen können, dass Ihr Ergebnis den Erwartungen entspricht. Dies entspricht etwas, an dem ich gerade beim PDF-Scraping gearbeitet habe, wo findD
einRegexZum Abgleichen eines Musters in Rohtextdaten (z. B. hätte ich eine Liste split
nach Entitäten und einen regulären Ausdruck zum Abgleichen von Adressen innerhalb jeder Entität. Gelegentlich wurde das PDF nicht in der richtigen Reihenfolge konvertiert, und es gab zwei Adressen für eine Entität Entität, die Schlechtigkeit verursachte).
> input1 <- list( letters[1:5], letters[3:12], letters[c(5,2,4,7,1)] )
> input2 <- list( letters[1:5], letters[3:12], letters[c(2,5,4,7,15,4)] )
> findD <- function(x) x[x=="d"]
> sapply(input1, findD )
[1] "d" "d" "d"
> sapply(input2, findD )
[[1]]
[1] "d"
[[2]]
[1] "d"
[[3]]
[1] "d" "d"
> vapply(input1, findD, "" )
[1] "d" "d" "d"
> vapply(input2, findD, "" )
Error in vapply(input2, findD, "") : values must be length 1,
but FUN(X[[3]]) result is length 2
Wie ich meinen Schülern erzähle, besteht ein Teil des Werdens eines Programmierers darin, Ihre Einstellung von "Fehler sind ärgerlich" zu "Fehler sind mein Freund" zu ändern.
Eingaben
mit der Länge Null Ein verwandter Punkt ist, dass bei einer Eingangslänge von Null sapply
unabhängig vom Eingabetyp immer eine leere Liste zurückgegeben wird. Vergleichen Sie:
sapply(1:5, identity)
## [1] 1 2 3 4 5
sapply(integer(), identity)
## list()
vapply(1:5, identity)
## [1] 1 2 3 4 5
vapply(integer(), identity)
## integer(0)
Mit vapply
haben Sie garantiert einen bestimmten Ausgabetyp, sodass Sie keine zusätzlichen Prüfungen für Eingaben mit der Länge Null schreiben müssen.
Benchmarks
vapply
kann etwas schneller sein, da es bereits weiß, in welchem Format die Ergebnisse erwartet werden sollen.
input1.long <- rep(input1,10000)
library(microbenchmark)
m <- microbenchmark(
sapply(input1.long, findD ),
vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx) # autoplot.microbenchmark is moving to the microbenchmark package in the next release so this should be unnecessary soon
autoplot(m)