I've read Tidyeval: Dropping a column using Select( ) within a function? but I'm interested in dropping multiple columns.
My problem with the approach in SO: Remove columns the tidyeval way is that passing and manipulating parameters as strings is not really what tidy eval is about. I want to manipulate lists of symbols directly.
Let's assume we've loaded the right stuff and want to drop columns in a table programmatically (i.e., by reference).
library(rlang)
library(dplyr)
Referring to a single quoted variable is easy once you get your head around it.
grpdim <- quo(Sepal.Length)
iris %>% select(!!grpdim) # keeps Sepal.Length
And for reasons I don't entirely understand select()
will accept the negation of a single quosure:
iris %>% select(-!!grpdim) # drops Sepal.Length
Now suppose we have a list of variables.
I think the idiomatic way to store these would be a list of quosures. I do this often now to avoid duplicating lists of grouping variables. And it's straightforward to select()
columns by unquoting this list.
grpdims <- quos(Species, Sepal.Length)
iris %>% select(!!!grpdims) # keeps Species, Sepal.Length
But the negation does not work as expected.
iris %>% select(-!!!grpdims) # keeps Petal.Width (?!)
I found a syntax that gives the desired result but it's quite nasty.
iris %>% select(!!!lapply(lapply(grpdims, quo_expr), function(x) quo(-!!x)))
To understand what's happening here look at these partial results and then please suggest something better.
lapply(grpdims, quo_expr) # a list of bare names
lapply(lapply(grpdims, quo_expr), function(x) quo(-!!x)) # a list of negated quosures