Jak przekazać nazwaną listę do argumentu kropek (`…`) funkcji (konkretnie `anova`) w R? (alternatywa dla `do.call`)
Mam listę wyjściowych modeli mieszanych, lme4::lmer
które chcę przekazać, do anova
której ma postać anova(object, ...)
, więc robię
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
Otrzymuję wynik, ale z nazwami rodzajowymi wymienionymi w ostrzeżeniu, a więc ten sam wynik, jakby models_list
nie został nazwany. Pytałem też na githubie (https://github.com/lme4/lme4/issues/612), ale użycie do.call
wydaje się, że nie będę w stanie rozwiązać tego problemu. Czy jest jakiś inny sposób?
Powtarzalny przykład
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
tak nazwami modeli fm1
, fm2
zostały zastąpione MODEL2
, MODEL1
; jest to problem, jeśli nazwy modeli są podawane poprzez zmianę (prawdopodobnie nie kolejnych) numerów.
Sprawdziłem możliwe pytania, których byłyby one swego rodzaju duplikatem, jak np
- Jak przekazać listę do funkcji w R?
- Przekaż częściową listę argumentów do do.call ()
- Jak przekazać dodatkowy argument do argumentu funkcji funkcji do.call w języku R
ale nie znalazłem zadowalającej odpowiedzi.
Dziękuję Ci!
Odpowiedzi
anova.merMod
używa niestandardowej oceny (NSE), aby uzyskać nazwy modeli. Jak to często bywa, NSE przysparza więcej kłopotów niż jest tego warte. Oto rozwiązanie:
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
Rozwiązanie tworzy połączenie. Odbywa się to z call
funkcją jak zwykle. Jednak tutaj musimy przekazać (w cudzysłowie) argumenty jako listę za pomocą do.call
. Następnie oceniamy to wezwanie w ramach listy modeli.
Chciałbym uniknąć tego w kodzie produkcyjnym, ponieważ jest dość złożony i dlatego trudny w utrzymaniu.