'Dynamic `case_when` that allows for different number of conditions and conditions itself
I'm looking for a dynamic way to specify some "condition parameters" and then feed that to a case_when
operation or something else if better suited for that problem.
My goal is to separate the specification of the conditions from the case_when call, e.g. so that a user can just type in the condition in a text file or a list in R and then I would take that info and feed it to case_when (or any other function if more appropriate).
Assuming the following data where I want to create an additional variable that recodes x
, I could do:
df <- data.frame(x = 1:10)
df |>
mutate(x2 = case_when(x < 4 ~ 1,
x >= 4 & x <=7 ~ 2,
TRUE ~ 3))
Now, what I want to achieve is to make this code flexible in a way that I can externally specify the case_when conditions and then do the recoding.
E.g. it might look like:
all_conditions <- list(1 = "x < 2",
2 = "x >= 2 & x < 5",
3 = "x >= 5 & x < 9",
4 = "TRUE")
And then I could do some sort of:
df |>
mutate(x2 = do(case_when, all_conditions))
While the example shows a numeric type of variable for which the solution of @Mael works, the solution should also work for character vars where the condition might look like x == "abc" | x == "def"
.
Solution 1:[1]
A possible solution, base on rlang
, is below.
EXPLANATION
First, we need to create a string with the whole code for
case_when
, using the listall_conditions
— that is what myimap
does.Second, using
rlang::parse_quo
, we transform the string into an expression to be used insidemutate
.
Remark
The names of the elements of list all_conditions
have to be enclosed by backticks.
library(tidyverse)
library(rlang)
df <- data.frame(x = 1:10)
all_conditions <- list(`1` = "x < 2",
`2` = "x >= 2 & x < 5",
`3` = "x >= 5 & x < 9",
`4` = "TRUE")
code <- imap(all_conditions, ~ str_c(.x, " ~ ", .y)) %>%
str_c(collapse = ", ") %>% str_c("case_when(",.,")")
df %>%
mutate(x2 = !!parse_quo(code, env = caller_env()))
#> x x2
#> 1 1 1
#> 2 2 2
#> 3 3 2
#> 4 4 2
#> 5 5 3
#> 6 6 3
#> 7 7 3
#> 8 8 3
#> 9 9 4
#> 10 10 4
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |