Muchos problemas de análisis de datos involucran la aplicación de la estrategia divide-aplica-combina, (Hadley Whickam, 2011) esta consiste en romper un problema en pedazos (de acuerdo a una variable de interés), operar sobre cada subconjunto de manera independiente (ej. calcular la media de cada grupo, ordenar observaciones por grupo, estandarizar por grupo) y después unir los pedazos nuevamente. El siguiente diagrama ejemplifiaca el paradigma de divide-aplica-combina:
Bibliografía recomendada: The Slit-Apply-Combine Strategy for Data Analysis, Hadley Wickham 2011.
En esta sección trabajaremos con las siguientes bases de datos para ejemplifcar las funciones de divide-aplica-combina:
flights <- read.csv("Prac_Uni7/ejemplosgenerales/data/flights.csv")
head(flights)
## date hour minute dep arr dep_delay arr_delay carrier
## 1 2011-01-01 12:00:00 14 0 1400 1500 0 -10 AA
## 2 2011-01-02 12:00:00 14 1 1401 1501 1 -9 AA
## 3 2011-01-03 12:00:00 13 52 1352 1502 -8 -8 AA
## 4 2011-01-04 12:00:00 14 3 1403 1513 3 3 AA
## 5 2011-01-05 12:00:00 14 5 1405 1507 5 -3 AA
## 6 2011-01-06 12:00:00 13 59 1359 1503 -1 -7 AA
## flight dest plane cancelled time dist
## 1 428 DFW N576AA 0 40 224
## 2 428 DFW N557AA 0 45 224
## 3 428 DFW N541AA 0 48 224
## 4 428 DFW N403AA 0 39 224
## 5 428 DFW N492AA 0 44 224
## 6 428 DFW N262AA 0 45 224
Cuando pensamos como implementar la estrategia divide-aplica-combina es natural pensar en iteraciones, por ejemplo utilizar un ciclo for para recorrer cada grupo de interés y aplicar las funciones, sin embargo la aplicación de
for loops desemboca en código difícil de entender. Adicionalmente, dplyr es mucho más veloz.
Estudiaremos las siguientes funciones del paquete dplyr
:
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
filter
: obten un subconjunto de las filas de acuerdo a un criterio.select
: selecciona columnas de acuerdo al nombrearrange
: reordena las filasmutate
: agrega nuevas variablessummarise
: reduce variables a valores (crear nuevas bases de datos)Estas funciones trabajan de manera similar, el primer argumento que reciben es un data frame (usualmente en formato limpio), los argumentos que siguen indican que operación se va a efectuar y el resultado es un nuevo data frame.
Veamos con ejemplos.
Ejemplo con base de datos de juguete para mostrar el funcionamiento de cada instrucción:
df_ej <- data.frame(genero= c("mujer", "hombre", "mujer", "mujer", "hombre"),
estatura = c(1.65, 1.80, 1.70, 1.60, 1.67))
df_ej
## genero estatura
## 1 mujer 1.65
## 2 hombre 1.80
## 3 mujer 1.70
## 4 mujer 1.60
## 5 hombre 1.67
dplyr::filter(df_ej, genero == "mujer")
## genero estatura
## 1 mujer 1.65
## 2 mujer 1.70
## 3 mujer 1.60
dplyr::filter(df_ej, estatura > 1.65 & estatura < 1.75)
## genero estatura
## 1 mujer 1.70
## 2 hombre 1.67
Algunos operadores importantes para filtrar son:
x > 1
x >= 1
x < 1
x <= 1
x != 1
x == 1
x %in% ("a", "b")
# Conjuntos
a | b
a & b
a & !b
xor(a, b)
Ejercicio: Encuentra todos los vuelos hacia SFO ó OAK en flights
Elegir columnas de un conjunto de datos.
df_ej
## genero estatura
## 1 mujer 1.65
## 2 hombre 1.80
## 3 mujer 1.70
## 4 mujer 1.60
## 5 hombre 1.67
select(df_ej, genero)
## genero
## 1 mujer
## 2 hombre
## 3 mujer
## 4 mujer
## 5 hombre
select(df_ej, -genero)
## estatura
## 1 1.65
## 2 1.80
## 3 1.70
## 4 1.60
## 5 1.67
select(df_ej, starts_with("g"))
select(df_ej, contains("g"))
arrange
)Arreglar u ordenar de acuerdo al valor de una o más variables:
arrange(df_ej, genero)
## genero estatura
## 1 hombre 1.80
## 2 hombre 1.67
## 3 mujer 1.65
## 4 mujer 1.70
## 5 mujer 1.60
arrange(df_ej, desc(estatura))
## genero estatura
## 1 hombre 1.80
## 2 mujer 1.70
## 3 hombre 1.67
## 4 mujer 1.65
## 5 mujer 1.60
mutate
)Mutar consiste en crear nuevas variables (columnas):
mutate(df_ej, estatura_cm = estatura * 100)
## genero estatura estatura_cm
## 1 mujer 1.65 165
## 2 hombre 1.80 180
## 3 mujer 1.70 170
## 4 mujer 1.60 160
## 5 hombre 1.67 167
mutate(df_ej, estatura_cm = estatura * 100, estatura_in = estatura_cm * 0.3937)
## genero estatura estatura_cm estatura_in
## 1 mujer 1.65 165 64.9605
## 2 hombre 1.80 180 70.8660
## 3 mujer 1.70 170 66.9290
## 4 mujer 1.60 160 62.9920
## 5 hombre 1.67 167 65.7479
Summarise sirve para crear nuevas bases de datos con resúmenes o agregaciones de los datos originales.
summarise(df_ej, promedio = mean(estatura))
## promedio
## 1 1.684
Podemos hacer resúmenes por grupo, primero creamos una base de datos agrupada:
by_genero <- group_by(df_ej, genero)
by_genero
## # A tibble: 5 x 2
## # Groups: genero [2]
## genero estatura
## <fct> <dbl>
## 1 mujer 1.65
## 2 hombre 1.80
## 3 mujer 1.70
## 4 mujer 1.60
## 5 hombre 1.67
y después operamos sobre cada grupo, creando un resumen a nivel grupo y uniendo los subconjuntos en una base nueva:
summarise(by_genero, promedio = mean(estatura))
## # A tibble: 2 x 2
## genero promedio
## <fct> <dbl>
## 1 hombre 1.74
## 2 mujer 1.65
summarise
son min(x), median(x), max(x), quantile(x, p), n(), sum(x), sum(x > 1), mean(x > 1), sd(x).flights$date_only <- as.Date(flights$date)
by_date <- group_by(flights, date_only)
no_miss <- dplyr::filter(by_date, !is.na(dep))
delays <- summarise(no_miss, mean_delay = mean(dep_delay), n = n())
Ejercicio Reescribe el código anterior utilizando %>%