0Pricing
R Academy · Lezione

map2() e pmap() per input multipli

Iteri simultaneamente su due o più liste con map2() e pmap().

map2() e pmap() per input multipli è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.

Iterare su più input

map() esegue l'iterazione su un input alla volta. Tuttavia, molte funzioni richiedono due o più input paralleli. map2() di purrr gestisce due input, mentre pmap() ne gestisce un numero qualsiasi. Entrambe garantiscono valori restituiti dello stesso tipo previsto.

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() — Due input paralleli

map2(.x, .y, .f) applica .f(x_i, y_i) agli elementi corrispondenti di .x e .y. I due vettori devono avere la stessa lunghezza, oppure uno dei due deve avere lunghezza 1 ed essere riciclato. Restituisce 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 sintassi abbreviata ~

La sintassi abbreviata basata sulle formule ~expr funziona anche con map2(): .x fa riferimento al primo input e .y al secondo. In questo modo le funzioni anonime con due argomenti rimangono concise.

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, ']'))

Varianti tipizzate di map2()

Come map(), anche map2() dispone di varianti tipizzate che garantiscono il tipo restituito: map2_dbl(), map2_chr(), map2_lgl(), map2_int() e map2_df(). Utilizzi la variante corrispondente al tipo di output previsto.

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() — Un numero qualsiasi di input

pmap(.l, .f) riceve come primo argomento una lista di vettori. Ogni vettore rappresenta un flusso di input distinto. La funzione riceve contemporaneamente gli elementi corrispondenti di tutti i flussi di input.

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 è una lista di colonne, quindi è possibile passarlo direttamente come primo argomento a pmap(). La funzione riceve i valori di una riga come argomenti denominati, associando i nomi delle colonne ai nomi dei parametri.

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)

Iterare su griglie di parametri

Un uso comune di pmap() consiste nell'iterare su una griglia di parametri di un modello. Utilizzi expand.grid() o tidyr::expand_grid() per creare le combinazioni di parametri, quindi pmap() per eseguire l'esperimento su ogni riga.

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() — Creare data frame

map2_df() (o map2_dfr()) applica una funzione a due input paralleli e concatena per righe i data frame risultanti. È particolarmente utile per confrontare due insiemi di elementi o unire dataset paralleli.

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')

Combinare pmap() con nest()

L'abbinamento di pmap() con data frame annidati e parametri del modello consente di adottare un modello molto efficace: memorizzare iperparametri e dati in un unico data frame, quindi usare pmap() sulle righe per adattare modelli con ogni insieme di parametri.

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)

Gestire gli errori con possibly()

Nei flussi di lavoro con map2()/pmap(), un solo input errato può interrompere l'intera operazione. Racchiuda la funzione in possibly(fn, otherwise=NA) per intercettare gli errori e restituire un valore predefinito, mantenendo attiva la pipeline anche quando alcuni input non vanno a buon fine.

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)

Pratica: convalida incrociata con pmap()

Un'applicazione pratica di pmap() consiste nell'eseguire una convalida incrociata k-fold iterando sulle assegnazioni dei fold. pmap() passa i dati di addestramento e di test di ciascun fold alla funzione di adattamento e restituisce una metrica delle prestazioni per ogni fold.

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))

Verifica rapida

Quale funzione di purrr è appropriata per iterare simultaneamente su più di due vettori di input paralleli?

Riepilogo: map2() e pmap()

Punti chiave sull'iterazione con più input:

  • map2(.x, .y, .f) — esegue l'iterazione su due input paralleli; nella sintassi ~, .x e .y vi fanno riferimento
  • map2_dbl/chr/lgl/int/df() — varianti tipizzate per garantire il tipo restituito
  • pmap(.l, .f) — esegue simultaneamente l'iterazione su una lista contenente un numero qualsiasi di vettori
  • Passando un data frame a pmap(), i nomi delle colonne diventano i nomi dei parametri della funzione
  • Utilizzi expand.grid() + pmap() per una ricerca su una griglia di parametri
  • Racchiuda le funzioni in possibly(fn, NA) per gestire gli errori in modo sicuro
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)
})

Domande Frequenti

La lezione «map2() e pmap() per input multipli» è gratuita?

Sì — il testo completo di «map2() e pmap() per input multipli» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.

Cosa imparerò in «map2() e pmap() per input multipli»?

Iteri simultaneamente su due o più liste con map2() e pmap(). Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare R Academy?

Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «map2() e pmap() per input multipli»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione R Academy?

Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. map() e varianti tipizzate
  2. map2() e pmap() per input multipli
  3. reduce(), accumulate() e walk()
  4. keep(), discard() e filtraggio delle liste
← Torna a R Academy