0Pricing
R Academy · درس

map2() وpmap() لمدخلات متعددة

كرّر على قائمتين أو أكثر في الوقت نفسه باستخدام map2() وpmap().

map2() وpmap() لمدخلات متعددة درس مجاني في R Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.

التكرار على مدخلات متعددة

تكرّر map() على مدخل واحد في كل مرة. لكن كثيرًا من الدوال تحتاج إلى مدخلين متوازيين أو أكثر. تتعامل map2() في purrr مع مدخلين، بينما تتعامل pmap() مع أي عدد من المدخلات. وتضمن كلتاهما الحفاظ على نوع القيمة المُرجعة.

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() — مدخلان متوازيان

تطبّق map2(.x, .y, .f) الدالة .f(x_i, y_i) على العناصر المتناظرة في .x و.y. يجب أن يكون للمتجهين الطول نفسه، أو أن يكون طول أحدهما 1 فيُعاد استخدامه. وتُرجع الدالة قائمة.

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() مع الصيغة المختصرة ~

تعمل الصيغة المختصرة ~expr مع map2(): يشير .x إلى المدخل الأول، ويشير .y إلى المدخل الثاني. ويساعد ذلك على إبقاء الدوال المجهولة ذات الوسيطين موجزة.

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

المتغيرات ذات الأنواع للدالة map2()

مثل map()، تتضمن map2() متغيرات ذات أنواع لضمان نوع القيم المُرجعة: map2_dbl() وmap2_chr() وmap2_lgl() وmap2_int() وmap2_df(). استخدموا المتغير الذي يطابق نوع المخرجات المتوقعة.

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() — أي عدد من المدخلات

تتلقى pmap(.l, .f) قائمة من المتجهات بوصفها وسيطها الأول. ويمثل كل متجه مسار إدخال منفصلًا. وتتلقى الدالة العناصر المتناظرة من جميع مسارات الإدخال في الوقت نفسه.

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() مع إطار بيانات

إطار البيانات هو قائمة من الأعمدة، لذا يمكنكم تمرير إطار بيانات مباشرةً بوصفه الوسيط الأول إلى pmap(). وتتلقى الدالة قيم صف واحد في صورة وسائط مُسمّاة، مع مطابقة أسماء الأعمدة لأسماء المعاملات.

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)

التكرار على شبكات المعاملات

من الاستخدامات الشائعة لـ pmap() التكرار على شبكة من معاملات النموذج. استخدموا expand.grid() أو tidyr::expand_grid() لإنشاء تركيبات المعاملات، ثم استخدموا pmap() لتشغيل التجربة لكل صف.

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() — إنشاء إطارات بيانات

تطبّق map2_df() (أو map2_dfr()) دالة على مدخلين متوازيين، ثم تربط إطارات البيانات الناتجة صفًا بصف. ويفيد ذلك كثيرًا في مقارنة مجموعتين من العناصر أو دمج مجموعتي بيانات متوازيتين.

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

دمج pmap() مع nest()

يتيح الجمع بين pmap() وإطارات البيانات المتداخلة ومعاملات النموذج نمطًا قويًا: إذ تُخزَّن المعاملات الفائقة والبيانات في إطار بيانات واحد، ثم يُستخدم pmap() على الصفوف لتدريب نماذج باستخدام كل مجموعة من المعاملات.

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)

معالجة الأخطاء باستخدام possibly()

في سيرَي عمل map2()/pmap()، قد يؤدي إدخال واحد غير صالح إلى إيقاف العملية بأكملها. غلّفوا دالتكم باستخدام possibly(fn, otherwise=NA) لاعتراض الأخطاء وإرجاع قيمة افتراضية، مما يبقي المسار قيد التشغيل حتى عند فشل بعض المدخلات.

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)

تطبيق عملي: التحقق المتقاطع باستخدام pmap()

من التطبيقات العملية لـ pmap() إجراء تحقق متقاطع k-fold عبر التكرار على تعيينات الطيات. يمرّر pmap() بيانات التدريب والاختبار الخاصة بكل طية إلى دالة التدريب، ويُرجع مقياس أداء لكل طية.

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

تحقق سريع

ما دالة purrr المناسبة للتكرار على أكثر من متجهَي إدخال متوازيين في الوقت نفسه؟

مراجعة: map2() وpmap()

أهم النقاط حول التكرار على مدخلات متعددة:

  • map2(.x, .y, .f) — تكرّر على مدخلين متوازيين؛ ويُستخدم .x و.y في الصيغة المختصرة ~
  • map2_dbl/chr/lgl/int/df() — متغيرات ذات أنواع لضمان نوع القيم المُرجعة
  • pmap(.l, .f) — تكرّر على قائمة تحتوي أي عدد من المتجهات في الوقت نفسه
  • مرّروا إطار بيانات إلى pmap() — فتصبح أسماء الأعمدة أسماء معاملات الدالة
  • استخدموا expand.grid() + pmap() للبحث في شبكة المعاملات
  • غلّفوا الدوال باستخدام possibly(fn, NA) لمعالجة الأخطاء بأمان
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)
})

الأسئلة الشائعة

هل درس «map2() وpmap() لمدخلات متعددة» مجاني؟

نعم — نص درس «map2() وpmap() لمدخلات متعددة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.

ماذا ستتعلم في «map2() وpmap() لمدخلات متعددة»؟

كرّر على قائمتين أو أكثر في الوقت نفسه باستخدام map2() وpmap(). تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟

لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «map2() وpmap() لمدخلات متعددة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟

نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. map() ومتغيراته ذات الأنواع
  2. map2() وpmap() لمدخلات متعددة
  3. reduce() وaccumulate() وwalk()
  4. keep() وdiscard() وتصفية القوائم
← العودة إلى R Academy