Evaluating both column name and the target value within `j` expression within `data.table`

Here is one possible alternative.

target <- "vs"
value <- 1
dt <- as.data.table(head(mtcars))

In terms of code it’s not necessarily simpler, but we can set up an unevaluated call cl defined outside the scope of dt which is to be evaluated inside the data table’s environment.

cl <- substitute(
    x == y, 
    list(x = as.name(target), y = value)
)

substitute() might be necessary for longer expressions. But in this case, call() would shorten the code and create the same cl result. And so cl could also be

cl <- call("==", as.name(target), value)

Now we can evaluate cl inside dt. On your example this seems to work fine.

dt[, NEWCOL := sum(eval(cl)), by = am][]
#     mpg cyl disp  hp drat    wt  qsec vs am gear carb NEWCOL
# 1: 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4      1
# 2: 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4      1
# 3: 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1      1
# 4: 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1      2
# 5: 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2      2
# 6: 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1      2

After thinking about this for a minute, I’m not sure value needed to be substituted, and hence the following also works. But as David notes, the first approach is more time efficient.

dt[, eval(as.name(target)) == value]
# [1] FALSE FALSE  TRUE  TRUE FALSE  TRUE

Leave a Comment