Encadenar operaciones en dplyr
En esta nueva entrada, vas a aprender a encadenar operaciones en dplyr
utilizando el operador %>%
de magrittr
y cómo esto es particularmente útil para calcular estadísticas por categorías.
Relacionado: TUTORIAL: Data wrangling en R con dplyr y tidyr - Parte 1
Al igual que en la entrada anterior, utilizo el conjunto de datos iris
que ya viene cargado en R.
Requisitos
- Tener instalado R y
dplyr
- Saber qué es una función y qué son los argumentos de una función en R
- Las ganas de aprender
Recomendado
- Utilizar RStudio
- Saber construir expresiones lógicas
Calcular la media, la desviación estándar u otras funciones resumen de una o más variables
Problema: Calcular estadísticas como el total, la media, percentiles, etc.
Solución: Utilizar el verbo summarise
(resumir) junto con la función apropiada.
El primer argumento de la función summarise
es el data.frame
; el resto, son funciones resumen (summary functions). Las funciones resumen son aquellas que toman varios valores y devuelven un sólo valor, como por ejemplo la media, la desviación estándar o los percentiles.
iris <- as_tibble(iris) # Esto no es estrictamente necesario, pero es recomendable
summarise(iris,
n = n(), # Devuelve el número de filas del conjunto de datos
Sepal.Width.Mean = mean(Sepal.Width),
Sepal.Width.Sd = sd(Sepal.Width),
Sepal.Width.Q1 = quantile(Sepal.Width, .25),
Sepal.Width.Q2 = quantile(Sepal.Width, .50),
Sepal.Width.Q3 = quantile(Sepal.Width, .75),
Sepal.Length.Mean = mean(Sepal.Length),
Sepal.Length.Sd = sd(Sepal.Length))
## # A tibble: 1 x 8
## n Sepal.Width.Mean Sepal.Width.Sd Sepal.Width.Q1 Sepal.Width.Q2
## <int> <dbl> <dbl> <dbl> <dbl>
## 1 150 3.06 0.436 2.8 3
## # … with 3 more variables: Sepal.Width.Q3 <dbl>, Sepal.Length.Mean <dbl>,
## # Sepal.Length.Sd <dbl>
Nota: la función n
sirve para contar cuántas filas tiene un conjunto de datos.
Los nombres de los argumentos son los nombres de las columnas resultantes. Si no lo haces, las columnas del resultado tendrían nombres horribles como sd(Sepal.Width)
. Aunque no es obligatorio, es útil que las columnas tengan un nombre apropiado para utilizarlo después.
Calcular estadísticas por grupo
Problema: Calcular estadísticas por grupo
Solución: Utilizar el verbo group_by
(agrupar por) junto con el verbo summarise
Vamos a calcular las mismas estadísticas del caso anterior, pero ahora para cada una de las categorías de Species
. Para esto, vamos a decirle a R que queremos la tabla iris
agrupada según esa variable y luego utilizamos summarise
.
summarise(
group_by(
iris,
Species
),
n = n(),
Sepal.Width.Mean = mean(Sepal.Width),
Sepal.Width.Sd = sd(Sepal.Width),
Sepal.Width.Q1 = quantile(Sepal.Width, .25),
Sepal.Width.Q2 = quantile(Sepal.Width, .50),
Sepal.Width.Q3 = quantile(Sepal.Width, .75),
Sepal.Length.Mean = mean(Sepal.Length),
Sepal.Length.Sd = sd(Sepal.Length)
)
## # A tibble: 3 x 9
## Species n Sepal.Width.Mean Sepal.Width.Sd Sepal.Width.Q1
## <fct> <int> <dbl> <dbl> <dbl>
## 1 setosa 50 3.43 0.379 3.2
## 2 versic… 50 2.77 0.314 2.52
## 3 virgin… 50 2.97 0.322 2.8
## # … with 4 more variables: Sepal.Width.Q2 <dbl>, Sepal.Width.Q3 <dbl>,
## # Sepal.Length.Mean <dbl>, Sepal.Length.Sd <dbl>
Encadenar operaciones utilizando el operador %>%
Problema: No anidar las funciones para que el código sea más legible
Solución: Encadenar operaciones utilizando el operador %>%
En el ejemplo anterior tuvimos que anidar las funciones summarise
y group_by
. Esto lo podemos evitar de la siguiente manera
iris %>%
group_by(Species) %>%
summarise(
Sepal.Width.Mean = mean(Sepal.Width),
Sepal.Length.Mean = mean(Sepal.Length)
)
## # A tibble: 3 x 3
## Species Sepal.Width.Mean Sepal.Length.Mean
## <fct> <dbl> <dbl>
## 1 setosa 3.43 5.01
## 2 versicolor 2.77 5.94
## 3 virginica 2.97 6.59
Esto lo podríamos leer de la siguiente manera
Toma la tabla
iris
, luego agrupa porSpecies
, y luego calcula la media deSepal.Width
y deSepal.Length
.
Por supuesto, leerlo en inglés es mejor porque todo queda en un sólo idioma
Take the table
iris
, then group bySpecies
, and then calculate the mean ofSepal.Width
and the mean ofSepal.Length
.
Una vez que tienes este resultado, puedes seguir encadenando operaciones sobre la tabla. Por ejemplo, si quieres sólo las categorías donde Sepal.Width.Mean
sea menor que 3, y luego ordenarlas de mayor a menor según Sepal.Length.Mean
el código sería el siguiente:
iris %>%
group_by(Species) %>%
summarise(
Sepal.Width.Mean = mean(Sepal.Width),
Sepal.Length.Mean = mean(Sepal.Length)
) %>%
filter(Sepal.Width.Mean < 3) %>%
arrange(desc(Sepal.Length.Mean))
## # A tibble: 2 x 3
## Species Sepal.Width.Mean Sepal.Length.Mean
## <fct> <dbl> <dbl>
## 1 virginica 2.97 6.59
## 2 versicolor 2.77 5.94
Aquí se ve la utilidad de darle nombre a las columnas resultantes: para utilizarlas en operaciones consecutivas.
¡Pensar en hacer esto mismo anidando funciones da dolor de cabeza! Mientras que un código anidado se lee de adentro hacia afuera, un código encadenado por el operador %>% se lee de arriba hacia abajo. Para más información sobre cómo funciona el operador %>%
sigue el tutorial de magrittr.
Un truco importante: Puedes escribir rápidamente %>%
en RStudio pulsando CTRL + ALT + M
en windows y linux, y CMD + shift + M
en Mac, lo cual es mucho más cómodo que escribirlo directamente.
Conclusión
Utilizar el operador %>%
junto con dplyr
mantiene el código bastante legible. Ya que las funciones de dplyr
son verbos, puedes leer el operador %>%
como luego y cada verbo como una orden, de manera que el código se lea como Toma la tabla tal y luego haz esto, luego haz lo otro, luego… y así. En la próxima parte, te enseño a combinar mutate
con funciones de resumen y group_by
para hacer cálculos de fila por grupos.