snacks
snacks

Reputation: 454

Selecting rows in data.table by expression on a character column name

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

Answers (2)

Frank 2
Frank 2

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

akrun
akrun

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

Related Questions