Jamie
Jamie

Reputation: 1965

Is it possible to substitute into `i` element in data.table[i, j , by]

I'm wondering if it's possible to substitute expressions into the i portion of data.table. I've set up a deeply nested list that contains preset parameters to perform subsetting depending on which sub-group a user has selected in a shiny app. I'm suspecting that it is not possible but am hoping to get confirmation one way or the other.

If it's not possible, I welcome any ideas for alternative solutions.

Basic example

library(data.table)

dt = data.table(
  y = rep(c('a','b'),5),
  x = 1:10
)

exp1 = "x > 5"

dt[y == "a" & substitute(exp1)]
# Error: operations are possible only for numeric, logical or complex types

Upvotes: 3

Views: 205

Answers (2)

Hieu Nguyen
Hieu Nguyen

Reputation: 609

My approach is like this:

library(data.table)
exp1 = "x > 5" |> str2lang()
(ll <- substitute(
    dt[y == "a" & e1],
    list(
        e1 = exp1
    )
))
eval(ll)

I think this is a good approach because it maintains idiomatic data.table's look. For example, if you want dt[y == "a" & x > 5, .(mm = length(x)), by = "y"]:

(ll <- substitute(
    dt[y == "a" & e1, .(mm = f1(e2)), by = e3], # Change right here and maintain data.table's look
    list(
        e1 = exp1,
        # e1 = "x > 5" |> str2lang(),
        e2 = quote(x), # Allow more flexibilities
        e3 = "y", # Allow more flexibilities
        f1 = quote(length) # Allow more flexibilities
    )
))
eval(ll)

It is also similar to the substitute2 and env approaches proposed in developmental version of data.table.

Upvotes: 4

Ronak Shah
Ronak Shah

Reputation: 388982

It is possible using eval(parse(..)) but there are some concerns related to it.

library(data.table)

exp1 = "x > 5"
dt[y == "a" & eval(parse(text = exp1))]

#   y x
#1: a 7
#2: a 9

Upvotes: 0

Related Questions