在[.data.table的j中使用lm(my_formula)

时间:2013-10-11 06:25:55

标签: r scope data.table

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

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这样的东西工作? / p>

在这种情况下,我使用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()

EDIT2。然而,这失败了,说明了@ eddi的回答

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

1 个答案:

答案 0 :(得分:4)

lm的工作方式是查找所提供公式环境中使用的变量。由于您在全局环境中创建公式,因此不会在j - 表达式环境中查找,因此使精确表达式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)}]

顺便说一句,这里发生了一件有趣的事情 - 无论何时在get - 表达式中使用j,所有变量都会被构建(所以如果你使用它可以避免它),这就是为什么我不需要以某种方式使用xydata.table知道那些变量是必需的。