在用户定义的函数中使用胶水进行变异
Posted
技术标签:
【中文标题】在用户定义的函数中使用胶水进行变异【英文标题】:Mutate using glue in a user defined function 【发布时间】:2021-10-07 22:34:03 【问题描述】:我想使用glue
函数更改特定列中的值以包含另一列中的信息。
我通常是这样做的:
library(glue)
library(dplyr)
df = data.frame(x = c("Banana","Apple","Melon"),
y = c(10,15,27),
z = rep(c("something_else"),3))
df %>%
mutate(x = glue("x (y)"))
输出:
#> x y z
#> 1 Banana (10) 10 something_else
#> 2 Apple (15) 15 something_else
#> 3 Melon (27) 27 something_else
当我尝试使用数据框和列名作为用户定义函数中的输入来做同样的事情时,我的问题就出现了。
我最初的要求是使用双花括号和胶水函数来传递输入,但这会导致错误。
concatenate_value_to_string <- function(tbl,var1,var2)
tbl %>%
mutate(var1 := glue("var1 (var2)"))
concatenate_value_to_string(df,x,y)
#> Error in UseMethod("mutate"): no applicable method for 'mutate' applied to an object of class "function"
由reprex package (v2.0.0) 于 2021 年 8 月 2 日创建
显然三重花括号不是这里的解决方案,有人可以帮我吗?
谢谢。
【问题讨论】:
【参考方案1】:你可以使用pull()
:
concatenate_value_to_string <- function(tbl,var1,var2)
tbl %>%
mutate(var1 := glue("pull(., var1) (pull(., var2))"))
concatenate_value_to_string(df,x,y)
concatenate_value_to_string(df,x,y)
#> x y z
#> 1 Banana (10) 10 something_else
#> 2 Apple (15) 15 something_else
#> 3 Melon (27) 27 something_else
或eval(expr(...))
:
concatenate_value_to_string <- function(tbl,var1,var2)
tbl %>%
mutate(var1 := glue("eval(expr(var1)) (eval(expr(var2)))"))
concatenate_value_to_string(df,x,y)
#> x y z
#> 1 Banana (10) 10 something_else
#> 2 Apple (15) 15 something_else
#> 3 Melon (27) 27 something_else
您尝试的方法不起作用,因为如果mutate()
是字符串的一部分,则foo
不能替换它,在上面的解决方案中,pull()
或expr()
这样做。
在这种情况下,我个人更愿意使用sprintf()
:
concatenate_value_to_string <- function(tbl,var1,var2)
tbl %>%
mutate(var1 := sprintf("%s (%s)", var1, var2))
concatenate_value_to_string(df,x,y)
#> x y z
#> 1 Banana (10) 10 something_else
#> 2 Apple (15) 15 something_else
#> 3 Melon (27) 27 something_else
【讨论】:
【参考方案2】:当您想要传递参数名称而不是字符串时,这是另一个选项。函数enquo
用于扩散用户定义的变量,但不是ensym
,它返回一个原始表达式enquo
返回一个quosure,它是一个绑定到环境的表达式。所以我们使用get_expr
来访问它的表达式,并用rlang::eval_tidy
或base::eval
包装它以在上下文中进行评估。
library(rlang)
concatenate_value_to_string <- function(tbl, var1, var2)
tbl %>%
mutate(!!enquo(var1) := glue("eval_tidy(get_expr(enquo(var1))) (eval_tidy(get_expr(enquo(var2))))"))
concatenate_value_to_string(df, x, y)
x y z
1 Banana (10) 10 something_else
2 Apple (15) 15 something_else
3 Melon (27) 27 something_else
【讨论】:
【参考方案3】:另一种选择可能是:
concatenate_value_to_string <- function(tbl, var1, var2)
tbl %>%
mutate(!!var1 := glue(".data[[var1]] (.data[[var2]])"))
concatenate_value_to_string(df, "x", "y")
x y z
1 Banana (10) 10 something_else
2 Apple (15) 15 something_else
3 Melon (27) 27 something_else
【讨论】:
以上是关于在用户定义的函数中使用胶水进行变异的主要内容,如果未能解决你的问题,请参考以下文章