tidyr 中的整洁评估
tidy evaluation in 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]
然后,小插图描述
The use of one_of()
here is important; if you don’t use it, and data contains a column named cols, nest()
will nest it instead of the columns named in 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 描述了
To provide an interface that works like the tidyr function that you’re wrapping, you should pass the argument along using {{ arg }}. {{ }} is a special tidy eval operator that captures the expression supplied by the user and forwards it to another tidy eval-enabled function.
nest_egg <- function(df, cols) {
nest(df, egg = {{ cols }})
}
nest_egg(mini_iris, -Species)
但我想知道我的nest_egg2
在
中有什么问题
所以这里有两件事;
- nest 函数接受一个向量,但是 enexprs returns 一个列表
- 嵌套不需要 (bang bang/eval)。大多数需要评估的是函数调用不带引号“”的列的名称,但是在您的情况下,因为 cols 已经是字符串的向量,所以无需评估也可以正常工作。
所以这应该可行;
library(dplyr)
library(tidyr)
mini_iris <-
iris %>%
as_tibble() %>%
.[c(1, 2, 51, 52, 101, 102), ]
nest_egg2 <- function(data, cols) {
nest(data, egg = cols)
}
nest_egg2(mini_iris, c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width"))
# # A tibble: 3 x 2
# Species egg
# <fct> <list<df[,4]>>
# setosa [2 x 4]
# versicolor [2 x 4]
# virginica [2 x 4]
在选择上下文中(而不是像 mutate()
那样的动作上下文),如果需要提供名称,可以在 c()
中使用 !!!
:
nest_egg <- function(df, cols) {
nest(df, egg = c(!!!cols))
}
由于 tidyselect 也支持名称向量,您也可以简单地取消引用它,两种方法都有效:
nest_egg <- function(df, cols) {
nest(df, egg = !!cols)
}
对于 df
有一个名为 `cols.
但在选择上下文中真正正确的方法是简单地使用 one_of()
(或在下一版本中使用 all_of()
)。
这是关于 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]
然后,小插图描述
The use of
one_of()
here is important; if you don’t use it, and data contains a column named cols,nest()
will nest it instead of the columns named in 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 描述了
To provide an interface that works like the tidyr function that you’re wrapping, you should pass the argument along using {{ arg }}. {{ }} is a special tidy eval operator that captures the expression supplied by the user and forwards it to another tidy eval-enabled function.
nest_egg <- function(df, cols) {
nest(df, egg = {{ cols }})
}
nest_egg(mini_iris, -Species)
但我想知道我的nest_egg2
在
所以这里有两件事;
- nest 函数接受一个向量,但是 enexprs returns 一个列表
- 嵌套不需要 (bang bang/eval)。大多数需要评估的是函数调用不带引号“”的列的名称,但是在您的情况下,因为 cols 已经是字符串的向量,所以无需评估也可以正常工作。
所以这应该可行;
library(dplyr)
library(tidyr)
mini_iris <-
iris %>%
as_tibble() %>%
.[c(1, 2, 51, 52, 101, 102), ]
nest_egg2 <- function(data, cols) {
nest(data, egg = cols)
}
nest_egg2(mini_iris, c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width"))
# # A tibble: 3 x 2
# Species egg
# <fct> <list<df[,4]>>
# setosa [2 x 4]
# versicolor [2 x 4]
# virginica [2 x 4]
在选择上下文中(而不是像 mutate()
那样的动作上下文),如果需要提供名称,可以在 c()
中使用 !!!
:
nest_egg <- function(df, cols) {
nest(df, egg = c(!!!cols))
}
由于 tidyselect 也支持名称向量,您也可以简单地取消引用它,两种方法都有效:
nest_egg <- function(df, cols) {
nest(df, egg = !!cols)
}
对于 df
有一个名为 `cols.
但在选择上下文中真正正确的方法是简单地使用 one_of()
(或在下一版本中使用 all_of()
)。