在父帧和当前帧中评估

时间:2018-08-05 17:52:02

标签: r

我正在寻找一种优雅(且安全!)的方法来评估父框架中的修订呼叫。所谓“修改”,是指我以某种方式修改了该调用,使其引用父框架中未包含但其他框架中的内容。我猜可能还会有人说:“发送一些内容,但仅用于评估”。

下面的示例阐明了我想要的内容,该示例在某些情况下有效,但并非在所有情况下都有效。 update函数(stats:::update.default)使用eval,我在weights参数中添加了与评估所用环境不同的内容(res)地点。因此,我使用了get("res", pos = -1L),希望它是引用res所处环境的一种安全方法。对于以变量作为公式估算的模型,两种定义的方法均会失败:

mod <- lm(mpg ~ cyl, data = mtcars)
form <- mpg ~ cyl
mod2 <- lm(form, data = mtcars)

wls1 <- function(x) {
  res <- residuals(x)^2 # example
  result <- update(x, weights = 1/get("res", pos = -1L))
  return(result)
}

wls2 <- function(x) {
  res <- residuals(x)^2 # example
  result <- update(x, weights = 1/res)
  return(result)
}

wls3 <- function(x) {
  data(ChickWeight)
  ChickWeight$cyl <- ChickWeight$weight
  ChickWeight$mpg <- ChickWeight$Time
  result <- update(x, data = ChickWeight)
  return(result)
}

wls1(mod)   # works
wls1(mod2)  # errors
wls2(mod)   # works
wls2(mod2)  # erros

wls3(mod)   # works
wls3(mod2)  # works

通常如何以安全的方式解决此问题? 我一直在寻找可以提供当前环境的函数(类似虚构的this.environment()函数),因此请避免使用pos参数,而应使用envir的{​​{1}}(我知道可以创建我自己的临时环境,并将get与之关联以使用类似res的东西。

2 个答案:

答案 0 :(得分:1)

我们可以通过为公式创建quote d'语言'对象,然后更新模型的call

来做到这一点。
form <- quote(mpg ~ cyl)
wlsN <- function(x, formula) {
   x$call$formula <- formula
   res <- residuals(x)^2 
   update(x, weights = 1/res)  # it is in the same environment.  No need for get 
 }


wlsN(mod2, form)
#Call:
#lm(formula = mpg ~ cyl, data = mtcars, weights = 1/res)

#Coefficients:
#(Intercept)          cyl  
#     37.705       -2.841  

-检查其他公式

form1 <- quote(disp ~ cyl + vs)
form2 <- quote(mpq ~ gear + carb)

mod1 <- lm(form1, data = mtcars)
mod2 <- lm(form2, data = mtcars)
wlsN(mod1, form1) # works
wlsN(mod2, form2) # works

答案 1 :(得分:1)

很难解决以下事实:R在dataformula的环境中寻找权重的值-在变量form中您的例子是全球环境。

一种与akrun's答案相同的主题:

wls3 <- function(x) {
 environment(x$call$formula) <- environment()
 res <- residuals(x)^2
 result <- update(x, weights=1/res)
}

我可以看到,在这种平常的解决方案中,如果使用x的公式已经具有不包含该调用环境的环境(可能会错误使用该术语),该丑陋的处理方式将变得很难看到wls3()

另一种替代方法(不建议)是使用分配,例如

wls4 <- function(x) {
 assign('res', residuals(x)^2, envir=environment(formula(x)))
 result <- update(x, weights=1/res)
}

但这会带来意外的结果,就是将变量res保留在全局环境中。