我正在尝试嵌套一个函数,该函数将两个字符串粘在一起,该函数使用组合字符串命名数据框架的列。然而,问题似乎是glue表达式没有足够早地计算为字符串。我可以(也应该)强制表达式在作为参数传递给另一个函数之前进行评估吗?
library(tidyverse)
# define inner function
add_prefix <- function(string) {
x <- glue::glue("prefix_{string}")
return(as.character(x))
}
# define outer function
mod_mtcars <- function(df, name) {
df %>%
mutate({{ name }} := mpg ^ 2)
}
mod_mtcars(mtcars, add_prefix("foo"))
#> Error: The LHS of `:=` must be a string or a symbol
# alternative outer function with explicit enquoting
mod_mtcars2 <- function(df, name) {
name <- ensym(name)
df %>%
mutate(!!name := mpg ^ 2)
}
mod_mtcars2(mtcars, add_prefix("foo"))
#> Error: Only strings can be converted to symbols
由reprex包(v2.0.1)在2018-10-30上创建
首先,现在更倾向于使用glue字符串语法,而不是直接包含在LHS中。所以更喜欢"{{ var }}" := expr
而不是{{ var }} := expr
。在rlang的未来版本中(明年),我们将使=
使用胶串成为可能。在这一点上,:=
将几乎被取代。在添加胶水支撑之前,我们使用:=
,允许!!
注射到LHS上。
第二,你的问题是你使用{{
而不是简单的注入。{{
用于注入表达式作为参数提供,而不是表达式的值。使用"{"
的普通胶水插值来注入值:
mod_mtcars <- function(df, name) {
df %>%
mutate("{name}" := mpg ^ 2)
}
PS:你的!!
版本有类似的问题。因为您在参数上使用了ensym()
,所以您消除了作为参数提供的表达式,而不是使用值。但是ensym()
要求表达式是一个简单的名称,并且您提供了一个完整的计算,从而导致错误。你可以这样修改:
mod_mtcars2 <- function(df, name) {
df %>%
mutate(!!name := mpg ^ 2)
}
但现在首选胶水语法。
name
不是符号。试一试:
mod_mtcars <- function(df, name) {
name <- sym(name)
df %>%
mutate({{ name }} := mpg ^ 2)
}
mod_mtcars(mtcars, add_prefix("foo"))
更好的是,tidy eval现在支持粘合字符串,因此您可以使用:
# don't need add_prefix()
mod_mtcars <- function(df, name){
df %>%
mutate("prefix_{{name}}" := mpg ^ 2)
}
mod_mtcars(mtcars, foo)
最后,花括号操作符将表达式传递给它一个字符串。如果您保留当前函数,请使用bang-bang操作符:
mod_mtcars <- function(df, name){
df %>%
mutate(!! name := mpg ^ 2)
}
mod_mtcars(mtcars, add_prefix("foo"))
我们可能需要转义输入(保持OP的原始功能不变)
mod_mtcars(mtcars, !!add_prefix("foo"))
与产出
mpg cyl disp hp drat wt qsec vs am gear carb prefix_foo
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 441.00
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 441.00
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 519.84
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 457.96
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 349.69
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 327.61
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 204.49
...