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 相当有限:它只能对单个输入做精确匹配。这在 1993 年 R 首次发布时看似合理,但对现代的用法来说就有些不够用了。

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