0Pricing
R Academy · Lección

map2() y pmap() para varias entradas

Itere simultáneamente sobre dos o más listas con map2() y pmap().

map2() y pmap() para varias entradas es una lección gratuita de R Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de R Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de R Academy incluye 4 lecciones en total.

Iteración sobre varias entradas

map() itera sobre una entrada cada vez. Sin embargo, muchas funciones necesitan dos o más entradas paralelas. map2() de purrr gestiona dos entradas, mientras que pmap() gestiona cualquier cantidad. Ambas mantienen la misma garantía de devolver un valor de tipo seguro.

library(purrr)

# Simulate: add corresponding elements from two vectors
x <- c(1, 2, 3, 4)
y <- c(10, 20, 30, 40)

# map2 applies fn(x[i], y[i]) for each i
result <- map2(x, y, function(a, b) a + b)
print(result)

map2() — Dos entradas paralelas

map2(.x, .y, .f) aplica .f(x_i, y_i) a los elementos correspondientes de .x y .y. Ambos vectores deben tener la misma longitud (o uno de ellos debe tener longitud 1 y reutilizarse). Devuelve una lista.

library(purrr)

names_vec <- c('Alice','Bob','Carol')
scores_vec <- c(85, 92, 78)

# Build a personalized message for each student
map2_chr(names_vec, scores_vec,
         ~paste(.x, 'scored', .y, 'points'))

map2() con la notación abreviada ~

La notación basada en fórmulas ~expr funciona con map2(): .x hace referencia a la primera entrada y .y a la segunda. Esto permite mantener concisas las funciones anónimas de dos argumentos.

library(purrr)

lower_bounds <- c(0, 10, 20, 50)
upper_bounds <- c(9, 19, 49, 100)

# Create labels for each range
map2_chr(lower_bounds, upper_bounds,
         ~paste0('[', .x, '-', .y, ']'))

Variantes tipadas de map2()

Al igual que map(), map2() cuenta con variantes tipadas para devolver valores de tipo seguro: map2_dbl(), map2_chr(), map2_lgl(), map2_int() y map2_df(). Use la variante que corresponda al tipo de salida esperado.

library(purrr)

actual <- c(100, 150, 200, 120)
target <- c(110, 140, 195, 130)

# Numeric: percentage achievement
map2_dbl(actual, target, ~round(100 * .x / .y, 1))

# Logical: did they meet their target?
map2_lgl(actual, target, ~.x >= .y)

pmap() — Cualquier cantidad de entradas

pmap(.l, .f) recibe una lista de vectores como primer argumento. Cada vector es un flujo de entrada independiente. La función recibe simultáneamente los elementos correspondientes de todos los flujos de entrada.

library(purrr)

# Three parallel inputs
params <- list(
  name = c('Alice','Bob','Carol'),
  score = c(85, 92, 78),
  grade = c('B','A','C')
)

pmap_chr(params, function(name, score, grade) {
  paste(name, ':', score, '(', grade, ')')
})

pmap() con un data frame

Un data frame es una lista de columnas, por lo que puede pasarlo directamente como primer argumento de pmap(). La función recibe los valores de una fila como argumentos con nombre, haciendo coincidir los nombres de las columnas con los nombres de los parámetros.

library(purrr)

params_df <- data.frame(
  mean_val = c(0, 5, 10),
  sd_val = c(1, 2, 3),
  n = c(100, 50, 200)
)

# Generate samples from different normal distributions
set.seed(42)
results <- pmap(params_df, function(mean_val, sd_val, n) {
  rnorm(n, mean=mean_val, sd=sd_val)
})

map_dbl(results, mean)

Iteración sobre cuadrículas de parámetros

Un uso habitual de pmap() es iterar sobre una cuadrícula de parámetros de un modelo. Use expand.grid() o tidyr::expand_grid() para crear las combinaciones de parámetros y, después, pmap() para ejecutar el experimento con cada fila.

library(purrr)

# Create a parameter grid
grid <- expand.grid(
  learning_rate = c(0.01, 0.1),
  epochs = c(10, 50),
  batch_size = c(32, 64)
)

# Simulate model training results
set.seed(42)
grid$accuracy <- pmap_dbl(grid, function(learning_rate, epochs, batch_size) {
  base <- 0.5 + 0.3 * log10(epochs) + 0.1 * learning_rate
  round(min(base + rnorm(1, 0, 0.02), 0.99), 3)
})

print(grid[order(-grid$accuracy),])

map2_df() — Creación de data frames

map2_df() (o map2_dfr()) aplica una función a dos entradas paralelas y combina por filas los data frames resultantes. Es una herramienta muy útil para comparar dos conjuntos de elementos o combinar conjuntos de datos paralelos.

library(purrr)

q1_sales <- list(East=100, West=200, North=80)
q2_sales <- list(East=120, West=190, North=95)

map2_df(q1_sales, q2_sales, function(q1, q2) {
  data.frame(
    q1 = q1,
    q2 = q2,
    change = q2 - q1,
    pct = round(100*(q2-q1)/q1, 1)
  )
}, .id = 'region')

Combinación de pmap() con nest()

Combinar pmap() con data frames anidados y parámetros de modelos permite aplicar un patrón muy potente: almacenar los hiperparámetros y los datos en un único data frame y, después, usar pmap() sobre las filas para ajustar modelos con cada conjunto de parámetros.

library(purrr)
library(dplyr)

# Simulate polynomial regression with different degrees
set.seed(42)
x <- 1:20
y <- 2*x + 0.5*x^2 + rnorm(20, 0, 10)
df <- data.frame(x=x, y=y)

configs <- data.frame(degree = 1:3)
configs$r2 <- map_dbl(configs$degree, function(d) {
  m <- lm(y ~ poly(x, d), data=df)
  summary(m)$r.squared
})

print(configs)

Gestión de errores con possibly()

En los flujos de trabajo con map2()/pmap(), una entrada incorrecta puede interrumpir toda la operación. Envuelva la función con possibly(fn, otherwise=NA) para capturar los errores y devolver un valor predeterminado, de modo que el pipeline continúe aunque algunas entradas fallen.

library(purrr)

safe_log <- possibly(log, otherwise=NA_real_)

values <- list(10, -5, 100, 0, 50)

# Without possibly(): log() warns for negative numbers
# With possibly(): errors return NA, computation continues
map_dbl(values, safe_log)

Práctica: validación cruzada con pmap()

Una aplicación práctica de pmap() es realizar una validación cruzada de k particiones iterando sobre las asignaciones de las particiones. pmap() envía los datos de entrenamiento y de prueba de cada partición a la función de ajuste y devuelve una métrica de rendimiento por partición.

library(purrr)

set.seed(42)
df <- data.frame(x=1:20, y=2*(1:20)+rnorm(20,0,3))
df$fold <- sample(rep(1:5, 4))

# Compute RMSE for each held-out fold
folds <- 1:5
rmse_vals <- map_dbl(folds, function(k) {
  train <- df[df$fold != k, ]
  test <- df[df$fold == k, ]
  m <- lm(y ~ x, data=train)
  preds <- predict(m, newdata=test)
  sqrt(mean((test$y - preds)^2))
})

cat('Per-fold RMSE:', round(rmse_vals, 2), '\n')
cat('Mean RMSE:', round(mean(rmse_vals), 2))

Comprobación rápida

¿Qué función de purrr es adecuada para iterar simultáneamente sobre más de dos vectores de entrada paralelos?

Recapitulación: map2() y pmap()

Conceptos clave del mapeo con varias entradas:

  • map2(.x, .y, .f) — itera sobre dos entradas paralelas; .x y .y en la notación abreviada con ~
  • map2_dbl/chr/lgl/int/df() — variantes tipadas para devolver valores de tipo seguro
  • pmap(.l, .f) — itera simultáneamente sobre una lista con cualquier cantidad de vectores
  • Pase un data frame a pmap() — los nombres de las columnas se convierten en nombres de parámetros de la función
  • Use expand.grid() + pmap() para buscar en una cuadrícula de parámetros
  • Envuelva las funciones con possibly(fn, NA) para gestionar los errores de forma segura
library(purrr)

# pmap with a data frame: each row = one function call
params <- data.frame(
  mean_val = c(0, 10, 100),
  sd_val = c(1, 5, 20),
  label = c('control','mid','high')
)

pmap_chr(params, function(mean_val, sd_val, label) {
  sprintf('%s: mean=%.0f, sd=%.0f', label, mean_val, sd_val)
})

Preguntas frecuentes

¿La lección «map2() y pmap() para varias entradas» es gratis?

Sí — el texto completo de «map2() y pmap() para varias entradas» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de R Academy, actualiza a CoddyKit PRO. El curso de R Academy incluye 4 lecciones en total.

¿Qué aprenderé en «map2() y pmap() para varias entradas»?

Itere simultáneamente sobre dos o más listas con map2() y pmap(). Practicas R Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar R Academy?

No se requiere experiencia previa. R Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «map2() y pmap() para varias entradas»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de R Academy?

Sí. Cada lección de R Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. map() y variantes tipadas
  2. map2() y pmap() para varias entradas
  3. reduce(), accumulate() y walk()
  4. keep(), discard() y filtrado de listas
← Volver a R Academy