La familia dplyr() no para de crecer.
Allá por junio os explicaba el nuevo miembro de la familia, across() que nos permite aplicar una o varias funciones a más de una columna de forma simultánea.
Hoy os voy a hablar de dos nuevos verbos que se vienen a hacernos un poco más fácil la tarea de manipular datos en R: if_all() and if_any().
Across funcionaba muy bien con los verbos summarise() y mutate(), ambas pensadas para trabajar sobre columnas, pero no se llevaba demasiado bien con filter() pensaba para seleccionar filas.
Los nuevos verbos vienen a suplir esta deficiencia de across().
if_all()
Imaginemos un data frame como el de la siguiente imagen sobre el que queremos quedarnos solo con (filter()) aquellos jugadores (filas) cuya estatura es mayor que la estatura media, cuyo peso es mayor que el peso medio y cuya edad es mayor que la edad media.
Antes de la aparición de if_all() podríamos hacerlo así:
players_sel1 <- players %>%
dplyr::mutate(altMed = mean(altura.cm., na.rm = TRUE),
pesoMed = mean(peso.kg., na.rm = TRUE),
edadMed = mean(edad, na.rm = TRUE)) %>%
dplyr::filter(altura.cm. > altMed & peso.kg. > pesoMed & edad > edadMed)
Con if_all(), primero definimos la función “ser mayor que la media”:
supMedia <- function(x) {
x > mean(x, na.rm = TRUE)
}
y luego filtramos nuestra tabla quedándonos solo con aquellas filas en las que las columnas que nosotros queramos, cumplen la condición (la función que acabamos de definir):
players_sel2 <- players %>%
dplyr::filter(if_all(c(altura.cm., peso.kg., edad), supMedia))
Podríamos refinar un poco más el código, indicando semánticas de selección como, por ejemplo, where(). En este caso, las 3 columnas son las únicas columnas numéricas de mi tabla por lo que puedo sustituir el último pipeline por este:
players_sel3 <- players %>%
dplyr::filter(if_all(where(is.numeric), supMedia))
if_any()
Funcionamiento completamente análogo a if_all() con la diferencia se que el resultado será positivo si se cumple al menos una de las condiciones, esto es, si al menos una de las columnas seleccionadas cumplen la condición.
Imaginemos un data frame como el de la siguiente imagen sobre el que queremos quedarnos solo con (filter()) aquellos jugadores (filas) cuya estatura es mayor que la estatura media o cuyo peso es mayor que el peso medio o cuya edad es mayor que la edad media.
Antes de la aparición de if_any() podríamos hacerlo así:
players_sel4 <- players %>%
dplyr::mutate(altMed = mean(altura.cm., na.rm = TRUE),
pesoMed = mean(peso.kg., na.rm = TRUE),
edadMed = mean(edad, na.rm = TRUE)) %>%
dplyr::filter(altura.cm. > altMed | peso.kg. > pesoMed | edad > edadMed)
Con if_any(), primero definimos la función “ser mayor que la media”:
supMedia <- function(x) {
x > mean(x, na.rm = TRUE)
}
y luego filtramos nuestra tabla quedándonos solo con aquellas filas en las que las columnas que nosotros queramos, cumplen la condición (la función que acabamos de definir):
players_sel5 <- players %>%
dplyr::filter(if_any(c(altura.cm., peso.kg., edad), supMedia))
Podríamos refinar un poco más el código, indicando semánticas de selección como, por ejemplo, where(). En este caso, las 3 columnas son las únicas columnas numéricas de mi tabla por lo que puedo sustituir el último pipeline por este:
players_sel6 <- players %>%
dplyr::filter(if_any(where(is.numeric), supMedia))
¡Bienvenidas al universo tidyverse!
datacy – data driven decisions