在使用`weights`参数调用`lapply`中的`lm`时出现错误。

10

在使用weights参数时,在lapply中调用lm时,我遇到了一种奇怪的行为。

我的代码由一个公式列表组成,在其中运行线性模型,并在lapply中调用。到目前为止,它一直在工作:

dd <- data.frame(y = rnorm(100),
                 x1 = rnorm(100),
                 x2 = rnorm(100),
                 x3 = rnorm(100),
                 x4 = rnorm(100),
                 wg = runif(100,1,100))

ls.form <- list(
  formula(y~x1+x2),
  formula(y~x3+x4),
  formula(y~x1|x2|x3),
  formula(y~x1+x2+x3+x4)
)

res.no.wg <- lapply(ls.form, lm, data = dd)

然而,当我添加weights参数时,出现了奇怪的错误:

res.with.wg <- lapply(ls.form, lm, data = dd, weights = dd[,"wg"])
Error in eval(extras, data, env) : 
  ..2 used in an incorrect context, no ... to look in

如果lapply中的...lm调用中的...发生冲突,但这仅因为weights参数。

您有什么想法是问题的原因以及如何解决?

注意:在没有lapply的情况下使用该调用可以按预期工作:

lm(ls.form[[1]], data = dd, weights = dd[,"wg"] )

Call:
lm(formula = ls.form[[1]], data = dd, weights = dd[, "wg"])

Coefficients:
(Intercept)           x1           x2  
   -0.12020      0.06049     -0.01937  

编辑 最终调用是在一种类型的函数内部执行的lapply

f1 <- function(samp, dat, wgt){
res.with.wg2 <- lapply(ls.form, function(x) {lm(formula = x, data=dat[samp,], weights=dat[samp,wgt])})
}

f1(1:66, dat=dd, wgt = "wg")

这似乎是在使用带有“权重”的函数中出现问题,需要注意lm。请参阅:https://stackoverflow.com/questions/38683076/ellipsis-trouble-passing-to-lm - John Paul
我重新打开了这个问题,尽管此问题之前已被提出,因为这里的答案比原问题的任何答案都要好。https://dev59.com/xpDea4cB1Zd3GeqPfLAA - G. Grothendieck
@G.Grothendieck,把这两个问题通过重复链接在一起不是更有价值吗?也许可以用这个来重复另一个问题? - Sotos
好的。我已经关闭了另一个答案并将其链接到这个答案。 - G. Grothendieck
还有一件事。勾选的答案最好地解释了这一点,但不幸的是,由其作者删除的答案对我来说似乎是首选的解决方法,如果该答案的作者撤销删除操作将是非常好的。 - G. Grothendieck
@G. Grothendieck 我已经取消了对我的回答的删除,起初我删除它是因为我觉得这个答案与其他已经在SO上的答案非常接近,而 James 的解决方案更好。如果我造成了任何困惑,对不起! - Florian
2个回答

11

我不太确定为什么它不能正常工作,但我确信我有一个解决方法:

res.with.wg2 <- lapply(ls.form, 
                   function(x) {lm(formula = x, data=dd, weights=dd[,"wg"])})

希望这能有所帮助!


你不应该删除在我的问题下的评论,你提供的链接很有用。 - Bastien
嗨@Bastien,抱歉我删除了评论。我之所以删除它,是因为我不确定那是否是实际问题(在该答案下面有一个很长的评论线程),特别是当我看到@James的回答时。我仍在努力理解这个问题,但恐怕它有点超出了我的能力范围。真正让我困惑的是res.with.wg <- lapply(X=ls.form, FUN=lm, data = dd, method= 'model.frame')确实可以正常工作。 - Florian
@Bastien,针对你的问题,你最好创建一个基础模型,然后使用“update”来创建具有不同公式的新模型。 - James
当我想到它时,我的问题是一个 parLapply-function-lapply-function-lm 调用... 可能过于复杂,但我确信 R 可以处理它。我会看一下 update 函数,它可能确实简化了事情... - Bastien
@Bastien 我已经更新了我的答案,并提供了如何使用它的示例。 - James
显示剩余2条评论

5

lapply的帮助文件中有一条注释:

由于历史原因,lapply创建的调用未被评估,并且编写了依赖它的代码(例如bquote)。这意味着记录的调用始终采用FUN(X [ [i]],...)的形式,其中i由当前(整数或双精度)索引替换。通常这不是问题,但如果FUN使用sys.call或match.call,或者它是使用调用的原始函数,则可能会有问题。这意味着通常更安全地使用包装器调用原始函数,例如,需要使用lapply(ll,function(x)is.numeric(x))来确保is.numeric的方法分派正确。

lm在其开头行中两次使用match.call

cl <- match.call()
mf <- match.call(expand.dots = FALSE)

解决方法在帮助文件中提到,并由 @Florian 使用匿名函数包装器实现。
更新
针对更改模型公式的特定问题,您可以通过使用 update 来重写,避免在 lapply 中调用 lm:
# create base model (the formula here doesn't really matter, but we can specify the weights safely here)
baselm <- lm(y+x1,data=dd,weights=dd[,"wg"])
# update with lapply
lapply(ls.form,update,object=baselm)
[[1]]

Call:
lm(formula = y ~ x1 + x2, data = dd, weights = dd[, "wg"])

Coefficients:
(Intercept)           x1           x2  
    0.07561      0.16111      0.15014  

...

有趣,我得把我的所有代码都混合起来,但我会尝试的。我会告诉你它的结果如何。 - Bastien
最后,你的解决方案对于这个问题是不错的,但它并没有解决我的问题(我认为它只是把问题转移到了别的地方...)。所以我接受了你的答案,但在这里提出了一个跟进问题:https://stackoverflow.com/questions/47909470/calling-update-within-a-lapply-within-a-function-why-isnt-it-working - Bastien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接