En realidad es no muy difícil manejar la heteroscedasticidad en modelos lineales simples (por ejemplo, modelos tipo ANOVA de una o dos vías).
Solidez del ANOVA
En primer lugar, como otros han señalado, el ANOVA es sorprendentemente robusto a las desviaciones del supuesto de varianzas iguales, especialmente si tiene datos aproximadamente equilibrados (igual número de observaciones en cada grupo). Por otra parte, las pruebas preliminares sobre varianzas iguales son no (aunque la prueba de Levene es mucho mejor que la F -prueba comúnmente enseñada en los libros de texto). Como dijo George Box:
Hacer la prueba preliminar de las desviaciones es más bien como hacerse a la mar en una barca de remos para averiguar si las condiciones son lo suficientemente tranquilas como para que un transatlántico abandone el puerto.
Aunque el ANOVA es muy robusto, ya que es muy fácil tener en cuenta la heteroscedaticidad, hay pocas razones para no hacerlo.
Pruebas no paramétricas
Si realmente le interesa diferencias de medias Las pruebas no paramétricas (por ejemplo, la prueba de Kruskal-Wallis) no son realmente útiles. Prueban las diferencias entre grupos, pero no no en la prueba general de diferencias de medias.
Ejemplo de datos
Vamos a generar un ejemplo sencillo de datos en los que uno desearía utilizar ANOVA, pero en los que el supuesto de varianzas iguales no es cierto.
set.seed(1232)
pop = data.frame(group=c("A","B","C"),
mean=c(1,2,5),
sd=c(1,3,4))
d = do.call(rbind, rep(list(pop),13))
d$x = rnorm(nrow(d), d$mean, d$sd)
Tenemos tres grupos, con diferencias (claras) tanto en las medias como en las varianzas:
stripchart(x ~ group, data=d)
ANOVA
No es sorprendente que un ANOVA normal maneje esto bastante bien:
> mod.aov = aov(x ~ group, data=d)
> summary(mod.aov)
Df Sum Sq Mean Sq F value Pr(>F)
group 2 199.4 99.69 13.01 5.6e-05 ***
Residuals 36 275.9 7.66
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
¿Qué grupos difieren? Utilicemos el método HSD de Tukey:
> TukeyHSD(mod.aov)
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = x ~ group, data = d)
$group
diff lwr upr p adj
B-A 1.736692 -0.9173128 4.390698 0.2589215
C-A 5.422838 2.7688327 8.076843 0.0000447
C-B 3.686146 1.0321403 6.340151 0.0046867
Con un P -valor de 0,26, no podemos afirmar que exista ninguna diferencia (en las medias) entre el grupo A y el B. E incluso si no tener en cuenta que hicimos tres comparaciones, no obtendríamos una baja P -valor ( P = 0.12):
> summary.lm(mod.aov)
[…]
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.5098 0.7678 0.664 0.511
groupB 1.7367 1.0858 1.599 0.118
groupC 5.4228 1.0858 4.994 0.0000153 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.768 on 36 degrees of freedom
¿Por qué? Basado en la trama, hay es una diferencia bastante clara. La razón es que el ANOVA supone varianzas iguales en cada grupo, y estima una desviación típica común de 2,77 (mostrada como "Error típico residual" en el summary.lm
o puede obtenerla tomando la raíz cuadrada del cuadrado medio residual (7,66) en la tabla ANOVA).
Pero el grupo A tiene una desviación típica (poblacional) de 1, y esta sobreestimación de 2,77 dificulta (innecesariamente) la obtención de resultados estadísticamente significativos, es decir, tenemos una prueba con una potencia (demasiado) baja.
ANOVA' con varianzas desiguales
Entonces, ¿cómo ajustar un modelo adecuado, que tenga en cuenta las diferencias en las varianzas? Es fácil en R:
> oneway.test(x ~ group, data=d, var.equal=FALSE)
One-way analysis of means (not assuming equal variances)
data: x and group
F = 12.7127, num df = 2.000, denom df = 19.055, p-value = 0.0003107
Por lo tanto, si desea ejecutar un simple 'ANOVA' unidireccional en R sin asumir varianzas iguales, utilice esta función. Es básicamente una extensión de la (Welch) t.test()
para dos muestras con varianzas desiguales.
Por desgracia, no funciona con TukeyHSD()
(o la mayoría de las funciones que utiliza en aov
objetos), por lo que incluso si estamos bastante seguros de que hay son diferencias de grupo, no sabemos donde lo son.
Modelización de la heteroscedasticidad
La mejor solución es modelar las varianzas explícitamente. Y es muy fácil en R:
> library(nlme)
> mod.gls = gls(x ~ group, data=d,
weights=varIdent(form= ~ 1 | group))
> anova(mod.gls)
Denom. DF: 36
numDF F-value p-value
(Intercept) 1 16.57316 0.0002
group 2 13.15743 0.0001
Sigue habiendo diferencias significativas, por supuesto. Pero ahora las diferencias entre los grupos A y B también han pasado a ser estadísticamente significativas ( P = 0.025):
> summary(mod.gls)
Generalized least squares fit by REML
Model: x ~ group
[…]
Variance function:
Structure: Different standard
deviations per stratum
Formula: ~1 | group
Parameter estimates:
A B C
1.000000 2.444532 3.913382
Coefficients:
Value Std.Error t-value p-value
(Intercept) 0.509768 0.2816667 1.809829 0.0787
groupB 1.736692 0.7439273 2.334492 0.0253
groupC 5.422838 1.1376880 4.766542 0.0000
[…]
Residual standard error: 1.015564
Degrees of freedom: 39 total; 36 residual
Así que utilizar un modelo adecuado ayuda. Obsérvese también que obtenemos estimaciones de las desviaciones típicas (relativas). La desviación típica estimada para el grupo A se encuentra en la parte inferior de los resultados: 1,02. La desviación típica estimada del grupo B es 2,44 veces mayor, es decir, 2,48, y la desviación típica estimada del grupo C es igualmente 3,97 (tipo intervals(mod.gls)
para obtener intervalos de confianza para las desviaciones estándar relativas de los grupos B y C).
Corrección de las pruebas múltiples
Sin embargo, realmente deberíamos corregir por pruebas múltiples. Esto es fácil utilizando la biblioteca 'multcomp'. Desafortunadamente, no tiene soporte incorporado para objetos 'gls', así que tendremos que añadir algunas funciones de ayuda primero:
model.matrix.gls <- function(object, ...)
model.matrix(terms(object), data = getData(object), ...)
model.frame.gls <- function(object, ...)
model.frame(formula(object), data = getData(object), ...)
terms.gls <- function(object, ...)
terms(model.frame(object),...)
Ahora manos a la obra:
> library(multcomp)
> mod.gls.mc = glht(mod.gls, linfct = mcp(group = "Tukey"))
> summary(mod.gls.mc)
[…]
Linear Hypotheses:
Estimate Std. Error z value Pr(>|z|)
B - A == 0 1.7367 0.7439 2.334 0.0480 *
C - A == 0 5.4228 1.1377 4.767 <0.001 ***
C - B == 0 3.6861 1.2996 2.836 0.0118 *
¡Sigue habiendo una diferencia estadísticamente significativa entre el grupo A y el grupo B! ☺ ¡Y hasta podemos obtener intervalos de confianza (simultáneos) para las diferencias entre las medias de los grupos!
> confint(mod.gls.mc)
[…]
Linear Hypotheses:
Estimate lwr upr
B - A == 0 1.73669 0.01014 3.46324
C - A == 0 5.42284 2.78242 8.06325
C - B == 0 3.68615 0.66984 6.70245
Utilizando un modelo aproximadamente (aquí exactamente) correcto, ¡podemos confiar en estos resultados!
Observe que para este sencillo ejemplo, los datos del grupo C no añaden realmente ninguna información sobre las diferencias entre los grupos A y B, ya que modelamos medias y desviaciones típicas separadas para cada grupo. Podríamos haber utilizado simplemente t -pruebas corregidas para comparaciones múltiples:
> pairwise.t.test(d$x, d$group, pool.sd=FALSE)
Pairwise comparisons using t tests with non-pooled SD
data: d$x and d$group
A B
B 0.03301 -
C 0.00098 0.02032
P value adjustment method: holm
Sin embargo, para modelos más complicados, por ejemplo, modelos de dos vías o modelos lineales con muchos predictores, la mejor solución es utilizar GLS (mínimos cuadrados generalizados) y modelizar explícitamente las funciones de varianza.
Y la función de varianza no tiene por qué ser simplemente una constante diferente en cada grupo; podemos imponerle una estructura. Por ejemplo, podemos modelizar la varianza como una potencia del media de cada grupo (y, por tanto, sólo es necesario estimar un el exponente), o quizás como el logaritmo de uno de los predictores del modelo. Todo esto es muy fácil con GLS (y gls()
en R).
Los mínimos cuadrados generalizados son, en mi opinión, una técnica de modelización estadística muy infrautilizada. En lugar de preocuparse por las desviaciones de los supuestos del modelo, modelo ¡esas desviaciones!