使用以编程方式构造的公式有任何陷阱吗?

时间:2013-06-30 23:18:30

标签: r scoping

我想要经历一长串潜在的解释变量, 依次回归每个响应变量。而不是粘贴在一起 模型公式,我正在考虑使用reformulate()as demonstrated here

下面的函数fun()似乎可以完成工作,适合所需的模型。但请注意 它在其调用元素中记录构造的公式对象的名称 而不是

## (1) Function using programmatically constructed formula
fun <- function(XX) {
    ff <- reformulate(response="mpg", termlabels=XX)
    lm(ff, data=mtcars)
}
fun(XX=c("cyl", "disp"))
# 
# Call:
# lm(formula = ff, data = mtcars)                 <<<--- Note recorded call
# 
# Coefficients:
# (Intercept)          cyl         disp  
#    34.66099     -1.58728     -0.02058  

## (2) Result of directly specified formula (just for purposes of comparison)
lm(mpg ~ cyl + disp, data=mtcars)
# 
# Call:
# lm(formula = mpg ~ cyl + disp, data = mtcars)   <<<--- Note recorded call
# 
# Coefficients:
# (Intercept)          cyl         disp  
#    34.66099     -1.58728     -0.02058  

我的问题:这有什么危险吗?这可以成为一个 例如,如果我想稍后应用updatepredict或 模型拟合对象的其他一些函数(可能来自其他一些环境)?

一个稍微尴尬的替代方案,然而,得到记录 呼叫权限是使用eval(substitute())。这在任何方面都是一种通常更安全的构造吗?

fun2 <- function(XX) {
    ff <- reformulate(response="mpg", termlabels=XX)
    eval(substitute(lm(FF, data=mtcars), list(FF=ff)))
}
fun2(XX=c("cyl", "disp"))$call
## lm(formula = mpg ~ cyl + disp, data = mtcars)

1 个答案:

答案 0 :(得分:2)

我总是犹豫不决,声称有没有的情况,其中涉及R环境和范围的东西可能会咬人,但......经过一些更多的探索,我上面的第一次使用看起来确实如此安全即可。

事实证明,打印的电话有点红鲱鱼。

实际被其他函数(以及formula()as.formula()提取的函数)使用的公式是存储在terms元素中的{em>适合对象,获得正确的实际公式。 (terms元素包含类"terms"的对象,它只是一个带有一堆附加属性的"formula"。)

要查看我的问题中的所有提案和相关注释都存储相同的"formula"对象(直到关联的环境),请运行以下命令。

## First the three approaches in my post
formula(fun(XX=c("cyl", "disp")))
# mpg ~ cyl + disp
# <environment: 0x026d2b7c>

formula(lm(mpg ~ cyl + disp, data=mtcars))
# mpg ~ cyl + disp

formula(fun2(XX=c("cyl", "disp"))$call)
# mpg ~ cyl + disp
# <environment: 0x02c4ce2c>

## Then Gabor Grothendieck's idea
XX = c("cyl", "disp")
ff <- reformulate(response="mpg", termlabels=XX)
formula(do.call("lm", list(ff, quote(mtcars))))  
## mpg ~ cyl + disp

要确认formula()确实是从适合对象的terms元素派生其输出,请查看stats:::formula.lmstats:::formula.terms