我试图将data.table中的eval行为理解为“框架”。
使用以下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正在运行,但我不明白哪个是在测试2的eval中设置的“正确”环境:
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 :(得分: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()中不存在,但是在{ {1}}。例如,让我们这样做:
.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