如何将命名列表传递给 R 中函数(特别是 anova)的点(`...`)参数? (替代 `do.call`)
How to pass a named list to the dots (`...`) argument of a function (specifically `anova`) in R? (alternatives to `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
;
如果模型名称是通过更改(可能是非连续的)数字给出的,则会出现问题。
我已经检查了可能存在重复的问题,因为
- How to pass a list to a function in R?
- Pass partial list of arguments to do.call()
- How to pass extra argument to the function argument of do.call in R
但一直没有找到满意的答案。
谢谢!
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
将(引用的)参数作为列表传递。然后我们在模型列表中评估此调用。
我会尽量避免在生产代码中使用它,因为它非常复杂,因此难以维护。
我有一个 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
;
如果模型名称是通过更改(可能是非连续的)数字给出的,则会出现问题。
我已经检查了可能存在重复的问题,因为
- How to pass a list to a function in R?
- Pass partial list of arguments to do.call()
- How to pass extra argument to the function argument of do.call in R
但一直没有找到满意的答案。
谢谢!
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
将(引用的)参数作为列表传递。然后我们在模型列表中评估此调用。
我会尽量避免在生产代码中使用它,因为它非常复杂,因此难以维护。