127  実践 case_when

library(tidyverse)

if_elseはTRUE/FALSEをかえす2条件のみで結果を場合分けしますが、case_whenは複数条件で条件分岐ができます。

スライドでお示ししたように、<ロジカルとなる式> ~ <返したい結果>を繰り返すことで好きな条件で結果を返せます。

実験してみましょう。

dat <- tibble(num = c(1:5))
dat
# A tibble: 5 × 1
    num
  <int>
1     1
2     2
3     3
4     4
5     5
dat %>% 
  mutate(kekka = case_when(
    num == 1 ~ "one",
    num == 2 ~ "two",
    num == 3 ~ "three",
    TRUE ~ ">3"
  ))
# A tibble: 5 × 2
    num kekka
  <int> <chr>
1     1 one  
2     2 two  
3     3 three
4     4 >3   
5     5 >3   

この例では、num列が1であればone、2であればtwo、3であればthree、それ以外で>3という文字列を返す結果になっています

case_whenで注意しておかないといけないことはif_elseと同様でcase_when関数が返す結果の型をそろえておくことです。

dat %>% 
  mutate(kekka = case_when(
    num == 1 ~ "one",
    num == 2 ~ "two",
    num == 3 ~ 3,
    TRUE ~ ">3"
  ))
Error in `mutate()`:
ℹ In argument: `kekka = case_when(...)`.
Caused by error in `case_when()`:
! Can't combine `..1 (right)` <character> and `..3 (right)` <double>.

もう一つ、実行される順番に注意が必要です。case_when関数は上の条件が優先されます。

dat %>% 
  mutate(kekka = case_when(
    num == 1 ~ "one",
    num == 1 ~ "two",
    num == 1 ~ "three",
    TRUE ~ ">3"
  ))
# A tibble: 5 × 2
    num kekka
  <int> <chr>
1     1 one  
2     2 >3   
3     3 >3   
4     4 >3   
5     5 >3   

また、最後のTRUEという「必ず当たる」条件を書いておかないと、

dat %>% 
  mutate(kekka = case_when(
    num == 1 ~ "one",
    num == 2 ~ "two",
    num == 3 ~ "three"
  ))
# A tibble: 5 × 2
    num kekka
  <int> <chr>
1     1 one  
2     2 two  
3     3 three
4     4 <NA> 
5     5 <NA> 

欠損値が生じてしまいますので、注意が必要です。

以上、case_whenの実践でした。

それではif_elseとcase_whenの練習問題をやってみましょう