ANOVA: cuando hay más de dos grupos
¿Por qué no hacer t-tests pareados?
Imagina que tienes cuatro grupos (A, B, C, D) y quieres saber si hay diferencias entre ellos. Tentación: hacer t-tests para cada par (A-B, A-C, A-D, B-C, B-D, C-D, seis tests). Mala idea.
Problema: cada t-test tiene un 5 % de probabilidad de dar un falso positivo. Seis tests = ~26 % de probabilidad de al menos un falso positivo. La tasa de error global se infla.
Solución: un único test que pregunta “¿hay alguna diferencia entre los grupos?”. Si sí, después haces los pares con corrección. Ese test es el ANOVA.
ANOVA conceptualmente
ANOVA compara dos cosas:
- Variabilidad entre grupos: qué tan distintas son las medias de cada grupo entre sí.
- Variabilidad dentro de los grupos: qué tan dispersos son los valores alrededor de su media de grupo.
El estadístico F es el cociente:
\[F = \frac{\text{varianza entre grupos}}{\text{varianza dentro de los grupos}}\]
Si F es grande, las diferencias entre grupos exceden la variabilidad interna, y rechazamos la hipótesis nula de “todas las medias son iguales”.
Supuestos clásicos:
- Normalidad dentro de cada grupo (chequeable con QQ-plot de los residuos).
- Homogeneidad de varianzas entre grupos (también llamada homocedasticidad).
- Independencia de las observaciones.
Si los supuestos se rompen visiblemente, hay alternativas.
ANOVA en R: aov() vs lm() + anova()
R ofrece dos formas. Resultados idénticos, pero la segunda es más extensible.
Forma 1: aov()
modelo_aov <- aov(Sepal.Length ~ Species, data = iris)
summary(modelo_aov)
#> Df Sum Sq Mean Sq F value Pr(>F)
#> Species 2 63.21 31.61 119.3 <2e-16 ***
#> Residuals 147 38.96 0.27Forma 2: lm() + anova()
modelo_lm <- lm(Sepal.Length ~ Species, data = iris)
anova(modelo_lm)
#> Analysis of Variance Table
#>
#> Response: Sepal.Length
#> Df Sum Sq Mean Sq F value Pr(>F)
#> Species 2 63.212 31.6060 119.26 < 2.2e-16 ***
#> Residuals 147 38.956 0.2650Output idéntico. Recomendación: usa la forma 2. El objeto lm es más general, puedes hacer summary(modelo_lm), predict(), confint() y diagnósticos con plot(modelo_lm). ANOVA es un caso particular de regresión lineal. Tratar la formulación como tal te conecta con todo el resto del ecosistema de modelos lineales (que veremos en los siguientes tutoriales del bloque 3).
Post-hoc: Tukey HSD para encontrar qué pares difieren
ANOVA te dice “hay alguna diferencia”. No te dice cuál. Para identificar pares específicos, usa un test post-hoc con corrección por comparaciones múltiples.
El más común: Tukey HSD (Honest Significant Difference).
TukeyHSD(modelo_aov)
#> Tukey multiple comparisons of means
#> 95% family-wise confidence level
#>
#> Fit: aov(formula = Sepal.Length ~ Species, data = iris)
#>
#> $Species
#> diff lwr upr p adj
#> versicolor-setosa 0.930 0.6862273 1.1737727 0
#> virginica-setosa 1.582 1.3382273 1.8257727 0
#> virginica-versicolor 0.652 0.4082273 0.8957727 0Cada fila es un par con:
- diff: diferencia de medias.
- lwr/upr: intervalo de confianza ajustado para múltiples comparaciones.
- p adj: p-value ajustado.
Tukey controla la tasa de error global al 5 % (family-wise error rate), no la de cada test individual. Es lo correcto para reportar.
Alternativas a Tukey:
pairwise.t.test()conp.adjust.method = "bonferroni"o"holm", más conservador, más flexible.- Dunnett: cuando solo te interesa comparar cada grupo con un control (no todos los pares).
Tipo I, II, III: la decisión que casi nadie entiende
Cuando hay dos o más factores en el ANOVA, el orden en que se incluyen en la fórmula afecta la descomposición de variabilidad. Hay tres “tipos” de sumas de cuadrados:
- Tipo I (secuencial): el que da
anova()por defecto. Cada efecto se evalúa después de los anteriores. - Tipo II: cada efecto se evalúa después de los efectos del mismo orden, pero antes que las interacciones que lo incluyen.
- Tipo III: cada efecto se evalúa después de todos los demás efectos. Es el que usa SPSS por defecto y suele ser lo que el resto del mundo asume.
Cuándo importa: cuando el diseño no es balanceado (distinto número de observaciones por grupo). En diseños balanceados, los tres tipos dan resultados idénticos.
Para Tipo II o III en R, usa el paquete car:
library(car)
modelo <- lm(Sepal.Length ~ Species * Petal.Width, data = iris)
Anova(modelo, type = 2) # Tipo II
Anova(modelo, type = 3) # Tipo IIINo te obsesiones con esto en tu primer ANOVA. Es importante cuando publicas papers con diseños complejos. Hasta entonces, Tipo I (anova() base) está bien si el diseño es balanceado.
Kruskal-Wallis: alternativa no-paramétrica
Si los supuestos de ANOVA se rompen (no normalidad clara, varianzas muy distintas, datos ordinales), Kruskal-Wallis es la versión robusta:
kruskal.test(Sepal.Length ~ Species, data = iris)Compara distribuciones, no medias. Si rechazas H₀, sabes que al menos una distribución difiere de las otras.
Post-hoc no-paramétrico: dunn.test::dunn.test() (de un paquete externo) o pairwise.wilcox.test().
Trampas habituales
- ANOVA con
nmuy distinto por grupo. No es un problema técnico (R lo maneja), pero los tipos de sumas de cuadrados sí. Para diseños desbalanceados serios, usa Tipo II o III explícitamente. - Reportar ANOVA significativo sin post-hoc. “Hay alguna diferencia” no es un hallazgo accionable. Sigue con Tukey o equivalente para decir cuáles pares difieren.
- Olvidar diagnóstico. Si los residuos del modelo son visiblemente no normales o heterocedásticos, el ANOVA es sospechoso.
plot(modelo)te enseña los gráficos diagnósticos en una línea. - Múltiples ANOVAs como sustituto de un MANOVA. Si tienes varias variables dependientes correlacionadas, hacer un ANOVA por cada una infla el error tipo I. Para eso existe MANOVA (multivariante), fuera del scope de este tutorial.
En la siguiente entrega
Has aprendido a comparar tres o más grupos. Has cubierto los tests paramétricos clásicos. La siguiente entrega abre el bloque 2 con los tests sobre datos categóricos: tablas cruzadas, chi-cuadrado y el test de Fisher para frecuencias bajas. Es lo siguiente.