首页 > 解决方案 > 在函数内调用 lm() 中的权重无法正确评估

问题描述

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

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))

这返回

eval 中的错误(extras、data、env):找不到对象“wts”

如果你单独运行这一切,它工作正常。我已经深入研究了 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

它确实返回一个数字向量。但是当我跑步时

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)

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

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

标签: rnon-standard-evaluation

解决方案


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

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))

eval(mf, parent.frame)你指的是用你的公式lm()打电话。model.frame()并且从?model.frame帮助页面上的描述中:“公式,子集和...中的所有变量首先在数据中查找,然后在公式环境中查找(有关更多详细信息,请参见公式()的帮助)并收集到一个数据框”。所以它再次查看公式的环境,而不是调用框架。


推荐阅读