Reputation: 339
This is a question about the codes in vignette("in-packages")
The dataset is below.
(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
If the column names are in a character vector (possibly from a function call), you can provide that to 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]
And then, vignette describes that
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.
I think it can be solved in using 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"))
but it shows error
Error: `!!!` can't be supplied with a name. Only the operand's names are retained.
In next section, Vignette describes that
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)
But I wonder what my nest_egg2
has problem in
Upvotes: 1
Views: 355
Reputation: 6803
In selection contexts (not in action contexts like in mutate()
), you can use !!!
inside c()
if you need to give a name:
nest_egg <- function(df, cols) {
nest(df, egg = c(!!!cols))
}
Since tidyselect also supports vectors of names, you can also simply unquote it, both approaches are valid:
nest_egg <- function(df, cols) {
nest(df, egg = !!cols)
}
The unquoting makes sure the env-variable cols
is chosen over the data-variable cols
, for the case that df
has a column named `cols.
But really the proper way in selection contexts is to simply use one_of()
(or all_of()
in the next version).
Upvotes: 1
Reputation: 1261
So there are two things here;
So this should work;
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]
Upvotes: 0