Ответ 1
UPDATE (eddi): По сравнению с версия 1.8.11 это исправлено, а .SD
- не требуется в случаях, когда выражение может быть оценено на месте, как в OP. Поскольку в настоящее время наличие .SD
вызывает конструкцию полного .SD
, это приведет к значительно более быстрым скоростям в некоторых случаях.
Что происходит, так это то, что вызовы eval()
обрабатываются иначе, чем вы, вероятно, себе представляете в коде, который реализует [.data.table()
. В частности, [.data.table()
содержит специальные ветки оценки для выражений i
и j
, которые начинаются с символа eval
. Когда вы завершаете вызов eval
внутри вызова sum()
, eval
больше не является первым элементом анализируемого/замещенного выражения, а специальная ветвь оценки пропускается.
Вот бит кода в функции монстра, отображаемый при вводе getAnywhere("[.data.table")
, который делает специальную учетную запись для вызовов eval()
, переданных через [.data.table()
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 здесь), или явно укажите eval()
в сторону .SD
, локальная переменная, которая содержит столбцы любой таблицы данных, на которой вы работаете (здесь d
). (Для более подробного объяснения роли .SD
см. Первые несколько абзацев этого ответа).
d[, sum(eval(quoted_a, envir=.SD))]