Search code examples
rdata.tablenon-standard-evaluation

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

Solution

  • 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.