Reputation: 198
I'm trying to pass two separate lists of variable names into a data.table (v1.9.4). It returns the correct columns, but it strips the variable names. This works as expected:
dt <- data.table(a=1:3, b=4:6, c=7:9, d=10:12)
dt
a b c d
1: 1 4 7 10
2: 2 5 8 11
3: 3 6 9 12
It also works fine to pass a single list of names:
dt[,list(a,b)]
a b
1: 1 4
2: 2 5
3: 3 6
But when I need to pass multiple lists, it returns the correct columns but strips the variable names:
dt[,c(list(a,b), list(c,d))]
V1 V2 V3 V4
1: 1 4 7 10
2: 2 5 8 11
3: 3 6 9 12
Why two lists? I'm using multiple quote()'d lists of variables. I've read FAQ question 1.6, and I know that one workaround is to use a character vector using with=FALSE. But my real use case involves passing a mix of names and expressions to a function, e.g.,
varnames <- quote(list(a,b))
expr <- quote(list(a*b, c+d))
function(dt, varnames, expr) {
dt[,c(varnames, expr)]
}
And I'd like the "varnames" columns to have their proper names (and they do if you just pass a single list like
dt[,list(a,b,a*b,c+d)]
a b V3 V4
1: 1 4 4 17
2: 2 5 10 19
3: 3 6 18 21
How can I combine multiple lists in a data.table such that it still returns the proper column names? (I'm not completely sure if this is a data.table issue or if I'm just doing something silly in the way I'm trying to combine lists in R, but c() seems to do what I want.)
Upvotes: 10
Views: 1246
Reputation: 52637
Another option is to construct the full call ahead of time:
varnames[4:5] <- expr[2:3] # this results in `list(a, b, a * b, c + d)`
dt[, eval(varnames)]
produces:
a b V3 V4
1: 1 4 4 17
2: 2 5 10 19
3: 3 6 18 21
More generically, suppose you have a list of quoted lists of expressions:
exprlist <- list(quote(list(a, b)), quote(list(c, c %% a)), quote(list(a + b)))
expr <- as.call(Reduce(function(x, y) c(as.list(x), as.list(y)[-1]), exprlist)) # @eddi
dt[, eval(expr)]
Upvotes: 4
Reputation: 92282
Here's a possible workaround using .SD
varnames <- quote(list(a,b))
expr <- quote(list(a*b, c+d))
myFunc <- function(dt, varnames, expr) {
dt[, c(.SD[, eval(varnames)], eval(expr))]
}
myFunc(dt, varnames, expr)
# a b V1 V2
# 1: 1 4 4 17
# 2: 2 5 10 19
# 3: 3 6 18 21
Upvotes: 1