【问题标题】:How to evaluate a constructed string with non-standard evaluation using dplyr?如何使用 dplyr 评估具有非标准评估的构造字符串?
【发布时间】:2018-01-01 20:58:02
【问题描述】:

我现在已经阅读了几本关于使用 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 ="

这是我的第三次尝试,尝试使用 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

【问题讨论】:

    标签: r dplyr nse rlang tidyeval


    【解决方案1】:

    像这样使用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()?
    • 当我们有一个字符串时使用sym。
    【解决方案2】:

    在学习 tidy eval 时,您可能会发现包 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 代码转换为简洁的 eval 代码。考虑到您的学习目标,这可能会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多