Reputation: 454
I would like to subset a data.table
by an expression involving a column, but I only have the column name as a character string.
My data.table
is
DT = data.table(a=c(1,0,1))
I would like to do
DT[a==1]
but I only have the column name "a" specified as a string. So far I am achieving the desired result by doing
DT[ DT[['a']]==1 ]
but is there a more idiomatic way of achieving the same result? I notice that DT[eval('a==1')]
throws an error.
Upvotes: 1
Views: 97
Reputation: 591
Starting with a generic expression and a column name, you can use as.name
and substitute to compose the final expression:
# helper function
subx = function(ex0, x_nm)
do.call(substitute, list(ex0, list(x = as.name(x_nm))))
# usage
ex = subx(quote(x == 1), "a")
DT[eval(ex)]
This approach -- composing the final expression and then calling eval
inside DT[...]
-- allows data.table to parse the expression and use any optimization (for example, in this case of filtering with ==
, "auto-indexing" might be used).
Upvotes: 3
Reputation: 886938
If are passing an expression, use parse
DT[eval(parse(text = 'a==1'))]
If the column name is the only one specified as a string
col1 <- "a"
DT[eval(as.symbol(col1)) == 1]
Or to a less extent get
(not recommended though as it can lead to envir issues if not properly used)
DT[get(col1) == 1]
# a
#1: 1
#2: 1
Another option is to make use of .SDcols
DT[DT[, .SD[[1]] == 1,.SDcols = col1]]
# a
#1: 1
#2: 1
Upvotes: 1