函数内 lm() 中对权重的调用未正确评估

Call to weight in lm() within function doesn't evaluate properly

我正在编写一个需要加权回归的函数。我多次遇到权重参数错误,我创建了一个最小的可重现示例,您可以在此处找到:

wt_reg <- function(form, data, wts) {
  lm(formula = as.formula(form), data = data,
     weights = wts)
}

wt_reg(mpg ~ cyl, data = mtcars, wts = 1:nrow(mtcars))

这个returns

Error in eval(extras, data, env) : object 'wts' not found

如果你 运行 这一切都单独进行,它工作正常。我深入研究了 lm,看来问题是对 eval(mf, parent.frame()) 的调用。即使 wts 在 parent.frame() 中,它在调用中似乎没有被正确评估。这里有更多细节:

mf 的分配与

相同
stats::model.frame(formula = as.formula(form), data = data, weights = wts, 
    drop.unused.levels = TRUE)

当我运行

parent.frame()$wts

它 return 一个数值向量。但是当我 运行

eval(stats::model.frame(formula = as.formula(form), data = data, weights = wts, 
    drop.unused.levels = TRUE), parent.frame()) 

没有。

我可以运行

stats::model.frame(formula = as.formula(parent.frame()$form), 
    data = parent.frame()$data, weights = parent.frame()$wts, 
    drop.unused.levels = TRUE)

并且有效。如果您想使用顶部的示例,您可以自己进行测试。

有什么想法吗?我真的不知道这里发生了什么...

公式在 R 中的特殊之处在于它们不仅跟踪 symbol/variable 名称,还跟踪创建它们的环境。查看

ff <- mpg ~ cyl
environment(ff)
# <environment: R_GlobalEnv>
foo <- function() {
  ff <- mpg ~ cyl
  environment(ff)
}
foo()
# <environment: 0x0000026172e505d8> private function environment (different each time)

问题是 lm 将尝试使用创建公式的环境来查找变量而不是父框架。由于您在调用 wt_reg 时创建了公式,因此该公式适用于全局范围。但是 wts 只存在于函数作用域中。您可以更改函数以将公式上的环境更改为本地函数环境,然后一切正常

wt_reg <- function(form, data, wts) {
  ff <- as.formula(form)
  environment(ff) <- environment()
  lm(formula = ff, data = data,
     weights = wts)
}

wt_reg(mpg ~ cyl, data = mtcars, wts = 1:nrow(mtcars))

您在 lm() 中提到的 eval(mf, parent.frame) 是用您的公式调用 model.frame()。根据 ?model.frame 帮助页面上的描述:"All the variables in formula, subset and in ... are looked for first in data and then in the environment of formula (see the help for formula() for further details) and collected into a data frame"。所以它又是在公式的环境中查找,而不是调用框架。