La documentación dice
vapplyes similar asapply, pero tiene un tipo de valor de retorno preespecificado, por lo que puede ser más seguro [...] de usar.
¿Podría explicar por qué en general es más seguro, quizás proporcionando ejemplos?
PD: Sé la respuesta y ya tiendo a evitarla sapply. Solo desearía que hubiera una buena respuesta aquí en SO para poder señalarla a mis compañeros de trabajo. Por favor, no responda "lea el manual".

Respuestas:
Como ya se ha señalado,
vapplyhace dos cosas: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 destopifnotpara asegurarse de que los valores de retorno sean consistentes con lo que esperaba, perovapplyes 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, dondefindDusaría unregexpara hacer coincidir un patrón en los datos de texto sin procesar (por ejemplo, tendría una listasplitpor 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 2Como 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) ## [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)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
vapplypuede 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.microbenchmark is moving to the microbenchmark package in the next release so this should be unnecessary soon autoplot(m)fuente
Las pulsaciones de teclas adicionales involucradas
vapplypodrían ahorrarle tiempo al depurar resultados confusos más adelante. Si la función a la que está llamando puede devolver diferentes tipos de datos,vapplyciertamente debería usarse.Un ejemplo que me viene a la mente estaría
sqlQueryen elRODBCpaquete. Si hay un error al ejecutar una consulta, esta función devuelve uncharactervector con el mensaje. Entonces, por ejemplo, digamos que está tratando de iterar sobre un vector de nombres de tablastnamesy seleccione el valor máximo de la columna numérica 'NumCol' en cada tabla con:sapply(tnames, function(tname) sqlQuery(cnxn, paste("SELECT MAX(NumCol) FROM", tname))[[1]])Si todos los nombres de las tablas son válidos, esto resultaría en un
numericvector. Pero si uno de los nombres de las tablas cambia en la base de datos y la consulta falla, los resultados se convertirán en modocharacter. Sin embargo, usarvapplyconFUN.VALUE=numeric(1)detendrá el error aquí y evitará que aparezca en algún lugar de la línea, o peor aún, no en absoluto.fuente
Si siempre quiere que su resultado sea algo en particular ... por ejemplo, un vector lógico.
vapplyse asegura de que esto suceda, perosapplyno necesariamente.a<-vapply(NULL, is.factor, FUN.VALUE=logical(1)) b<-sapply(NULL, is.factor) is.logical(a) is.logical(b)fuente
logical(1)en este caso, ya que FALSE parece que establece una opción en "OFF" en lugar de especificar un tipo