Función lapply en R
La función lapply
forma parte de la familia de funciones apply y permite aplicar una función sobre un vector o una lista, devolviendo una lista. En este tutorial explicaremos cómo usar la función lapply en R con varios ejemplos.
Sintaxis de la función lapply()
La función lapply
aplica una función a una lista o a un vector y devuelve una lista de la misma longitud que el objeto de entrada. La sintaxis de la función es como sigue:
lapply(X, # Lista o vector
FUN, # Función a ser aplicada
...) # Argumentos adicionales para ser pasados a FUN
¿Cómo usar la función lapply en R?
Usar la función lapply
es muy sencillo, tan solo debes pasar la lista o el vector y especificar la función que quieres que se aplique a cada uno de sus elementos.
Iterar sobre una lista
Considera, por ejemplo, la siguiente lista con dos elementos llamados A
y B
.
a <- list(A = c(8, 9, 7, 5),
B = data.frame(x = 1:5, y = c(5, 1, 0, 2, 3)))
a
$A
[1] 8 9 7 5
$B
x y
1 1 5
2 2 1
3 3 0
4 4 2
5 5 3
Si aplicas la función sum
a la lista anterior obtendrás la suma de cada uno de sus elementos (la suma de los elementos del vector y la suma de los elementos del data frame).
lapply(a, sum)
$A
[1] 29
$B
[1] 26
Iterar sobre un vector
Si tienes un vector, la función lapply
aplicará la función que especifiques a cada uno de los elementos del vector. Como ejemplo, considera el vector b
y calcula la raíz cuadrada de cada elemento como se indica en el siguiente bloque de código:
b <- c(12, 18, 6)
lapply(b, sqrt)
[[1]]
[1] 3.464102
[[2]]
[1] 4.242641
[[3]]
[1] 2.44949
Si pasas una lista a lapply
, la función que corresponda se aplicará a todos los elementos de la lista. Si pasas un vector, la función se aplicará a cada elemento del vector.
lapply con argumentos adicionales
Vale la pena mencionar que si la función que estás pasando al argumento FUN
tiene argumentos adicionales puedes establecerlos después de la función, usando una coma, tal y como se muestra en el siguiente ejemplo donde especificamos el argumento probs
de la función quantile
.
c <- list(A = c(56, 12, 57, 24), B = c(89, 12, 64, 18, 65, 76))
lapply(c, # Lista
quantile, # Función aplicada
probs = c(0.25, 0.5, 0.75)) # Argumento adicional de la función quantile
$A
25% 50% 75%
21.00 40.00 56.25
$B
25% 50% 75%
29.50 64.50 73.25
lapply con una función propia
También es posible aplicar una función propia con la función lapply
. Para ese propósito puedes crear una función y pasar su nombre al argumento FUN
o escribir directamente la función dentro de la función lapply
, tal y como se muestra en el siguiente bloque de código:
d <- 1:3
# Función para elevar al cuadrado
fun <- function(x) {
x ^ 2
}
# Aplicamos la función 'fun'
lapply(d, fun)
lapply(d, FUN = function(x) x ^ 2) # Equivalente
lapply(d, function(x) x ^ 2) # Equivalente
[[1]]
[1] 1
[[2]]
[1] 4
[[3]]
[1] 9
lapply vs bucle for
La función lapply
se puede usar para evitar bucles for, que son conocidos por ser lentos en R si no se aplican de forma correcta. Considera que quieres devolver una lista que contenga los números pares de un vector elevados al cubo y los impares elevados a la cuarta potencia. En tal caso podrías escribir:
# Lista vacía de 5 elementos
x <- vector("list", 5)
# Vector
vec <- 1:5
for(i in vec) {
if(i %% 2 == 0) { # Comprobamos si el elemento 'i' es par
x[[i]] <- i ^ 3
} else {
x[[i]] <- i ^ 4
}
}
x
Una alternativa podría ser utilizar la función lapply
de la siguiente manera:
fun <- function(i) {
if(i %% 2 == 0) {
i ^ 3
} else {
i ^ 4
}
}
lapply(vec, fun)
La salida en ambos casos será la misma:
[[1]]
[1] 1 # <- Cuarta potencia de 1
[[2]]
[1] 8 # <- 2 al cubo
[[3]]
[1] 81 # <- Cuarta potencia de 3
[[4]]
[1] 64 # <- 4 al cubo
[[5]]
[1] 625 # <- Cuarta potencia de 5
Tan solo serás capaz de usar la función lapply
en lugar de un bucle for si quieres devolver una lista de la misma longitud que el vector con el que quieres iterar.
lapply vs sapply en R
Las funciones lapply
y sapply
son muy similares, ya que la primera es un wrapper de la segunda. La principal diferencia entre ambas funciones es que lapply
devuelve una lista en lugar de un array. Sin embargo, si estableces simplify = FALSE
en la función sapply
ambas devolverán una lista.
Para aclarar lo anterior, si aplicas la función sqrt
a un vector con la función lapply
obtendrás una lista de la misma longitud del vector, donde cada elemento de la lista es la raíz cuadrada de cada elemento del vector original:
lapply(c(4, 9, 16), FUN = sqrt)
[[1]]
[1] 2
[[2]]
[1] 3
[[3]]
[1] 4
Sin embargo, si usas la función sapply
en su lugar, obtendrás la misma salida pero ésta será un vector.
sapply(c(4, 9, 16), FUN = sqrt)
2 3 4
Recuerda que también puedes devolver una lista con la función sapply
, estableciendo el argumento simplify
como FALSE
o envolviéndola con la función as.list
.
sapply(c(4, 9, 16), FUN = sqrt, simplify = FALSE)
as.list(sapply(c(4, 9, 16), sqrt)) # Equivalente
[[1]]
[1] 2
[[2]]
[1] 3
[[3]]
[1] 4
Análogamente a lo anterior también es posible devolver un vector con la función lapply
usando las funciones unlist
o simplify2array
como sigue:
unlist(lapply(c(4, 9, 16), sqrt))
simplify2array(lapply(c(4, 9, 16), sqrt)) # Equivalente
Más ejemplos de la función lapply en R
lapply en las columnas de un data frame
Supón que tienes un data frame y que quieres multiplicar los elementos de la primera columna por uno, los elementos de la segunda por dos y así sucesivamente.
Por una parte, si quieres realizar el cálculo para todas las columnas puedes escribir:
df <- data.frame(x = c(6, 2), y = c(3, 6), z = c(2, 3))
# Función aplicada a todas las columnas
lapply(1:ncol(df), function(i) df[, i] * i)
[[1]]
[1] 6 2
[[2]]
[1] 6 12
[[3]]
[1] 6 9
Por otra parte, si quieres usar la función lapply
en determinadas columnas del data frame puedes ejecutar:
# Función aplicada a la primera y tercera columna
lapply(c(1, 3), function(i) df[, i] * i)
[[1]]
[1] 6 2
[[2]]
[1] 6 9
Funciones lapply anidadas
En caso de ser necesario también es posible anidar múltiples funciones lapply
. Considera que quieres iterar sobre las columnas y filas de un data frame y aplicar una función a cada celda. Para ese propósito, y suponiendo que quieres multiplicar cada celda por cuatro, puedes escribir algo como lo que sigue:
df <- data.frame(x = c(6, 2), y = c(3, 6))
# Lista vacía de dos elementos
res <- vector("list", 2)
for(i in 1:ncol(df)) {
for (j in 1:nrow(df)) {
res[[j]][i] <- df[j, i] * 4
}
}
res
[[1]] # <- Primera fila por cuatro
[1] 24 12
[[2]] # <- Segunda fila por cuatro
[1] 8 24
Puedes obtener los mismos valores anidando dos funciones lapply
, aplicando un lapply
dentro del argumento FUN
del primero:
lapply(1:ncol(df), function(i) {
unlist(lapply(1:nrow(df), function(j) {
df[j, i] * 4
}))
})
Ten en cuenta que este ejemplo solo es para mostrar que se pueden anidar varios lapply
y tiene solo fines educativos, ya que simplemente podrías escribir df * 4
para obtener los mismos valores que la salida.