Comment passer une liste nommée à l'argument points (`…`) d'une fonction (spécifiquement `anova`) dans R? (alternatives à `do.call`)
J'ai une liste de sortie de modèles mixtes lme4::lmer
dont je veux passer et anova
qui a la forme anova(object, ...)
, alors je le fais
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
J'obtiens le résultat, mais avec les noms génériques signalés par l'avertissement, donc le même résultat que si models_list
n'était pas nommé. J'ai demandé aussi sur github (https://github.com/lme4/lme4/issues/612), mais l'utilisation do.call
semble que je ne pourrai pas résoudre ce problème. Y a-t-il un autre moyen?
Exemple reproductible
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
de sorte que les noms de modèle fm1
, fm2
ont été remplacés par MODEL2
, MODEL1
; c'est un problème si les noms de modèle sont donnés en changeant des nombres (éventuellement non consécutifs).
J'ai vérifié d'éventuelles questions dont celles-ci seraient une sorte de duplicata, comme
- Comment passer une liste à une fonction dans R?
- Passer une liste partielle d'arguments à do.call ()
- Comment passer un argument supplémentaire à l'argument de fonction de do.call dans R
mais n’ont pas trouvé de réponse satisfaisante.
Merci!
Réponses
anova.merMod
utilise une évaluation non standard (NSE) pour obtenir les noms de modèle. Comme c'est souvent le cas, NSE pose plus de problèmes qu'il n'en vaut la peine. Voici une solution:
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
La solution crée un appel. Cela se fait avec la call
fonction comme d'habitude. Cependant, ici, nous devons passer les arguments (entre guillemets) sous forme de liste en utilisant do.call
. Nous évaluons ensuite cet appel dans la liste des modèles.
J'essaierais d'éviter d'avoir cela dans le code de production car c'est assez complexe et donc difficile à maintenir.