apply(), lapply() y sapply() en R: repetir sin bucles
La familia apply sirve para aplicar una función a muchos elementos de golpe, sin escribir un bucle for. Son tres funciones que hacen casi lo mismo → la diferencia está en sobre qué trabajan y qué te devuelven.
La diferencia, en una tabla
| Función | Trabaja sobre | Devuelve |
|---|---|---|
apply() |
filas o columnas de una matriz o data frame | vector o matriz |
lapply() |
elementos de una lista o vector | siempre una lista |
sapply() |
igual que lapply | vector, si puede simplificarlo |
Ejemplo simple
sapply() es la que más vas a usar, porque devuelve algo cómodo de leer:
notas <- list(mates = c(7, 8, 9), lengua = c(5, 6, 7))
sapply(notas, mean)
Devuelve un vector con nombres: mates 8, lengua 6. Directo.
La misma llamada con lapply() devolvería una lista, más incómoda de mirar pero más segura cuando los resultados no son todos del mismo tipo:
lapply(notas, mean)
apply(): por filas o por columnas
Esta lleva un argumento más, el MARGIN, que indica la dirección: 1 = filas, 2 = columnas.
tabla <- matrix(1:12, nrow = 3)
apply(tabla, 1, sum) # suma cada fila
apply(tabla, 2, sum) # suma cada columna
Una regla para recordarlo: 1 es lo primero que se dice al describir una matriz ("filas por columnas"), así que 1 = filas.
Ejemplo algo más completo: resumir un data frame
El caso real más frecuente: sacar un estadístico de todas las columnas numéricas, como la mean() o la sd().
datos <- data.frame(
edad = c(25, 32, 47, 51),
altura = c(170, 165, 180, 175),
peso = c(65, 59, 82, 78)
)
sapply(datos, mean)
sapply(datos, sd)
Y si quieres varias medidas a la vez, le pasas una función propia:
sapply(datos, function(x) c(media = mean(x), maximo = max(x)))
Ahí function(x) define una función anónima, que se usa solo en ese momento y no hace falta guardar con nombre.
Ojo con una cosa: si el data frame tiene columnas de texto, sapply(datos, mean) te devolverá avisos y NA. Filtra antes las numéricas:
numericas <- datos[, sapply(datos, is.numeric)]
sapply(numericas, mean)
¿Y los bucles for? Funcionan perfectamente y no tienen nada de malo. Pero con sapply() escribes una línea en vez de cuatro, y no te tienes que preocupar de crear el vector de resultados antes ni de ir rellenándolo.