ドキュメントには
patterns <- list( TRUE ~ as.character(x), x %% 5 == 0 ~ "fizz", x %% 7 == 0 ~ "buzz", x %% 35 == 0 ~ "fizz buzz" ) case_when(!!! patterns)
みたいに書いてあるので, list に入れればいいかと思ったけど,少し違った.
df
,df.cond
という data.frame
があったときに,df
を 列 num
が df.cond
の from
から to
までに入るか,でグループ分けして,グループを 列group
に入れる,ということを考える.
df <- data.frame(num = c(1:14)) df #> num #> 1 1 #> 2 2 #> 3 3 #> 4 4 #> 5 5 #> 6 6 #> 7 7 #> 8 8 #> 9 9 #> 10 10 #> 11 11 #> 12 12 #> 13 13 #> 14 14 df.cond <- data.frame(from = c(1, 5, 10), to = c(4, 9, 14), val = c("A", "B", "C"), stringsAsFactors = FALSE) df.cond #> from to val #> 1 1 4 A #> 2 5 9 B #> 3 10 14 C
まとめると,
list
ではなく,exprs
を使う- unevaluated expression であることが必要
- 各条件については,
- 条件全体は
expr
でcase_when
のときに評価 - df.cond に関する部分は
UQ
で 先に評価しておく
- 条件全体は
つまり,
library(dplyr) library(rlang) patterns <- exprs() for (i in 1:nrow(df.cond)) { patterns <- append(patterns, expr(.data[["num"]] >= UQ(df.cond$from[i]) & .data[["num"]] <= UQ(df.cond$to[i]) ~ UQ(df.cond$val[i]))) } patterns #> [[1]] #> .data[["num"]] >= 1 & .data[["num"]] <= 4 ~ "A" #> #> [[2]] #> .data[["num"]] >= 5 & .data[["num"]] <= 9 ~ "B" #> #> [[3]] #> .data[["num"]] >= 10 & .data[["num"]] <= 14 ~ "C"
というようになり,
df <- df %>% mutate(group = case_when(!!!patterns)) #> num group #> 1 1 A #> 2 2 A #> 3 3 A #> 4 4 A #> 5 5 B #> 6 6 B #> 7 7 B #> 8 8 B #> 9 9 B #> 10 10 C #> 11 11 C #> 12 12 C #> 13 13 C #> 14 14 C
という感じになる.
ちなみに,reprex::reprex()
では case_when(!(!(!patterns)))
となり,
#> Error in mutate_impl(.data, dots): Evaluation error: invalid argument type.
というエラーになった.