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中的函式

base R 中的 switch相當有限:它只能對單一輸入做完全相符的比對。 R 在 1993 年首次發布時,這樣的設計看似合理,但以現代用途來說需要改良。

Note

如同 Conditionals概念中提到的,tidyverse套件集合的設計目的,是在不影響向後相容性的前提下補充(有時甚至取代)base R 的功能。

tidyverse 套件也有很出色、很現代的說明文件,所以點擊下面的連結可以了解更多細節。

只要在程式碼開頭加上 library(dplyr)(載入單一套件)或 library(tidyverse)(載入整個集合),就能把 dplyr套件納入作用域。

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 1.2.0 版(2026 年 2 月)中棄用。 現在嘗試使用它會產生警告訊息,建議改用 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