Come è già stato notato, vapply
fa due cose:
- Leggero miglioramento della velocità
- Migliora la coerenza fornendo controlli limitati del tipo restituito.
Il secondo punto è il vantaggio maggiore, poiché aiuta a rilevare gli errori prima che si verifichino e porta a un codice più robusto. Questo controllo del valore restituito può essere eseguito separatamente utilizzando sapply
seguito da stopifnot
per assicurarsi che i valori restituiti siano coerenti con ciò che ci si aspettava, ma vapply
è un po 'più semplice (se più limitato, poiché il codice di controllo degli errori personalizzato potrebbe verificare i valori entro i limiti, ecc. ).
Ecco un esempio per vapply
assicurarti che il risultato sia quello previsto. Questo è parallelo a qualcosa su cui stavo lavorando durante lo scraping del PDF, dove findD
userei un fileregexper abbinare un modello in dati di testo non elaborati (ad esempio, avrei un elenco che era split
per entità e un'espressione regolare per abbinare gli indirizzi all'interno di ciascuna entità. A volte il PDF era stato convertito fuori ordine e c'erano due indirizzi per un entità, che ha causato cattiveria).
> 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
Come dico ai miei studenti, parte del diventare un programmatore è cambiare la propria mentalità da "gli errori sono fastidiosi" a "gli errori sono miei amici".
Input di lunghezza zero
Un punto correlato è che se la lunghezza di input è zero, sapply
restituirà sempre un elenco vuoto, indipendentemente dal tipo di input. Confrontare:
sapply(1:5, identity)
sapply(integer(), identity)
vapply(1:5, identity)
vapply(integer(), identity)
Con vapply
, si ha la garanzia di avere un particolare tipo di output, quindi non è necessario scrivere controlli aggiuntivi per input di lunghezza zero.
Punti di riferimenti
vapply
può essere un po 'più veloce perché sa già in quale formato dovrebbe aspettarsi i risultati.
input1.long <- rep(input1,10000)
library(microbenchmark)
m <- microbenchmark(
sapply(input1.long, findD ),
vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx)
autoplot(m)