2015-05-05 3 views
10

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

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

И я бы хотел, чтобы «столбцы» имени переменной, чтобы их собственные имена (и они делают, если вы просто пропускать один список, как

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

Он работает с именованными списками, но не уверен, что это было бы приемлемо для ваших целей. 'dt [, c (list (a = a, b = b), list (c = c, d = d))] –

+0

Интересно - спасибо! Это, безусловно, квалифицируется как обходное решение, и это лучше, чем обходное решение FAQ 1.6, поскольку это также будет работать с выражениями (а не только с именами переменных). Но я все равно хотел бы знать, есть ли способ объединить неназванные списки, чтобы он работал с регулярным (чистым!) Синтаксисом data.table. (Или если я делаю что-то глупо с тем, как я совмещаю цитированные списки.) – cauchy

+1

@cauchy, вы ничего не делаете неправильно, 'data.table' просто делает вам одолжение в простом списке, конвертируя неназванный список в именованный, но он не может этого сделать в более сложных случаях, поскольку намерение не ясно – eddi

ответ

4

Другой вариант построить полный вызов загодя:

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

Прохладный! Я не понимал, что это можно сделать. Кроме того, никогда не видел случая, когда этот вид присваивания работает, но 'c (varnames, expr [-1])' does not. 'expr' являются странными. – Frank

+1

довольно круто - я предлагаю упростить: 'as.call (Reduce (function (x, y) c (as.list (x), as.list (y) [- 1]), exprlist)) ' – eddi

+0

@eddi, отлично, я пытался что-то сделать, но не мог заставить его работать. – BrodieG

1

Вот можно обойти с помощью .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 
+0

Вау, я удивлен, увидев, что он работает в этом случае. Я полагаю .SD() возвращает столбцы с именами, прикрепленными к ним, поэтому он работает по той же причине, что и именованный список, предложенный docendo discimus выше. Главным недостатком этого для меня является то, что у меня есть десятки тысяч столбцов, и мне нужно лишь небольшое количество переменных, а .SD() действительно неэффективно, если вы не используете большинство столбцов. – cauchy