首页 > 解决方案 > tidyr 中的整洁评估

问题描述

这是一个关于代码的问题vignette("in-packages")

数据集如下。

(mini_iris <- iris %>% 
    as_tibble() %>% 
    .[c(1, 2, 51, 52, 101, 102), ])
#> # A tibble: 6 x 5
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species   
#>          <dbl>       <dbl>        <dbl>       <dbl> <fct>     
#> 1          5.1         3.5          1.4         0.2 setosa    
#> 2          4.9         3            1.4         0.2 setosa    
#> 3          7           3.2          4.7         1.4 versicolor
#> 4          6.4         3.2          4.5         1.5 versicolor
#> 5          6.3         3.3          6           2.5 virginica 
#> 6          5.8         2.7          5.1         1.9 virginica

如果列名在字符向量中(可能来自函数调用),则可以将其提供给 one_of()

nest_egg <- function(data, cols) {
  nest(data, egg = one_of(cols))
}

nest_egg(mini_iris, c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width"))
#> # A tibble: 3 x 2
#>   Species               egg
#>   <fct>      <list<df[,4]>>
#> 1 setosa            [2 × 4]
#> 2 versicolor        [2 × 4]
#> 3 virginica         [2 × 4]

然后,小插图描述了

这里的使用one_of()很重要;如果你不使用它,并且 data 包含一个名为 cols 的列,nest()将嵌套它而不是 cols 中命名的列。

我认为可以通过使用tidy evaluation来解决。

library(rlang)
nest_egg2 <- function(data, cols) {
  cols <- enexprs(cols)
  nest(data, egg = !!!cols)
}
nest_egg2(mini_iris, c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width"))

但它显示错误

Error: `!!!` can't be supplied with a name. Only the operand's names are retained.

在下一节中,Vignette 描述了

要提供一个与您包装的 tidyr 函数类似的接口,您应该使用 {{ arg }} 传递参数。{{ }} 是一个特殊的 tidy eval 运算符,它捕获用户提供的表达式并将其转发给另一个启用 tidy eval 的函数。

nest_egg <- function(df, cols) {
  nest(df, egg = {{ cols }})
}

nest_egg(mini_iris, -Species)

但我想知道我nest_egg2有什么问题

标签: rtidyversetidyrtidyeval

解决方案


在选择上下文中(不是在像 in 这样的动作上下文中),如果需要命名mutate(),可以使用!!!inside :c()

nest_egg <- function(df, cols) {
  nest(df, egg = c(!!!cols))
}

由于 tidyselect 还支持名称向量,您也可以简单地取消引用它,这两种方法都有效:

nest_egg <- function(df, cols) {
  nest(df, egg = !!cols)
}

取消引用确保 env-variablecols在 data-variable 上被选择cols,对于df具有名为 `cols.

但在选择上下文中真正正确的方法是简单地使用one_of()(或all_of()在下一个版本中)。


推荐阅读