sw

switch در R

1 تمرین

درباره‌ی switch

تابع switch() می‌تواند جایگزینی مختصر برای یک سری طولانی از آزمون‌های if ... else if باشد. متغیری که روی آن switch انجام می‌شود معمولاً یک رشته است و در این صورت می‌توان گیومه‌ها را از انتخابگر حذف کرد.

star <- function(type) {
  switch(type,
    M = , # will "fall through" if no value given
    K = "red dwarf",
    G = "Earth-like",
    "bigger star" # only correct for O,B,A,F
  )
}

> star("M")
[1] "red dwarf"

توجه کنید که گزینه‌ها فقط زمانی به گزینه‌ی بعدی عبور می‌کنند که مقدارشان خالی گذاشته شود، همان‌طور که در مثال بالا برای M چنین است. لازم نیست مانند برخی زبان‌های دیگر دستورهای break را بگنجانید.

مقدار نهایی می‌تواند یک مقدار پیش‌فرض باشد، مانند اینجا، یا یک stop() تا در صورتی که قرار است شرط‌ها همه‌ی حالت‌ها را پوشش دهند، خطا پرتاب شود. switch روی یک عدد صحیح کمی متفاوت است: در این حالت پیش‌فرض همیشه NULL است (که در مفهوم نیستی به آن پرداخته خواهد شد).

توابع در dplyr

switch در R پایه نسبتاً محدود است: فقط یک تطابق دقیق با یک ورودی واحد انجام می‌دهد. این در سال ۱۹۹۳ که R برای نخستین بار منتشر شد معقول به نظر می‌رسید، اما برای استفاده‌ی امروزی به بهبود نیاز دارد.

Note

همان‌طور که در مفهوم Conditionals اشاره شد، مجموعه بسته‌های tidyverse طوری طراحی شده است که قابلیت‌های R پایه را تکمیل کند (و گاهی جایگزین آن شود) بدون آنکه سازگاری با نسخه‌های قبلی را تحت تأثیر قرار دهد.

بسته‌های tidyverse همچنین مستندات مدرن و عالی دارند، بنابراین پیگیری پیوندهای زیر جزئیات بیشتری به شما می‌دهد.

می‌توان بسته‌ی dplyr را با افزودن library(dplyr) (برای همان یک بسته) یا library(tidyverse) (برای کل مجموعه) به ابتدای کدتان در دسترس قرار داد.

کتابخانه‌ی dplyr دو تابع اضافی مرتبط با switch ارائه می‌کند.

توابع recode_values و replace_values

این دو تابع مرتبط، امکان نگاشت برداری‌شده‌ای شبیه به switch را از مقادیر قدیمی به مقادیر جدید فراهم می‌کنند.

تفاوت اصلی آن‌ها این است که recode_values() یک بردار کاملاً جدید می‌سازد، در حالی که replace_values() امکان به‌روزرسانی جزئی یک بردار موجود را می‌دهد.

تطابق همچنان دقیق است، اما:

  • گزینه‌های سمت چپ می‌توانند بردار باشند و اگر هر عنصری مطابقت داشته باشد، ورودی مطابقت می‌کند.
  • گزینه‌های سمت چپ و نتایج سمت راست با یک تایلد ~ به جای = به هم مرتبط می‌شوند.
  • مقادیر گمشده‌ی NA را می‌توان به‌صراحت مطابقت داد (که در مفهوم نیستی به آن پرداخته خواهد شد).
  • در همه‌ی حالت‌ها می‌توان یک مقدار پیش‌فرض تعیین کرد.
library(dplyr)

x <- c("a", "b", "a", "d", "b", NA, "c", "e", "z")
recode_values(
  x,
  "a" ~ 1,
  "b" ~ 2,
  "c" ~ 3,
  c("d", "e") ~ 4, # either "d' or "e" will match
  NA ~ 0,          # matches missing values
  default = 100   # note the different syntax for the default
)
#> [1]   1   2   1   4   2   0   3   4 100
Note

شاید آنلاین توصیه‌هایی ببینید درباره‌ی استفاده از تابع case_match() به‌عنوان یک switch برداری.

این تابع در نسخه‌ی ۱.۲.۰ بسته‌ی dplyr (فوریه ۲۰۲۶) منسوخ شد. تلاش برای استفاده از آن اکنون یک پیام هشدار تولید می‌کند که به استفاده از recode_values() به جای آن توصیه می‌کند.

تابع case_when

case_when نحوه‌ی نگارش case_match را یک پله جلوتر می‌برد و اجازه می‌دهد هر عبارت منطقی در سمت چپ ~ قرار بگیرد.

بردار ورودی (x در مثال زیر) به‌عنوان آرگومان داده نمی‌شود؛ فقط باید از قبل تعریف شده باشد.

x <- 1:10
case_when(
  x < 3 ~ "low",
  between(x, 3, 5) ~ "mid",
  between(x, 6, 8) ~ "high",
  .default = "what?"
)
#>  [1] "low"   "low"   "mid"   "mid"   "mid"   "high"  "high"  "high"  "what?" "what?"

تابع between() نیز بخشی از dplyr است.

توابع رشته پیش‌تر بحث شد و عبارات باقاعده موضوع یک مفهوم بعدی خواهد بود. این‌ها با case_when خیلی خوب ترکیب می‌شوند.

library(stringr)

tracks <- "R C Python C# Elixir C++ Odin" |> str_split_1(" ")
tracks
#> [1] "R"      "C"      "Python" "C#"     "Elixir" "C++"    "Odin"  

case_when(
  str_starts(tracks, "C") ~ "C-like",
  str_starts(tracks, "[AEIOU]") ~ "vowel",
  .default = "other"
)
#> [1] "other"  "C-like" "other"  "C-like" "vowel"  "C-like" "vowel"
ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

switch را یاد بگیرید