AIC, error anova: no todos los modelos se ajustan al mismo número de observaciones, no todos los modelos se ajustan al mismo tamaño de conjunto de datos

9

Tengo modelos como este:

require(nlme)

set.seed(123)
n <- 100
k <- 5
cat <- as.factor(rep(1:k, n))
cat_i <- 1:k # intercept per kategorie
x <- rep(1:n, each = k)
sigma <- 0.2
alpha <- 0.001
y <- cat_i[cat] + alpha * x + rnorm(n*k, 0, sigma)
plot(x, y)

m1 <- lm(y ~ x)
summary(m1)

m2 <- lm(y ~ cat + x)
summary(m2)

m3 <- lme(y ~ x, random = ~ 1|cat, na.action = na.omit)
summary(m3)

Ahora estoy tratando de evaluar si el efecto aleatorio debe estar presente en el modelo. Así que comparo los modelos usando AIC o anova, y obtengo el siguiente error:

> AIC(m1, m2, m3)
   df       AIC
m1  3 1771.4696
m2  7 -209.1825
m3  4 -154.0245
Warning message:
In AIC.default(m1, m2, m3) :
  models are not all fitted to the same number of observations  
> anova(m2, m3)
Error in anova.lmlist(object, ...) : 
  models were not all fitted to the same size of dataset

Como puede ver, en ambos casos utilizo el mismo conjunto de datos. He encontrado dos remedios, pero no los considero satisfactorios:

  1. Agregando method = "ML"a la llamada lme ​​() , no estoy seguro si es una buena idea cambiar el método.
  2. Usando en su lmer()lugar. Sorprendentemente, esto funciona, a pesar del hecho de que lmer () usa el método REML. Sin embargo, no me gusta esta solución porque lmer()no muestra los valores p para los coeficientes; en su lugar, me gusta usar los más antiguos lme().

¿Tienes alguna idea de si esto es un error o no y cómo podemos solucionarlo?

Curioso
fuente

Respuestas:

6

Una búsqueda rápida muestra que es posible (aunque tengo que admitir que pensé que no lo era) y que no es un error ... solo otro caso donde los métodos en R están ocultos y dan como resultado cosas que parecen 'inesperadas ', pero la multitud de RTFM dice: "Está en la documentación". De todos modos ... su solución tiene que ver anovacon el lmeprimer argumento y los lmmodelos como el segundo argumento (y el tercero si lo desea). Si esto parece extraño, es porque es un poco extraño. La razón es que cuando llama anova, el anova.lmemétodo se llama solo si el primer argumento es un lmeobjeto. De lo contrario, llama anova.lm(lo que a su vez llama anova.lmlist; si profundizas anova.lm, verás por qué). Para obtener detalles sobre cómo desea llamaranovaen este caso, busque ayuda para anova.lme. Verá que puede comparar otros modelos con lmemodelos, pero tienen que estar en una posición distinta al primer argumento. Aparentemente, también es posible usar anovamodelos ajustados usando la glsfunción sin preocuparse demasiado por el orden de los argumentos del modelo. Pero no conozco los detalles suficientes para determinar si es una buena idea o no, o qué implica exactamente (probablemente parece estar bien, pero es su decisión). A partir de ese enlace comparando lma lmeparece estar bien documentado y citó como un método, por lo que me equivoque en esa dirección, si yo fuera usted.

Buena suerte.

russellpierce
fuente
1
Ah, y la respuesta de user11852 con respecto a AIC con los apéndices de Gavin, no hay AIC.lme especial ni nada para abordar ese problema y todo comienza a ir más allá de mi calificación salarial
russellpierce
3

m2m3MLREMLykkX=0method="ML"

Dicho esto, echemos un vistazo debajo del 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")
     }     
 }

donde en tu caso puedes ver que:

  lls <- lapply(list(m2,m3), stats4::logLik)
  attr(lls[[1]], "nobs")
  #[1] 500
  attr(lls[[2]], "nobs")
  #[1] 498

y obviamente logLikestá haciendo algo (¿tal vez?) inesperado ... no, no realmente, si miras la documentación de logLik, ?logLikverás que se declara explícitamente:

 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’)

lo que nos lleva de vuelta a nuestro punto original, deberías estar usando ML.

Para usar un dicho común en CS: "¡No es un error; es una característica (real)!"

EDITAR : (Solo para abordar su comentario :) Suponga que se ajusta a otro modelo usando lmeresta vez:

m3lmer <- lmer(y ~ x + 1|cat)

y haces lo siguiente:

lls <- lapply(list(m2,m3, m3lmer), stats4::logLik)
attr(lls[[3]], "nobs")
#[1] 500
 attr(lls[[2]], "nobs")
#[1] 498

Lo que parece una clara discrepancia entre los dos, pero en realidad no es como lo explicó Gavin. Solo para decir lo obvio:

 attr( logLik(lme(y ~ x, random = ~ 1|cat, na.action = na.omit, method="ML")),
 "nobs")
#[1] 500

Hay una buena razón por la que esto sucede en términos de metodología, creo. lmeintenta darle sentido a la regresión LME mientras que lmeral hacer comparaciones de modelos recurre inmediatamente a sus resultados de ML. Creo que no hay errores en este asunto lmey lmersolo diferentes razones detrás de cada paquete.

Vea también el comentario de Gavin Simposon sobre una explicación más perspicaz de lo que sucedió anova()(lo mismo sucede prácticamente con AIC)

usεr11852
fuente
"deberías estar usando ML", pero ¿cómo puedes explicar que estás lmerusando REML (ver el resumen del modelo) y funciona bien en AIC? Por lo tanto, hay dos posibilidades: 1) el mensaje de error es * una característica , no un error, y el hecho de que funcione lmeres un error. O 2) el mensaje de error es un error , no una característica.
Curioso
Ver publicación actualizada (tuve que incluir algún código). Yo mismo había notado su punto válido al escribir su respuesta original, pero originalmente opté por mantenerlo fuera, por lo que la razón detrás de mi respuesta está estrictamente basada en la computación.
usεr11852
3
@Tomas lmer() no usa REML cuando le pides que haga comparaciones. IIRC incluyeron un poco de azúcar sofisticado, lmer()por lo que no tuvo que reajustar el modelo MLsolo para comparar ajustes cuando desea REMLen ajustes individuales para obtener las mejores estimaciones de los parámetros de varianza. Mire ?lmer, ejecute el primer ejemplo de LME hasta e incluyendo la anova(fm1, fm2)llamada. Observe las probabilidades de registro informadas por anova()y las informadas anteriormente en el resultado impreso. El anova()está obteniendo estimaciones de ML para usted.
Gavin Simpson
Buen punto Gavin, me olvido de que lmerobtuve ambas cosas al mismo tiempo (usa PLS, por lo que da vueltas estimando solo una a la vez). Olvidé comprobar lo que mencionaste.
usεr11852
2
@rpierce: El AIC reportado dentroanova() es el basado en ML. La AIC informada AIC()es la que se basa en REML.
usεr11852