Объединение нескольких списков имен переменных в data.table?

Я пытаюсь передать два отдельных списка имен переменных в data.table(v1.9.4). Он возвращает правильные столбцы, но он разделяет имена переменных. Это работает как ожидалось:

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

Он также отлично работает, чтобы передать один список имен:

dt[,list(a,b)]
   a b
1: 1 4
2: 2 5
3: 3 6

Но когда мне нужно передать несколько списков, он вернет правильные столбцы, но разделит имена переменных:

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

Почему два списка? Я использую несколько котировок() 'd переменных. Я прочитал FAQ 1.6, и я знаю, что одним из способов является использование символьного вектора с использованием = FALSE. Но мой реальный случай использования включает передачу сочетания имен и выражений в функцию, например,

varnames <- quote(list(a,b))
expr <- quote(list(a*b, c+d))
function(dt, varnames, expr) {
  dt[,c(varnames, expr)]
}

И я бы хотел, чтобы столбцы "varnames" имели свои собственные имена (и они делают, если вы просто передаете один список, например

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

Как я могу объединить несколько списков в таблице data.table, чтобы она по-прежнему возвращала правильные имена столбцов? (Я не совсем уверен, что это проблема с data.table или если я просто делаю что-то глупо в том, как я пытаюсь объединить списки в R, но c(), похоже, делает то, что я хочу.)

Ответ 1

Другой вариант заключается в том, чтобы завершить полный вызов заблаговременно:

varnames[4:5] <- expr[2:3]  # this results in `list(a, b, a * b, c + d)`
dt[, eval(varnames)]

дает:

   a b V3 V4
1: 1 4  4 17
2: 2 5 10 19
3: 3 6 18 21

В общем случае предположим, что у вас есть список цитированных списков выражений:

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)]

Ответ 2

Здесь возможное обходное решение с использованием .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