2014-11-12 11 views
2

Я пытаюсь понять поведение eval в data.table как «кадр».using eval in data.table

со следующим data.table:

set.seed(1) 
foo = data.table(var1=sample(1:3,1000,r=T), var2=rnorm(1000), var3=sample(letters[1:5],1000,replace = T)) 

Я пытаюсь повторить эту инструкцию

foo[var1==1 , sum(var2) , by=var3] 

с помощью функции Eval:

eval1 = function(s) eval(parse(text=s) ,envir=sys.parent()) 

Как вы можете видеть, тесты 1 и 3 работают, но я не понимаю, какой «правильный» envir установить в eval для теста 2:

var_i="var1" 
var_j="var2" 
var_by="var3" 

# test 1 works 
foo[eval1(var_i)==1 , sum(var2) , by=var3 ] 

# test 2 doesn't work 
foo[var1==1 , sum(eval1(var_j)) , by=var3] 

# test 3 works 
foo[var1==1 , sum(var2) , by=eval1(var_by)] 
+0

Это похоже на работу 'v1 <- parse (text = paste (var_i," == ", 1)); v2 <- parse (text = paste0 ("sum (", var_j, ", na.rm = TRUE)")); by1 <- parse (текст = var_by); f1 <- function (dt, expr1, expr2, expr3) { dt [eval (expr1), eval (expr2), by = eval (expr3)] }; f1 (foo, v1, v2, by1) ' – akrun

+0

Спасибо @akrun, он работает, но это не то, что я ищу. Я попытался бы (если возможно) понять кадр таблицы данных в j-выражении (DT [i, j, by]). Еще раз спасибо, надеюсь, мой вопрос ясен ... – statadat

ответ

1

j-exp, проверяет это переменные в среде .SD, которая выступает за Subset of Data. .SD сам по себе является data.table, который содержит столбцы для , что группа.

Когда вы делаете:

foo[var1 == 1, sum(eval(parse(text=var_j))), by=var3] 

сразу, j-exp получает внутренне оптимизированное/заменен на sum(var2). Но sum(eval1(var_j)) не оптимизирован и остается как есть.

Затем, когда он оценивается для каждой группы, он должен будет найти var2, который не существует в parent.frame(), из которого вызывается функция, но в .SD. В качестве примера, давайте сделаем это:

eval1 <- function(s) eval(parse(text=s), envir=parent.frame()) 
foo[var1 == 1, { var2 = 1L; eval1(var_j) }, by=var3] 
# var3 V1 
# 1: e 1 
# 2: c 1 
# 3: a 1 
# 4: b 1 
# 5: d 1 

Это найти var2 от его родительского фрейма. То есть, мы должны указать на подходящую среду для оценки с помощью дополнительного аргумента со значением = .SD.

eval1 <- function(s, env) eval(parse(text=s), envir = env, enclos = parent.frame()) 
foo[var1 == 1, sum(eval1(var_j, .SD)), by=var3] 
# var3   V1 
# 1: e 11.178035 
# 2: c -12.236446 
# 3: a -8.984715 
# 4: b -2.739386 
# 5: d -1.159506