Isso é peculiar definitivamente. Como um primeiro pensamento: ao fazer a comparação de modelos em que os modelos estão tendo diferentes estruturas de efeitos fixos ( m2
e, m3
por exemplo), é melhor para nós o pois "mudará" . (Ele será multiplicado por , onde ) Isso é interessante porque funciona usando o que me faz acreditar que pode não ser um bug. Parece quase que aplica "boas práticas".y k k X = 0MLREML
ykkX=0method="ML"
Dito isto, vamos olhar sob o capô:
methods(AIC)
getAnywhere('AIC.default')
A single object matching ‘AIC.default’ was found
It was found in the following places
registered S3 method for AIC from namespace stats
namespace:stats with value
function (object, ..., k = 2)
{
ll <- if ("stats4" %in% loadedNamespaces())
stats4:::logLik
else logLik
if (!missing(...)) {
lls <- lapply(list(object, ...), ll)
vals <- sapply(lls, function(el) {
no <- attr(el, "nobs") #THIS IS THE ISSUE!
c(as.numeric(el), attr(el, "df"), if (is.null(no)) NA_integer_ else no)
})
val <- data.frame(df = vals[2L, ], ll = vals[1L, ])
nos <- na.omit(vals[3L, ])
if (length(nos) && any(nos != nos[1L]))
warning("models are not all fitted to the same number of observations")
val <- data.frame(df = val$df, AIC = -2 * val$ll + k * val$df)
Call <- match.call()
Call$k <- NULL
row.names(val) <- as.character(Call[-1L])
val
}
else {
lls <- ll(object)
-2 * as.numeric(lls) + k * attr(lls, "df")
}
}
onde no seu caso você pode ver que:
lls <- lapply(list(m2,m3), stats4::logLik)
attr(lls[[1]], "nobs")
#[1] 500
attr(lls[[2]], "nobs")
#[1] 498
e obviamente logLik
está fazendo algo (talvez?) inesperado ...? não, na verdade, se você olhar para a documentação de logLik
, ?logLik
verá que está explicitamente declarado:
There may be other attributes depending on the method used: see
the appropriate documentation. One that is used by several
methods is ‘"nobs"’, the number of observations used in estimation
(after the restrictions if ‘REML = TRUE’)
o que nos leva de volta ao nosso ponto original, você deveria estar usando ML
.
Para usar um ditado comum no CS: "Não é um bug; é um recurso (real)!"
EDIT : (Apenas para endereçar seu comentário :) Suponha que você se enquadre em outro modelo usando lmer
este tempo:
m3lmer <- lmer(y ~ x + 1|cat)
e você faz o seguinte:
lls <- lapply(list(m2,m3, m3lmer), stats4::logLik)
attr(lls[[3]], "nobs")
#[1] 500
attr(lls[[2]], "nobs")
#[1] 498
O que parece ser uma clara discrepância entre os dois, mas realmente não é como Gavin explicou. Apenas para afirmar o óbvio:
attr( logLik(lme(y ~ x, random = ~ 1|cat, na.action = na.omit, method="ML")),
"nobs")
#[1] 500
Há uma boa razão pela qual isso acontece em termos de metodologia, eu acho. lme
tenta entender a regressão LME para você enquanto, lmer
ao fazer comparações de modelos, ela volta imediatamente aos resultados de ML. Eu acho que não há bugs sobre esse assunto lme
e lmer
apenas diferentes razões por trás de cada pacote.
Veja também o comentário de Gavin Simposon sobre uma explicação mais perspicaz do que aconteceu anova()
(a mesma coisa acontece praticamente com AIC
)