Como ya se ha señalado, vapplyhace dos cosas:
- Mejora leve de la velocidad
- Mejora la coherencia al proporcionar comprobaciones de tipo de devolución limitadas.
El segundo punto es la mayor ventaja, ya que ayuda a detectar errores antes de que sucedan y conduce a un código más robusto. Esta verificación del valor de retorno se puede hacer por separado usando sapplyseguido de stopifnotpara asegurarse de que los valores de retorno sean consistentes con lo que esperaba, pero vapplyes un poco más fácil (si es más limitado, ya que el código de verificación de errores personalizado podría verificar valores dentro de los límites, etc. ).
Este es un ejemplo de vapplycómo garantizar que su resultado sea el esperado. Esto es paralelo a algo en lo que estaba trabajando mientras raspaba PDF, donde findDusaría unregexpara hacer coincidir un patrón en los datos de texto sin procesar (por ejemplo, tendría una lista splitpor entidad y una expresión regular para hacer coincidir las direcciones dentro de cada entidad. Ocasionalmente, el PDF se había convertido fuera de orden y habría dos direcciones para un entidad, que causó maldad).
> 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
Como les digo a mis alumnos, parte de convertirse en programador es cambiar su forma de pensar de "los errores son molestos" a "los errores son mi amigo".
Entradas de longitud cero
Un punto relacionado es que si la longitud de entrada es cero, sapplysiempre devolverá una lista vacía, independientemente del tipo de entrada. Comparar:
sapply(1:5, identity)
sapply(integer(), identity)
vapply(1:5, identity)
vapply(integer(), identity)
Con vapply, tiene la garantía de tener un tipo particular de salida, por lo que no necesita escribir comprobaciones adicionales para entradas de longitud cero.
Benchmarks
vapply puede ser un poco más rápido porque ya sabe en qué formato debería esperar los resultados.
input1.long <- rep(input1,10000)
library(microbenchmark)
m <- microbenchmark(
sapply(input1.long, findD ),
vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx)
autoplot(m)
