apply en R
Las funciones de la familia apply en R son un conjunto bien conocido de funciones vectorizadas de R que permiten realizar tareas complejas sobre arrays evitando el uso de bucles for. En este tutorial, aprenderás cómo usar apply
en R a través de varios ejemplos y casos de uso.
La función apply en R
El comando apply en R permite aplicar una función a través de una matriz, array o data frame. Puedes hacer esto de varias maneras, dependiendo de cómo configures el argumento MARGIN
, que habitualmente puede tomar los valores 1
, 2
o c(1, 2)
.
apply(X, # Array, matriz o data frame
MARGIN, # 1: filas, 2: columnas, c(1, 2): filas y columnas
FUN, # Función a ser aplicada
...) # Argumentos adicionales para ser pasados a FUN
A través de este tutorial usaremos los siguientes datos de ejemplo, así que asegúrate de tenerlos cargados en tu espacio de trabajo. Ten en cuenta que vamos a utilizar un data frame, pero también podríamos haber elegido una matriz o un array en su lugar.
# Data frame
df <- data.frame(x = 1:4, y = 5:8, z = 10:13)
df
x y z
1 5 10
2 6 11
3 7 12
4 8 13
MARGIN = 1
aplica la función a las filas mientras que MARGIN = 2
aplica la función a las columnas.
Aplicar función a cada fila
Puedes aplicar una función a cada fila de un array pasando un 1 como parámetro al argumento MARGIN
. Para este primer ejemplo, vamos a aplicar la función sum
a las filas del data frame de ejemplo.
# Suma por filas
apply(X = df, MARGIN = 1, FUN = sum)
Ten en cuenta que al usar esta función es habitual no especificar los nombres de los argumentos debido a la simplicidad de la función, pero recuerda el orden de los argumentos.
# Suma por filas
apply(df, 1, sum)
16 19 22 25
También puedes aplicar la función a índices o datos específicos, creando un subconjunto de los datos que quieras de tu data frame.
# Suma por filas de un subconjunto de los datos
apply(df[c(1, 2), ], 1, sum)
16 19
Ten en cuenta que la salida es un vector que contiene la suma correspondiente de cada fila.
Aplicar función a cada columna
Estableciendo MARGIN = 2
, la función se aplicará a cada columna del array con el que estés trabajando.
# Suma por columnas
apply(df, 2, sum)
x y z
10 26 46
En este caso, la salida es un vector que contiene la suma de cada columna del data frame de muestra. También puedes aplicar la función a columnas específicas si las indicas.
# Suma por columnas a un subconjunto de los datos
apply(df[, c(1, 3)], 2, sum)
x z
10 46
Cabe destacar que esto es más eficiente que aplicar la función a todo el data frame si luego quieres quedarte con un subconjunto de los datos originales.
Los ejemplos anteriores son para fines educativos. Es más eficiente usar las funciones colSums
y rowSums
para calcular la suma de columnas y filas, respectivamente.
Aplicar función a todo el data frame
Puedes establecer el argumento MARGIN
como c(1, 2)
o equivalentemente como 1:2
para aplicar la función a cada valor del data frame.
apply(df, c(1, 2), sum)
x y z
[1, ] 1 5 10
[2, ] 2 6 11
[3, ] 3 7 12
[4, ] 4 8 13
Si pones MARGIN = c(2, 1)
en lugar de c(1, 2)
la salida será la misma matriz, pero traspuesta.
apply(df, c(2, 1), sum)
[, 1] [, 2] [, 3] [, 4]
x 1 2 3 4
y 5 6 7 8
z 10 11 12 13
El output es de clase “matrix” en lugar de “data.frame”.
Nótese que en este caso los elementos de la salida son los elementos del data frame en sí, ya que se está calculando la suma de cada celda individual.
En la sección donde explicamos cómo usar funciones propias con la función apply
mostraremos un ejemplo donde aplicar por filas y columnas es lo mismo que aplicar la función por columnas y otro donde las salidas son diferentes en todos los casos, con el objetivo de comprender mejor el propósito de aplicar una función sobre filas y columnas al mismo tiempo.
Argumentos adicionales de la función apply
La función mean
tiene un argumento adicional (na.rm
) para especificar si se eliminan los valores de tipo NA
o no. Si necesitas especificar argumentos de la función que estás aplicando, puedes pasarlos separados por comas de la siguiente manera:
# Media por filas eliminando NA
apply(df, 1, mean, na.rm = TRUE)
Apply en R con una función propia
La función que pases al argumento FUN
no necesita ser una función de R base. Puedes aplicar una función de R incluso si es una función propia. En este ejemplo, crearemos una función llamada fun
que calcula el cuadrado de un número y convertiremos la salida a carácter si el argumento character
se establece como TRUE
.
fun <- function(x, character = FALSE) {
if (character == FALSE) {
x ^ 2
} else {
as.character(x ^2)
}
}
Primero, si aplicas la función por filas, la salida será una matriz que contiene el cuadrado de los elementos por fila.
apply(df, 1, fun)
[, 1] [, 2] [, 3] [, 4]
x 1 4 9 16
y 25 36 49 64
z 100 121 144 169
Si especificas character = TRUE
, cada elemento de la matriz se convertirá a tipo carácter.
apply(df, 1, fun, character = TRUE)
[, 1] [, 2] [, 3] [, 4]
[1, ] "1" "4" "9" "16"
[2, ] "25" "36" "49" "64"
[3, ] "100" "121" "144" "169"
En segundo lugar, si aplicas la función por columnas, obtendrás el siguiente resultado, que corresponde a la matriz traspuesta de la que obtuviste al aplicar la función por filas.
apply(df, 2, fun)
x y z
[1, ] 1 25 100
[2, ] 4 36 121
[3, ] 9 49 144
[4, ] 16 64 169
Por último, si aplicas la función a cada celda, obtendrás el siguiente resultado:
apply(df, c(1, 2), fun)
x y z
[1, ] 1 25 100
[2, ] 4 36 121
[3, ] 9 49 144
[4, ] 16 64 169
Nótese que, en este caso, aplicar la función por filas y columnas es lo mismo que aplicar la función por columnas, porque la función está calculando la suma de cada elemento individual, es decir, el elemento en sí. A continuación mostraremos un ejemplo donde las tres salidas son diferentes. Considera, como ejemplo, la siguiente función:
f <- function(x) sum(exp(x))
Esta función calcula la suma de la exponencial de un número o vector. Entonces, si aplicas la función por filas, obtendrás lo siguiente:
apply(df, 1, f)
22177.60 60284.96 163871.51 445448.95
Por ejemplo, el primer elemento de la salida (22177.60) se puede obtener con: sum(exp(1) + exp(5) + exp(10))
. Ahora, si aplicas la función por columnas, la salida será completamente diferente.
apply(df, 2, f)
x y z
84.79102 4629.43310 687068.79094
Finalmente, si aplicas la función por filas y columnas, la salida será una matriz que contiene el exponencial de cada elemento.
apply(df, 1:2, f)
x y z
[1, ] 2.718282 148.4132 22026.47
[2, ] 7.389056 403.4288 59874.14
[3, ] 20.085537 1096.6332 162754.79
[4, ] 54.598150 2980.9580 442413.39
Ejemplos adicionales de la función apply() en R
A continuación se muestran más ejemplos de uso de la función apply
en R, incluido uno en el que se aplica una función a un array multidimensional.
apply(df, 2, min) # Valores mínimos por columna
apply(df, 2, range) # Rango (valores mínimos y máximos) por columna
apply(df, 1, summary) # Resumen por fila
apply(df, 2, summary) # Resumen por columna
# Aplicando la función sum a un array multidimensional
ar <- array(data = 1:18, dim = c(3, 2, 3))
apply(ar, 3, sum) # <- El argumento MARGIN = 3
La última línea devuelve la suma de todas las componentes de cada elemento del array.