如何使用dplyr评估具有非标准评估的构造字符串?

5

我已经阅读了几篇关于使用dplyr进行编程的指南,但我仍然对如何解决使用非标准评估(NSE)评估构建/连接字符串的问题感到困惑。我意识到有比使用NSE更好的解决方案,但我想学习如何使用它。

t <- tibble( x_01 = c(1, 2, 3), x_02 = c(4, 5, 6))
i <- 1

这是我期望得到的结果,但希望在mutate()中构建变量:
t %>% mutate(d_01 = x_01 * 2)
#>   A tibble: 3 x 3
#>   x_01  x_02  d_01
#>   <dbl> <dbl> <dbl>
#> 1  1.00  4.00  2.00
#> 2  2.00  5.00  4.00
#> 3  3.00  6.00  6.00

这是我第一次尝试使用字符串:

new <- sprintf("d_%02d", i)
var <- sprintf("x_%02d", i)
t %>% mutate(new = var * 2)
#> Error in mutate_impl(.data, dots) : 
#> Evaluation error: non-numeric argument to binary operator.

这是我第二次尝试使用quosures(引用):

new <- rlang::quo(sprintf("d_%02d", i))
var <- rlang::quo(sprintf("x_%02d", i))
t %>% mutate(!!new = !!var * 2)
#> Error: unexpected '=' in "t %>% mutate(!!new ="

这是我第三次尝试使用引号和 := 运算符:

new <- rlang::quo(sprintf("d_%02d", i))
var <- rlang::quo(sprintf("x_%02d", i))
t %>% mutate(!!new := !!var * 2)
#> Error in var * 2 : non-numeric argument to binary operator
2个回答

8

像这样使用sym:=:

library(dplyr)
library(rlang)

t <- tibble( x_01 = c(1, 2, 3), x_02 = c(4, 5, 6))
i <- 1

new <- sym(sprintf("d_%02d", i))
var <- sym(sprintf("x_%02d", i))
t %>% mutate(!!new := (!!var) * 2)

提供:

# A tibble: 3 x 3
   x_01  x_02  d_01
  <dbl> <dbl> <dbl>
1     1     4     2
2     2     5     4
3     3     6     6

请注意,这在基本的R语言中非常简单。
tdf <- data.frame( x_01 = c(1, 2, 3), x_02 = c(4, 5, 6))
i <- 1

new <- sprintf("d_%02d", i)
var <- sprintf("x_%02d", i)
tdf[[new]] <- 2 * tdf[[var]]

谢谢!所以当你想要先解析表达式时,使用 sym() 是吗? - Jeffrey Girard
4
当需要处理一个字符字符串时,请使用sym - G. Grothendieck

2
你可能会发现friendlyeval包在学习整洁评估时非常有用。它简化了API并使函数选择在这些情况下更加清晰明了。
你有两个字符串想要用作列名,因此可以编写:
t <- tibble( x_01 = c(1, 2, 3), x_02 = c(4, 5, 6))
i <- 1

new <- sprintf("d_%02d", i)
var <- sprintf("x_%02d", i)
t %>% mutate(!!treat_string_as_col(new) := 
               !!treat_string_as_col(var) * 2)

您可以使用RStudio的插件随时将friendlyeval代码转换为普通的整洁评估代码。这对于您的学习目标可能会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接