允许不同数量的条件和条件本身的动态“case_when”
Dynamic `case_when` that allows for different number of conditions and conditions itself
我正在寻找一种动态方式来指定一些“条件参数”,然后将其提供给 case_when
操作或其他更适合该问题的方法。
我的目标是将条件规范与 case_when 调用分开,例如这样用户就可以在文本文件或 R 中的列表中输入条件,然后我会获取该信息并将其提供给 case_when(或者更合适的任何其他功能)。
假设我想创建一个附加变量来重新编码 x
的以下数据,我可以这样做:
df <- data.frame(x = 1:10)
df |>
mutate(x2 = case_when(x < 4 ~ 1,
x >= 4 & x <=7 ~ 2,
TRUE ~ 3))
现在,我想要实现的是使这段代码变得灵活,以便我可以在外部指定 case_when 条件,然后进行重新编码。
例如它可能看起来像:
all_conditions <- list(1 = "x < 2",
2 = "x >= 2 & x < 5",
3 = "x >= 5 & x < 9",
4 = "TRUE")
然后我可以做一些事情:
df |>
mutate(x2 = do(case_when, all_conditions))
虽然该示例显示了@Mael 的解决方案适用的数字类型变量,但该解决方案也适用于条件可能类似于 x == "abc" | x == "def"
.
的字符变量
基于 rlang
的可能解决方案如下。
解释
首先,我们需要用 case_when
的完整代码创建一个字符串,使用列表 all_conditions
— 这就是我的 imap
所做的。
其次,使用rlang::parse_quo
,我们将字符串转换为要在mutate
.
中使用的表达式
备注
列表 all_conditions
的元素名称必须用反引号括起来。
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
我正在寻找一种动态方式来指定一些“条件参数”,然后将其提供给 case_when
操作或其他更适合该问题的方法。
我的目标是将条件规范与 case_when 调用分开,例如这样用户就可以在文本文件或 R 中的列表中输入条件,然后我会获取该信息并将其提供给 case_when(或者更合适的任何其他功能)。
假设我想创建一个附加变量来重新编码 x
的以下数据,我可以这样做:
df <- data.frame(x = 1:10)
df |>
mutate(x2 = case_when(x < 4 ~ 1,
x >= 4 & x <=7 ~ 2,
TRUE ~ 3))
现在,我想要实现的是使这段代码变得灵活,以便我可以在外部指定 case_when 条件,然后进行重新编码。
例如它可能看起来像:
all_conditions <- list(1 = "x < 2",
2 = "x >= 2 & x < 5",
3 = "x >= 5 & x < 9",
4 = "TRUE")
然后我可以做一些事情:
df |>
mutate(x2 = do(case_when, all_conditions))
虽然该示例显示了@Mael 的解决方案适用的数字类型变量,但该解决方案也适用于条件可能类似于 x == "abc" | x == "def"
.
基于 rlang
的可能解决方案如下。
解释
首先,我们需要用
case_when
的完整代码创建一个字符串,使用列表all_conditions
— 这就是我的imap
所做的。其次,使用
中使用的表达式rlang::parse_quo
,我们将字符串转换为要在mutate
.
备注
列表 all_conditions
的元素名称必须用反引号括起来。
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