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が最初にリリースされた当時は妥当でしたが、現代の使い方には改善が必要です。
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
オンラインでは、ベクトル化されたswitchとしてcase_match()関数を使うというアドバイスを見かけるかもしれません。
この関数は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"