首页 > 解决方案 > 如何将命名列表传递给R中函数(特别是`anova`)的点(`...`)参数?(“do.call”的替代品)

问题描述

我有一个混合模型输出列表,lme4::lmer我想将其传递给anova其中的表单anova(object, ...),所以我这样做了

models_list <- list("lmm1" = lmm1, "lmm2" = lmm2, "lmm3" = lmm3, "lmm4" = lmm4, "lmm5" = lmm5)
do.call(anova, c(models_list[[1]], models_list[-1]))
Warning in anova.merMod(new("lmerMod", resp = new("lmerResp", .xData = <environment>),  :
  failed to find model names, assigning generic names

我得到了结果,但是警告中注明了通用名称,因此与models_list未命名的结果相同。我也在 github(https://github.com/lme4/lme4/issues/612)上问过,但使用do.call似乎我无法解决这个问题。还有其他方法吗?

可重现的例子

library(lme4)
fm1 <- lmer(Reaction ~ Days + (Days | Subject), sleepstudy)
fm2 <- lmer(Reaction ~ Days + (Days || Subject), sleepstudy)
anova(fm1,fm2)
refitting model(s) with ML (instead of REML)
Data: sleepstudy
Models:
fm2: Reaction ~ Days + ((1 | Subject) + (0 + Days | Subject))
fm1: Reaction ~ Days + (Days | Subject)
    npar    AIC    BIC  logLik deviance  Chisq Df Pr(>Chisq)
fm2    5 1762.0 1778.0 -876.00   1752.0                     
fm1    6 1763.9 1783.1 -875.97   1751.9 0.0639  1     0.8004
# so I can see fm2 and fm2, to which model corresponds each line, but
models_list <- list("fm1" = fm1, "fm2" = fm2)
do.call(anova, c(lmaux[[1]], lmaux[-1]))
Warning in anova.merMod(new("lmerMod", resp = new("lmerResp", .xData = <environment>),  :
  failed to find model names, assigning generic names
refitting model(s) with ML (instead of REML)
Data: sleepstudy
Models:
MODEL2: Reaction ~ Days + ((1 | Subject) + (0 + Days | Subject))
MODEL1: Reaction ~ Days + (Days | Subject)
       npar    AIC    BIC  logLik deviance  Chisq Df Pr(>Chisq)
MODEL2    5 1762.0 1778.0 -876.00   1752.0                     
MODEL1    6 1763.9 1783.1 -875.97   1751.9 0.0639  1     0.8004

所以型号名称fm1,fm2被替换为MODEL2, MODEL1; 如果模型名称是通过更改(可能是非连续的)数字给出的,这将是一个问题。

我已经检查了可能的问题,这些问题可能是一种重复,因为

但还没有找到满意的答案。

谢谢!

标签: rlistlme4anovado.call

解决方案


anova.merMod使用非标准评估 (NSE) 来获取模型名称。通常情况下,NSE 带来的麻烦多于其价值。这是一个解决方案:

eval(
  do.call(
    call, 
    c(list("anova"), 
      lapply(names(models_list), as.symbol)), 
    quote = TRUE), 
  models_list)

#refitting model(s) with ML (instead of REML)
#Data: sleepstudy
#Models:
#fm2: Reaction ~ Days + ((1 | Subject) + (0 + Days | Subject))
#fm1: Reaction ~ Days + (Days | Subject)
#    npar    AIC    BIC  logLik deviance  Chisq Df Pr(>Chisq)
#fm2    5 1762.0 1778.0 -876.00   1752.0                     
#fm1    6 1763.9 1783.1 -875.97   1751.9 0.0639  1     0.8004

该解决方案创建一个呼叫。call像往常一样使用该功能完成。但是,在这里我们需要使用do.call. 然后我们在模型列表中评估这个调用。

我会尽量避免在生产代码中使用它,因为它非常复杂,因此难以维护。


推荐阅读