Come è già stato notato, vapplyfa 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 sapplyseguito da stopifnotper 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 vapplyassicurarti che il risultato sia quello previsto. Questo è parallelo a qualcosa su cui stavo lavorando durante lo scraping del PDF, dove findDuserei un fileregexper abbinare un modello in dati di testo non elaborati (ad esempio, avrei un elenco che era splitper 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, sapplyrestituirà 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)
