nice selection
2 min readI started writing in R before the tidyverse became a thing and I never really had to think about non-standard evaluation when writing functions. Those days are long past and I’ve recently struggled with the challenge when writing functions for the R4EPIs project, which would stick out like ugly little trolls along side tidyverse functions.
One of my biggest struggles was trying to figure out how, excactly to select a
varaible from a user as either a character string or a bare variable. I had only
known about rlang::enquo()
and rlang::sym()
, but I thought I had to use one
or the other.
I had liked tidyselect::vars_select()
because it gave me characters that I
could use on my data frame columns, and it worked really will with the dots:
f <- function(.df, ...) {
tidyselect::vars_select(colnames(.df), ...)
}
f(iris, tidyselect::starts_with("Sepal"))
## Sepal.Length Sepal.Width
## "Sepal.Length" "Sepal.Width"
f(iris, Sepal.Width)
## Sepal.Width
## "Sepal.Width"
f(iris, "Sepal.Width")
## Sepal.Width
## "Sepal.Width"
But when I would try it with specific arguments, it would scold me if the data weren’t in character form:
f <- function(.df, var) {
tidyselect::vars_select(colnames(.df), var)
}
f(iris, Sepal.Width)
## Error in .f(.x[[i]], ...): object 'Sepal.Width' not found
f(iris, "Sepal.Width")
## Sepal.Width
## "Sepal.Width"
I recently found that I could use !! enquo(var)
to allow the user to input
either a character or a bare variable:
library("rlang")
f <- function(.df, var) {
tidyselect::vars_select(colnames(.df), !! enquo(var))
}
f(iris, Sepal.Width)
## Sepal.Width
## "Sepal.Width"
f(iris, "Sepal.Width")
## Sepal.Width
## "Sepal.Width"
And now it finally makes sense!