Capítulo26 Iteración: purrr
El tema proviene de los siguientes sitios.
English: https://r4ds.had.co.nz/iteration.html
Español: https://es.r4ds.hadley.nz/iteración.html
Fecha de la última revisión
## [1] "2026-07-29"
26.1 Temas: El paquete purrr
- La idea de iterar (repetir una acción)
- El bucle
forde base R - La familia
map()depurrr - Fórmulas anónimas con
~y.x - Iterar sobre dos listas con
map2() - Un modelo por grupo
purrr es parte de tidyverse, así que se activa con library(tidyverse).
26.2 ¿Qué es iterar?
Iterar es repetir la misma acción sobre cada elemento de una lista, vector o columna. Igual que con las funciones, la meta es no repetir código. Si las funciones evitan copiar y pegar código dentro de una tarea, la iteración evita copiar y pegar la misma tarea muchas veces.
Supón que queremos la mediana de cada columna de este data frame:
df <- tibble(
a = rnorm(10),
b = rnorm(10),
c = rnorm(10),
d = rnorm(10)
)
# Repetir a mano es tedioso y propenso a errores:
median(df$a)## [1] -0.2364174
## [1] 0.2332814
## [1] 1.136037
## [1] 0.4082237
26.3 El bucle for de base R
La forma clásica de iterar es con un bucle for:
resultado <- vector("double", ncol(df)) # espacio para guardar la salida
for (i in seq_along(df)) { # para cada columna
resultado[[i]] <- median(df[[i]]) # calcular y guardar
}
resultado## [1] -0.2364174 0.2332814 1.1360375 0.4082237
Funciona, pero hay que escribir bastante “andamiaje” (crear el vector de salida,
manejar el índice i). purrr simplifica esto.
26.4 La familia map()
Las funciones map() toman un vector o lista, aplican una función a cada
elemento, y devuelven un resultado. Hay una versión por tipo de salida:
map()devuelve una listamap_dbl()devuelve un vector de doblesmap_int()devuelve un vector de enterosmap_chr()devuelve un vector de textomap_lgl()devuelve un vector lógico
## a b c d
## -0.2364174 0.2332814 1.1360375 0.4082237
## a b c d
## -0.3534311 0.1467468 1.0998756 0.2888905
## a b c d
## 0.9753734 0.8503055 0.5548967 1.0877976
Compara: el bucle for completo de arriba se reduce a map_dbl(df, median).
26.5 Fórmulas anónimas con ~ y .x
A veces necesitas una pequeña operación que no tiene nombre de función. Puedes
escribirla como una fórmula empezando con ~, y usar .x para representar
“el elemento actual”.
## a b c d
## 3.042304 2.203092 1.832097 3.338961
## a b c d
## 3 5 10 6
Esto es muy útil con datos reales. Por ejemplo, el promedio de atraso de salida por mes en los vuelos:
vuelos %>%
split(.$mes) %>% # una lista: un data frame por mes
map_dbl(~ mean(.x$atraso_salida, na.rm = TRUE)) # promedio de atraso por mes## 1 2 3 4 5 6 7 8
## 10.036665 10.816843 13.227076 13.938038 12.986859 20.846332 21.727787 12.611040
## 9 10 11 12
## 6.722476 6.243988 5.435362 16.576688
26.6 Iterar sobre dos listas con map2()
Cuando necesitas recorrer dos listas en paralelo, usa map2(). Los elementos
se representan con .x (de la primera) y .y (de la segunda).
medias <- c(0, 10, 100)
desv <- c(1, 2, 3)
# Generar 5 números al azar de cada combinación de media y desviación
map2(medias, desv, ~ rnorm(5, mean = .x, sd = .y))## [[1]]
## [1] 1.01720062 -0.45401384 1.11807753 0.02410736 -0.30014527
##
## [[2]]
## [1] 13.09959 10.12764 10.11323 9.00243 10.06829
##
## [[3]]
## [1] 99.31260 99.88415 98.67224 100.17103 103.52231
26.7 Un modelo por grupo
Un uso poderoso es ajustar un modelo por grupo. Aquí ajustamos una regresión del atraso de llegada contra el de salida, por separado para cada aerolínea.
Nota: como el paquete
mapstambién se carga en este libro, escribimospurrr::map()de forma explícita para no confundirla conmaps::map().
modelos <- vuelos %>%
split(.$aerolinea) %>%
purrr::map(~ lm(atraso_llegada ~ atraso_salida, data = .x))
# Ver el R^2 de cada modelo
modelos %>%
purrr::map(summary) %>%
map_dbl("r.squared") %>%
head()## 9E AA AS B6 DL EV
## 0.8622935 0.7952061 0.7012039 0.8369837 0.8192728 0.9080101
Este patrón —dividir, aplicar un modelo a cada parte, y resumir— es la base del
tema de muchos modelos con purrr y broom.
- Ejercicios:
Hacer los ejercicios en la sección 21.5 del libro en español.
- Ejercicios:
Usa map_dbl() para calcular el número de valores únicos (n_distinct()) en cada
columna del data frame diamantes.
- Ejercicios:
Hacer los ejercicios en la sección 21.9 del libro en español.