4

我想使用该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 包于 2021-08-02 创建 (v2.0.0 )

显然三重花括号不是这里的解决方案,有人可以帮我吗?

谢谢你。

4

3 回答 3

3

你可以使用dplyr::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(rlang::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
于 2021-08-02T16:13:28.313 回答
1

当您想传递参数名称而不是字符串时,这是另一种选择。函数enquo用于扩散用户定义的变量,但不是ensym返回原始表达式,而是enquo返回一个 quosure,它是绑定到环境的表达式。所以我们使用get_expr它来访问它的表达式并将其包装在上下文中rlang::eval_tidybase::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
于 2021-08-02T15:42:10.673 回答
0

另一种选择可能是:

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
于 2021-08-02T15:36:21.750 回答