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です(これについては「Nothingness」概念で扱います)。

dplyrの関数

base Rのswitchはかなり限定的で、1つの入力に対する完全一致しか行いません。 1993年にRが最初にリリースされた当時は妥当でしたが、現代の使い方には改善が必要です。

Note

Conditionalsの概念でも触れたように、tidyverseのパッケージ群は、後方互換性を損なわずにbase Rの機能を補完する(ときには置き換える)ために設計されています。

tidyverseのパッケージには、優れた現代的なドキュメントもそろっているので、以下のリンクをたどるとより詳しい情報が得られます。

dplyrパッケージは、コードの先頭にlibrary(dplyr)(単体のパッケージを使う場合)かlibrary(tidyverse)(コレクション全体を使う場合)を追加すると利用できるようになります。

dplyrライブラリには、switchに関連する2つの追加関数があります。

recode_values関数とreplace_values関数

この2つのよく似た関数を使うと、switchのようなベクトル化された、古い値から新しい値への対応づけができます。

両者の主な違いは、recode_values()がまったく新しいベクトルを作るのに対し、replace_values()は既存のベクトルの一部だけを更新できる点です。

照合は依然として完全一致ですが、次の点が異なります。

  • 左側のオプションにはベクトルを書くこともでき、いずれかの要素が一致すれば入力が一致したとみなされます。
  • 左側のオプションと右側の結果は、=ではなくチルダ~で結びます。
  • 欠損値NAも明示的に照合できます(これについては「Nothingness」概念で扱います)。
  • どの場合にもデフォルトを指定できます。
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

オンラインでは、ベクトル化されたswitchとしてcase_match()関数を使うというアドバイスを見かけるかもしれません。

この関数はdplyrバージョン1.2.0(2026年2月)で非推奨になりました。 これを使おうとすると警告メッセージが表示され、代わりにrecode_values()を使うよう促されます。

The 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を学習する