4

我已经养成了访问 data.table 列的习惯,j即使我不需要:

require(data.table)
set.seed(1); n = 10
DT <- data.table(x=rnorm(n),y=rnorm(n))

frm <- formula(x~y)

DT[,lm(x~y)]         # 1 works
DT[,lm(frm)]         # 2 fails
lm(frm,data=DT)      # 3 what I'll do instead

我希望# 2 能够工作,因为lm应该在全局环境中搜索变量DT......有没有一种优雅的方法可以让# 2 这样的东西工作?

在这种情况下,我使用的是lm,它带有一个“数据”参数,所以 #3 工作得很好。

编辑。请注意,这有效:

x1 <- DT$x
y1 <- DT$y
frm1 <- formula(x1~y1)
lm(frm1)

这也是:

rm(x1,y1)
bah <- function(){
    x1 <- DT$x
    y1 <- DT$y
    frm1 <- formula(x1~y1)
    lm(frm1)
}
bah()

编辑2。但是,这失败了,说明了@eddi 的答案

frm1 <- formula(x1~y1)
bah1 <- function(){
    x1 <- DT$x
    y1 <- DT$y
    lm(frm1)
}
bah1()
4

1 回答 1

4

它的工作方式lm是查找在所提供公式的环境中使用的变量。由于您在全局环境中创建公式,它不会在j-expression 环境中查找,因此使精确表达式lm(frm)起作用的唯一方法是将适当的变量添加到正确的环境中:

DT[, {assign('x', x, environment(frm));
      assign('y', y, environment(frm));
      lm(frm)}]

现在显然这不是一个很好的解决方案,Arun 和 Josh 的建议都好得多,我只是把它放在这里是为了理解手头的问题。

编辑另一种(可能更变态,而且相当脆弱)的方法是改变手头公式的环境(我在这里永久地做,但你可以将它恢复回来,或者复制它然后再做):

DT[, {setattr(frm, '.Environment', get('SDenv', parent.frame(2))); lm(frm)}]

顺便说一句,这里发生了一件有趣的事情——每当你使用getin j-expression 时,所有的变量都会被构造出来(所以如果你能避免它,就不要使用它),这就是为什么我不需要在某些情况下也使用x和知道需要这些变量的方法ydata.table

于 2013-10-11T15:17:00.437 回答