您收集输入的方式不是很实用。您的问题是您正在尝试解析如下所示的代码:
var1, var2, var3
尝试在你的 R 控制台中输入,你会得到同样的错误:
#> Error: unexpected ',' in "var1,"
因此,首先重构您的代码,以便您将输入收集为两个向量:
cnds <- c("condition1", "condition2", "condition3")
vals <- c("1", "2", "3")
现在您有两种选择将这些字符串转换为 R 代码:解析或创建符号。当您期望任意 R 代码时使用前者,而当您期望变量或列名时使用后者。你能发现差异吗?
rlang::parse_exprs(c("foo", "bar()", "100"))
#> [[1]]
#> foo
#>
#> [[2]]
#> bar()
#>
#> [[3]]
#> [1] 100
rlang::syms(c("foo", "bar()", "100"))
#> [[1]]
#> foo
#>
#> [[2]]
#> `bar()`
#>
#> [[3]]
#> `100`
在您的情况下,您可能需要解析,因为条件将是 R 代码。所以让我们从解析两个向量开始:
cnds <- map(cnds, rlang::parse_expr)
vals <- map(vals, rlang::parse_expr)
我正在映射parse_expr()
而不是使用复数版本parse_exprs()
,因为后者可以返回比其输入更长的列表。例如parse_exprs(c("foo; bar", "baz; bam"))
,将 2 个字符串转换为 4 个表达式的列表。parse_expr()
如果字符串包含多个表达式,则返回错误,因此在我们的例子中更健壮。
现在我们可以映射这两个 LHS 和 RHS 列表并创建公式。一种简单的方法是使用 quasiquotation 通过取消引用每个 LHS 及其对应的 RHS 来创建公式:
fs <- map2(cnds, vals, function(c, v) rlang::expr(!!c ~ !!v))
结果是准备好拼接的公式表达式列表case_when()
:
data %>% mutate(result = case_when(!!!fs))
用于rlang::qq_show()
查看拼接取消引用正在做什么:
rlang::qq_show(mutate(result = case_when(!!!fs)))
#> mutate(result = case_when(condition1 ~ 1, condition2 ~2, condition3 ~ 3))