Manipulación de Datos con dplyr
## Objetivos de Aprendizaje
- Dominar verbos de dplyr para manipulación de datos
- Usar el operador pipe efectivamente
- Trabajar con datos agrupados
- Manejar múltiples tablas
## Introducción a dplyr
### ¿Qué es dplyr?
dplyr es una gramática de manipulación de datos que proporciona verbos consistentes para:
- Seleccionar columnas
- Filtrar filas
- Ordenar filas
- Crear nuevas columnas
- Resumir datos
### Instalación
```r
install.packages("dplyr")
library(dplyr)
```
## El Operador Pipe
### ¿Qué es %>%?
El operador pipe pasa el lado izquierdo como primer argumento al lado derecho:
```r
# Sin pipe
head(filter(df, edad > 25), 3)
# Con pipe
df %>%
filter(edad > 25) %>%
head(3)
```
### Cómo Funciona
```r
# x %>% f(y) se convierte en f(x, y)
# x %>% f(y) %>% g(z) se convierte en g(f(x, y), z)
# Esto hace el código legible de izquierda a derecha
df %>%
filter(edad > 25) %>%
select(nombre, edad) %>%
arrange(edad)
```
## select() - Elegir Columnas
### Selección Básica
```r
df <- data.frame(
nombre = c("Alicia", "Roberto", "Carlos"),
edad = c(25, 30, 35),
puntuacion = c(95.5, 87.3, 92.1),
grupo = c("A", "B", "A")
)
# Seleccionar columnas específicas
select(df, nombre, edad)
# Excluir columnas
select(df, -puntuacion)
# Excluir múltiples
select(df, -puntuacion, -grupo)
```
### Funciones de Ayuda
```r
# Seleccionar columnas por patrón
select(df, starts_with("a")) # columnas que empiezan con "a"
select(df, ends_with("e")) # columnas que terminan con "e"
select(df, contains("ou")) # columnas que contienen "ou"
# Seleccionar columnas por tipo
select_if(df, is.numeric)
# Renombrar durante selección
select(df, nombre_completo = nombre, edad)
```
## filter() - Elegir Filas
### Filtrado Básico
```r
# Condición única
filter(df, edad > 28)
# Múltiples condiciones (AND)
filter(df, edad > 28 & puntuacion > 90)
filter(df, edad > 28, puntuacion > 90) # Igual que arriba
# Condición OR
filter(df, edad < 25 | edad > 32)
# Condición NOT
filter(df, !edad > 28)
filter(df, edad <= 28)
```
### Operadores de Comparación
```r
# == Igual
filter(df, grupo == "A")
# != No igual
filter(df, grupo != "A")
# >, >=, <, <=
filter(df, puntuacion >= 90)
# %in% para múltiples coincidencias
filter(df, nombre %in% c("Alicia", "Roberto"))
# between para rango
filter(df, between(edad, 25, 32)) # edad >= 25 & edad <= 32
```
### Filtrar con NA
```r
# Filas donde edad es NA
filter(df, is.na(edad))
# Filas donde edad NO es NA
filter(df, !is.na(edad))
```
## arrange() - Ordenar Filas
### Ordenamiento Básico
```r
# Orden ascendente
arrange(df, edad)
# Orden descendente
arrange(df, desc(edad))
# Múltiples columnas
arrange(df, grupo, edad)
# Grupo primero, luego descendente
arrange(df, grupo, desc(edad))
```
## mutate() - Agregar Columnas
### Mutación Básica
```r
# Agregar nueva columna
mutate(df, promedio_puntuacion = puntuacion / 10)
# Múltiples mutaciones
mutate(df,
promedio_puntuacion = puntuacion / 10,
aprobado = puntuacion > 60
)
```
### Funciones Comunes
```r
# Sumas acumuladas
mutate(df, suma_edad = cumsum(edad))
# Lag y lead
mutate(df,
edad_anterior = lag(edad),
edad_siguiente = lead(edad)
)
# Rango
mutate(df, rango = rank(desc(puntuacion)))
# Promedios móviles
mutate(df, promedio_movil = (edad + lag(edad) + lead(edad)) / 3)
```
### If-else en mutate
```r
mutate(df,
calificacion = case_when(
puntuacion >= 90 ~ "A",
puntuacion >= 80 ~ "B",
puntuacion >= 70 ~ "C",
TRUE ~ "F"
)
)
```
## transmute() - Crear y Reemplazar
```r
# transmute mantiene solo las columnas nuevas
transmute(df,
nombre,
promedio_puntuacion = puntuacion / 10
)
```
## summarize() - Agregar
### Resumen Básico
```r
summarize(df,
edad_media = mean(edad),
puntuacion_max = max(puntuacion),
conteo = n()
)
```
### Funciones de Resumen
```r
# n() - contar filas
summarize(df, n())
# n_distinct() - contar únicos
summarize(df, n_grupo = n_distinct(grupo))
# sum(), mean(), median(), sd(), var()
summarize(df,
total = sum(puntuacion),
promedio = mean(puntuacion)
)
# min(), max(), first(), last()
summarize(df,
mas_joven = min(edad),
mas_viejo = max(edad)
)
# cuantiles
summarize(df, q25 = quantile(puntuacion, 0.25))
```
## group_by() - Agrupar Datos
### Agrupamiento Básico
```r
df <- data.frame(
grupo = c("A", "A", "B", "B", "A"),
nombre = c("Alicia", "Roberto", "Carlos", "Diana", "Eva"),
puntuacion = c(95, 87, 92, 88, 90)
)
# Agrupar por columna única
df %>%
group_by(grupo) %>%
summarize(puntuacion_media = mean(puntuacion))
# Agrupar por múltiples columnas
df %>%
group_by(grupo, nombre) %>%
summarize(puntuacion_media = mean(puntuacion))
```
### Operaciones Agrupadas
```r
# Agregar estadísticas de grupo
df %>%
group_by(grupo) %>%
mutate(media_grupo = mean(puntuacion)) %>%
select(nombre, puntuacion, media_grupo)
# Filtrar dentro de grupos
df %>%
group_by(grupo) %>%
filter(puntuacion == max(puntuacion))
```
### Desagrupar
```r
df %>%
group_by(grupo) %>%
ungroup() %>%
mutate(media_general = mean(puntuacion))
```
## count() - Conteo Rápido
```r
# Contar por grupo
count(df, grupo)
# Contar con orden
count(df, grupo, sort = TRUE)
# Contar con múltiples grupos
count(df, grupo, nombre)
```
## distinct() - Filas Únicas
```r
# Eliminar duplicados
distinct(df)
# Por columnas específicas
distinct(df, grupo, .keep_all = TRUE)
# Contar únicos
distinct(df, grupo) %>% nrow()
# o
n_distinct(df$grupo)
```
## joins - Combinar Tablas
### Tipos de Uniones
```r
# Dataframes de ejemplo
df1 <- data.frame(
id = c(1, 2, 3),
nombre = c("Alicia", "Roberto", "Carlos")
)
df2 <- data.frame(
id = c(2, 3, 4),
puntuacion = c(87, 92, 88)
)
```
### Unión Interna
```r
# Mantener solo filas coincidentes
inner_join(df1, df2, by = "id")
# id nombre puntuacion
# 2 Roberto 87
# 3 Carlos 92
```
### Unión Izquierda
```r
# Mantener todo de df1
left_join(df1, df2, by = "id")
# id nombre puntuacion
# 1 Alicia NA
# 2 Roberto 87
# 3 Carlos 92
```
### Unión Derecha
```r
# Mantener todo de df2
right_join(df1, df2, by = "id")
# id nombre puntuacion
# 2 Roberto 87
# 3 Carlos 92
# 4 88
```
### Unión Completa
```r
# Mantener todo de ambos
full_join(df1, df2, by = "id")
```
### Otras Uniones
```r
# Semi unión - mantener filas de df1 que coinciden en df2
semi_join(df1, df2, by = "id")
# Anti unión - mantener filas de df1 que NO coinciden
anti_join(df1, df2, by = "id")
```
## across() - Múltiples Columnas
### Aplicar a Múltiples Columnas
```r
# Aplicar función a todas las columnas numéricas
df %>%
summarise(across(where(is.numeric), mean))
# Aplicar a columnas específicas
df %>%
summarise(across(c(edad, puntuacion), mean))
# Con nombres
df %>%
summarise(across(c(edad, puntuacion),
list(media = mean, sd = sd)))
```
### en filter() y mutate()
```r
# Filtrar donde cualquier columna numérica > 50
df %>% filter(across(where(is.numeric), ~ .x > 50))
# Mutar múltiples columnas
df %>% mutate(across(edad:puntuacion, ~ .x * 2))
```
## rowwise() - Operaciones por Fila
```r
# Operaciones por fila
df <- data.frame(
a = c(1, 2, 3),
b = c(4, 5, 6)
)
df %>%
rowwise() %>%
mutate(suma = sum(a, b))
```
## Case When
```r
# Múltiples condiciones
df %>%
mutate(calificacion = case_when(
puntuacion >= 90 ~ "A",
puntuacion >= 80 ~ "B",
puntuacion >= 70 ~ "C",
puntuacion >= 60 ~ "D",
TRUE ~ "F"
))
```
## Resumen
- Usar `%>%` pipe para flujo de código legible
- `select()` elige columnas, `filter()` elige filas
- `arrange()` ordena, `mutate()` crea/transforma columnas
- `summarize()` agrega, `group_by()` habilita operaciones de grupo
- `count()` conteo rápido, `distinct()` valores únicos
- Funciones `join` combinan tablas: inner, left, right, full
- `across()` aplica funciones a múltiples columnas
- `rowwise()` para operaciones por fila
- `case_when()` para múltiples condiciones if-else
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →