map2() i pmap() dla wielu danych wejściowych
Iteruj jednocześnie po dwóch lub większej liczbie list za pomocą map2() i pmap().
map2() i pmap() dla wielu danych wejściowych to bezpłatna lekcja R Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.
Iterowanie po wielu danych wejściowych
map() iteruje za każdym razem po jednym argumencie wejściowym. Wiele funkcji wymaga jednak dwóch lub większej liczby równoległych danych wejściowych. purrr udostępnia map2() do obsługi dwóch danych wejściowych oraz pmap() do obsługi dowolnej ich liczby. Obie funkcje zapewniają zwracanie wartości o bezpiecznym, określonym typie.
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() — dwa równoległe dane wejściowe
map2(.x, .y, .f) stosuje .f(x_i, y_i) do odpowiadających sobie elementów .x i .y. Oba wektory muszą mieć tę samą długość (albo jeden z nich musi mieć długość 1 i podlegać recyklingowi). Funkcja zwraca listę.
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() ze skrótem ~
Skrócona składnia formuły ~expr działa również z map2(): .x oznacza pierwsze dane wejściowe, a .y — drugie. Dzięki temu anonimowe funkcje z dwoma argumentami pozostają zwięzłe.
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, ']'))Typowane warianty map2()
Podobnie jak map(), map2() ma typowane warianty zapewniające bezpieczny typ zwracanej wartości: map2_dbl(), map2_chr(), map2_lgl(), map2_int() i map2_df(). Należy użyć wariantu odpowiadającego oczekiwanemu typowi wyniku.
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() — dowolna liczba danych wejściowych
pmap(.l, .f) przyjmuje jako pierwszy argument listę wektorów. Każdy wektor jest osobnym strumieniem danych wejściowych. Funkcja otrzymuje jednocześnie odpowiadające sobie elementy ze wszystkich strumieni.
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() z ramką danych
Ramka danych jest listą kolumn, dlatego można przekazać ją bezpośrednio jako pierwszy argument do pmap(). Funkcja otrzymuje wartości jednego wiersza jako nazwane argumenty, a nazwy kolumn są dopasowywane do nazw parametrów.
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)Iterowanie po siatkach parametrów
Częste zastosowanie pmap() to iterowanie po siatce parametrów modelu. Należy użyć expand.grid() lub tidyr::expand_grid(), aby utworzyć kombinacje parametrów, a następnie pmap(), aby uruchomić eksperyment dla każdego wiersza.
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() — tworzenie ramek danych
map2_df() (lub map2_dfr()) stosuje funkcję do dwóch równoległych danych wejściowych, a następnie łączy wynikowe ramki danych wierszami. Jest to przydatne podczas porównywania dwóch zbiorów elementów lub scalania równoległych zbiorów danych.
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')Łączenie pmap() z nest()
Połączenie pmap() ze zagnieżdżonymi ramkami danych i parametrami modelu umożliwia zastosowanie użytecznego wzorca: należy przechowywać hiperparametry i dane w jednej ramce danych, a następnie użyć pmap() po wierszach, aby dopasować modele dla każdego zestawu parametrów.
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)Obsługa błędów za pomocą possibly()
W potokach z map2()/pmap() jeden nieprawidłowy argument może przerwać całą operację. Należy opakować funkcję za pomocą possibly(fn, otherwise=NA), aby przechwytywać błędy i zwracać wartość domyślną. Dzięki temu potok działa dalej, nawet gdy niektóre dane wejściowe powodują błędy.
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)W praktyce: walidacja krzyżowa z pmap()
Praktyczne zastosowanie pmap(): wykonanie walidacji krzyżowej k-fold przez iterowanie po przypisaniach do podzbiorów. pmap() przekazuje dane treningowe i testowe każdego podzbioru do funkcji dopasowującej, zwracając miarę jakości dla każdego podzbioru.
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))Szybkie sprawdzenie
Która funkcja purrr jest odpowiednia do jednoczesnego iterowania po więcej niż dwóch równoległych wektorach danych wejściowych?
Podsumowanie: map2() i pmap()
Najważniejsze informacje o mapowaniu z wieloma danymi wejściowymi:
map2(.x, .y, .f)— iteruje po dwóch równoległych danych wejściowych; w skrócie~używa.xi.ymap2_dbl/chr/lgl/int/df()— typowane warianty zapewniające bezpieczny typ zwracanej wartościpmap(.l, .f)— jednocześnie iteruje po liście zawierającej dowolną liczbę wektorów- Przekazanie ramki danych do
pmap()— nazwy kolumn stają się nazwami parametrów funkcji - Użycie
expand.grid()+pmap()do przeszukiwania siatki parametrów - Opakowanie funkcji za pomocą
possibly(fn, NA)w celu bezpiecznej obsługi błędów
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)
})Często zadawane pytania
Czy lekcja „map2() i pmap() dla wielu danych wejściowych” jest bezpłatna?
Tak — pełny tekst „map2() i pmap() dla wielu danych wejściowych” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „map2() i pmap() dla wielu danych wejściowych”?
Iteruj jednocześnie po dwóch lub większej liczbie list za pomocą map2() i pmap(). Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć R Academy?
Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „map2() i pmap() dla wielu danych wejściowych”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?
Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- map() i warianty typowane
- map2() i pmap() dla wielu danych wejściowych
- reduce(), accumulate() i walk()
- keep(), discard() i filtrowanie list