Wie übergebe ich eine benannte Liste an das Punktargument (`…`) einer Funktion (speziell `anova`) in R? (Alternativen zu `do.call`)

Dec 15 2020

Ich habe eine Liste gemischter Modelle, deren Ausgabe lme4::lmerich übergeben möchte, anovadie die Form hat anova(object, ...), also tue ich es

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

Ich erhalte das Ergebnis, aber mit den durch die Warnung vermerkten generischen Namen, also das gleiche Ergebnis, als ob models_listes nicht benannt worden wäre. Ich fragte auch auf Github (https://github.com/lme4/lme4/issues/612), aber mit do.callscheint, dass ich dieses Problem nicht lösen kann. Gibt es einen anderen Weg?

Reproduzierbares Beispiel

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

so die Modellnamen fm1, fm2wurden ersetzt durch MODEL2, MODEL1; Dies ist ein Problem, wenn die Modellnamen durch Ändern (möglicherweise nicht aufeinanderfolgender) Nummern angegeben werden.

Ich habe mögliche Fragen geprüft, bei denen es sich um eine Art Duplikat handeln würde

  • Wie übergebe ich eine Liste an eine Funktion in R?
  • Übergeben Sie eine unvollständige Liste von Argumenten an do.call ()
  • So übergeben Sie ein zusätzliches Argument an das Funktionsargument von do.call in R.

habe aber keine zufriedenstellende Antwort gefunden.

Vielen Dank!

Antworten

2 Roland Dec 15 2020 at 18:50

anova.merModVerwendet eine nicht standardmäßige Bewertung (NSE), um die Modellnamen abzurufen. Wie so oft ist NSE mehr Ärger als es wert ist. Hier ist eine Lösung:

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

Die Lösung erstellt einen Anruf. Dies geschieht callwie gewohnt mit der Funktion. Hier müssen wir jedoch die (zitierten) Argumente als Liste mit übergeben do.call. Wir bewerten diesen Aufruf dann in der Liste der Modelle.

Ich würde versuchen, dies im Produktionscode zu vermeiden, da es ziemlich komplex und daher schwierig zu warten ist.