如何使用 dplyr 评估具有非标准评估的构造字符串?
How to evaluate a constructed string with non-standard evaluation using dplyr?
我已经阅读了一些关于使用 dplyr 进行编程的指南,但我仍然对如何解决使用非标准评估评估 constructed/concatenated 字符串的问题感到困惑( 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 ="
这是我的第三次尝试,尝试使用 quosures 和 :=
运算符:
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
像这样使用 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]]
您可能会发现包 friendlyeval
在学习 tidy eval 时很有用。它简化了 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
代码转换为简洁的评估代码。考虑到您的学习目标,这可能会有所帮助。
我已经阅读了一些关于使用 dplyr 进行编程的指南,但我仍然对如何解决使用非标准评估评估 constructed/concatenated 字符串的问题感到困惑( 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 ="
这是我的第三次尝试,尝试使用 quosures 和 :=
运算符:
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
像这样使用 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]]
您可能会发现包 friendlyeval
在学习 tidy eval 时很有用。它简化了 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
代码转换为简洁的评估代码。考虑到您的学习目标,这可能会有所帮助。