Reputation: 12450
I'm trying to wrap my head around quasiquotation so that I could use it together with a data.table
call. Here is an example:
library(data.table)
library(rlang)
dt <- data.table(col1 = 1:10, col2 = 11:20)
dt[, col1]
If I wanted to wrap this into function, how would I do this? I tried:
foo <- function(dt, col) {
col <- quo(col)
expr(dt[, !!col1])
}
foo(dt, col1)
But get Error in enexpr(expr) : object 'col1' not found
. I assume I'm missing some steps as data.table
evaluates this differently than dplyr
.
Upvotes: 4
Views: 698
Reputation: 682
You can use deparse
and substitute
and use the argument with=FALSE
as in :
foo <- function(dt, col){
col_str = deparse(substitute(col))
dt[, col_str, with = F]
}
or you can use eval
and substitute
and use the default data.table argument with=TRUE
as in :
foo <- function(dt, col){
col_symb = substitute(col)
dt[, eval(col_symb)] # by default: with=TRUE
}
In both cases, substitute
will get the name of the argument that you pass to the parameter col
. In the first case deparse
will convert this name as a string, thus enabling us to select it from the data.table using with = FALSE. In the second case we evaluate (using eval
) the name of the argument in the context of the data.table.
Upvotes: 1
Reputation: 206516
You want to capture the column name as a symbol with
col <- ensym(col)
rather than quo()
and then use
expr(dt[, !!col])
(not col1
which doesn't exist there) but that will just return an expression. If you want to evaluated it, you'd need
eval_tidy(expr(dt[, !!col]))
But really the quasinotation stuff works best in the tidyverse and not with data.table functions natively. The "data.table" way might be more like something in this existing question: Pass column name in data.table using variable. data.table very much prefers strings to symbols.
Upvotes: 6