2013-04-09 3 views
17

Что мне здесь не хватает?eval и quote in data.table

d = data.table(a = 1:5) 

d[, a]     # 1 2 3 4 5 
d[, sum(a)]    # 15 

d[, eval(quote(a))]  # 1 2 3 4 5 
d[, sum(eval(quote(a)))] # 15 

quoted_a = quote(a) 
d[, eval(quoted_a)]  # 1 2 3 4 5 
d[, sum(eval(quoted_a))] # Error in eval(expr, envir, enclos) : object 'a' not found 

Что происходит? Я бегу R 2.15.0 и data.table 1.8.9.

+0

У меня была такая проблема сегодня; была решена с помощью 'quote (sum (a))' вместо 'expression (sum (a))'. Не знаю, почему это имело значение. – rbatt

ответ

20

ОБНОВЛЕНИЕ (Eddi): По состоянию version 1.8.11 это было исправлено и .SD не требуется в тех случаях, когда выражение может быть вычислено на месте, как и в ОП. Поскольку в настоящее время наличие .SD приводит к созданию полного .SD, это приведет к значительно более высокой скорости в некоторых случаях.


Что происходит в том, что призывы к eval() обращаются иначе, чем вы, вероятно, представить себе в коде, который реализует [.data.table(). В частности, [.data.table() содержит специальные ветви оценки для i и j выражения, которые начинаются с символа eval. Когда вы завершаете вызов eval внутри вызова sum(), eval уже не является первым элементом анализируемого/замещенного выражения, а специальная ветвь оценки пропускается.

Вот немного кода в функции монстра отображается набрав getAnywhere("[.data.table"), что делает специальное пособие для звонков в eval() передали через [.data.table() «s j -argument:

jsub = substitute(j) 
    ... 
    # Skipping some lines 
    ... 
jsubl = as.list.default(jsub) 
if (identical(jsubl[[1L]], quote(eval))) { # The test for eval 'on the outside' 
    jsub = eval(jsubl[[2L]], parent.frame(), parent.frame()) 
    if (is.expression(jsub)) 
     jsub = jsub[[1L]] 
} 

В качестве временного решения, либо следовать пример в data.table FAQ 1.6 (pdf here), или явно указать eval() в сторону .SD, локальную переменную, которая содержит столбцы любой таблицы данных, на которой вы работаете (здесь d). (Для более подробного объяснения роли .SD см. Первые несколько параграфов this answer).

d[, sum(eval(quoted_a, envir=.SD))] 
+0

нормально, как я могу это исправить? Я хотел бы передать 'data.table' и имя переменной в функцию, которая будет вычислять, например. «сумма». Раньше я использовал вышеуказанный код (и я мог бы поклясться, что он работал с предыдущей версией «R» или «data.table'), но это, похоже, не может быть и речи ...? – eddi

+1

Как насчет 'quoted_a <- quote (sum (a))', как показано в [** faq 1.6 **] (http://datatable.r-forge.r-project.org/datatable-faq.pdf) ? – Arun

+0

, который не будет работать для меня, тот, кто вызывает функцию, не знает, какие оценки будут происходить там – eddi