ANOVA y comparación de grupos
"Cuando tenés más de dos grupos, una sola prueba t no alcanza. Y muchas pruebas t a la vez te mienten."
Qué vas a aprender en este capítulo
En el capítulo 4 viste pruebas t para comparar dos grupos. Pero la realidad rara vez es de dos: comparás 3 sucursales de la pupusería, 4 algoritmos de ML, 5 tratamientos médicos, 6 turnos de producción. Si hacés una prueba t entre cada par, la probabilidad de un falso positivo se dispara.
ANOVA (Analysis of Variance) resuelve esto: una sola prueba para "¿hay alguna diferencia entre los grupos?". Si el resultado es significativo, después usás comparaciones post-hoc para identificar cuál grupo difiere de cuál, con el error tipo I controlado.
Es la herramienta más usada en:
- Control de calidad (¿las 3 líneas de producción dan la misma media?).
- A/B/C tests (¿alguna de las 4 versiones del homepage convierte distinto?).
- Investigación experimental (¿algún tratamiento difiere del placebo?).
- Industrial (Six Sigma, DOE — Design of Experiments).
- AED / negocios (¿alguna región vende distinto?).
6.1 La idea: una pregunta global, después detalle
💡 Intuición
Tenés tres pupuserías (San Miguel, Santa Ana, La Unión). Querés saber si la venta diaria promedio es distinta entre ellas. Tenés 30 días de datos por cada una.
Tentación incorrecta: hacer 3 pruebas t (SM vs SA, SM vs LU, SA vs LU). El problema: cada prueba tiene 5 % de probabilidad de error tipo I. Con 3 pruebas, al menos una falla por azar con probabilidad ~14 %. Con 5 grupos serían 10 pruebas y la probabilidad de error global sube a ~40 %.
ANOVA pregunta primero una sola cosa: "¿al menos un grupo es distinto de los demás?". Si la respuesta es sí (rechazás global), entonces hacés comparaciones por pares con corrección para mantener el error global controlado.
ANOVA es la versión "estadísticamente honesta" de comparar varios grupos.
6.2 La pregunta y las hipótesis
📐 Fundamento
Para grupos con medias poblacionales :
No es (que serían todas distintas). Cualquier desviación rompe .
Si rechazamos , sabemos que algo difiere — pero no qué. Para eso vienen las comparaciones post-hoc.
6.3 La idea matemática: comparar variabilidades
📐 Fundamento
ANOVA descompone la variabilidad total en dos fuentes:
- SSB (between): ¿qué tan distinto es cada grupo del promedio global? Mide el "efecto" del grupo.
- SSW (within): ¿qué tanto varían los datos adentro de cada grupo? Mide el "ruido".
Donde es el número de grupos y es el total de observaciones.
Lectura:
- Si es grande → la variabilidad entre grupos es mayor que la variabilidad dentro → algún grupo se aparta. Rechazo .
- Si es cercano a 1 → entre y dentro varían parecido → no hay efecto del grupo. No rechazo.
Bajo , sigue una distribución F con grados de libertad . El p-value es .
Tabla ANOVA tradicional
| Fuente | SS | gl | MS | F |
|---|---|---|---|---|
| Entre grupos | SSB | |||
| Dentro de grupos | SSW | |||
| Total | SST |
Tu output de R, Python o SPSS te da exactamente esa tabla. Lo que importa interpretar es la columna del p-value.
6.4 Supuestos (y cuándo se rompen)
📐 Fundamento
ANOVA asume:
- Independencia de las observaciones (entre y dentro de grupos).
- Normalidad de los residuos en cada grupo.
- Homocedasticidad (varianzas iguales entre grupos).
Cómo chequearlos
| Supuesto | Test gráfico | Test formal |
|---|---|---|
| Normalidad | QQ-plot | Shapiro-Wilk, Anderson-Darling |
| Homocedasticidad | Boxplot por grupo | Levene, Bartlett |
| Independencia | Inspección del diseño | Durbin-Watson (si hay orden temporal) |
¿Qué pasa si fallan?
- Normalidad falla pero grande (>30 por grupo): ANOVA es robusto por TLC. Ignorá.
- Normalidad falla con chico: usá Kruskal-Wallis (no paramétrica).
- Homocedasticidad falla: usá Welch's ANOVA (no asume varianzas iguales) o transformá los datos (log, raíz).
- Independencia falla: tu diseño está mal. Repensá el experimento — no hay test que arregle violación de independencia.
6.5 ANOVA en código
🛠️ Aplicado
import pandas as pd
import scipy.stats as stats
import statsmodels.api as sm
from statsmodels.formula.api import ols
# Datos: ventas diarias en 3 pupuserías, 30 días cada una
sm_ventas = [120, 135, 128, ...] # San Miguel
sa_ventas = [110, 115, 108, ...] # Santa Ana
lu_ventas = [125, 130, 132, ...] # La Unión
# Versión rápida con scipy
F, p = stats.f_oneway(sm_ventas, sa_ventas, lu_ventas)
print(f"F = {F:.2f}, p = {p:.4f}")
# Versión completa con statsmodels (para tabla y post-hoc)
df = pd.DataFrame({
'venta': sm_ventas + sa_ventas + lu_ventas,
'sucursal': ['SM']*30 + ['SA']*30 + ['LU']*30,
})
modelo = ols('venta ~ C(sucursal)', data=df).fit()
print(sm.stats.anova_lm(modelo))
Output típico:
sum_sq df F PR(>F)
C(sucursal) 1234.5 2 8.21 0.0006
Residual 3456.7 87
→ rechazás . Hay alguna diferencia. Ahora, ¿cuál?
6.6 Comparaciones post-hoc
📐 Fundamento
Cuando ANOVA rechaza, hacés comparaciones por pares con corrección por comparaciones múltiples.
Bonferroni (la más simple)
Hacés pruebas t por pares y usás .
Para 3 grupos: 3 pares, . Una diferencia es significativa solo si .
Pro: simple, conservadora, válida en cualquier diseño. Con: muy conservadora cuando hay muchos grupos. Pierde poder.
Tukey HSD (Honest Significant Difference)
Diseñada específicamente para ANOVA. Más potente que Bonferroni y mantiene el FWER (Family-Wise Error Rate) en .
from statsmodels.stats.multicomp import pairwise_tukeyhsd
resultado = pairwise_tukeyhsd(df['venta'], df['sucursal'], alpha=0.05)
print(resultado)
Output:
group1 group2 meandiff lower upper reject
LU SA -16.3 -22.1 -10.5 True
LU SM -2.1 -7.9 3.7 False
SA SM 14.2 8.4 20.0 True
Lectura: La Unión vende más que Santa Ana (significativo). San Miguel vende más que Santa Ana (significativo). LU y SM no se distinguen.
Otras alternativas
- Dunnett: cuando hay un grupo control y comparás cada tratamiento contra él.
- Scheffé: muy conservadora, útil con contrastes complejos.
- Holm-Bonferroni: versión secuencial de Bonferroni, más potente.
Regla práctica: Tukey HSD por default; Dunnett si hay control claro.
6.7 ANOVA de dos factores (two-way)
📐 Fundamento
Cuando tenés dos factores categóricos simultáneos (p. ej., sucursal × día de la semana), ANOVA two-way mide:
- Efecto del factor A (sucursal).
- Efecto del factor B (día).
- Interacción A × B (¿el efecto de sucursal depende del día?).
modelo = ols('venta ~ C(sucursal) + C(dia) + C(sucursal):C(dia)', data=df).fit()
print(sm.stats.anova_lm(modelo, typ=2))
La interacción es el output más importante: si es significativa, no podés interpretar los efectos principales aisladamente. Una sucursal puede ser la mejor los lunes y la peor los viernes — promedios globales engañan.
Si tenés > 2 factores, estás en territorio de DOE (Design of Experiments). Six Sigma y manufactura usan diseños fraccionales (Taguchi, Plackett-Burman) para explorar muchos factores con pocos experimentos.
6.8 Cuando los supuestos fallan: no paramétricas
🛠️ Aplicado
Si la normalidad falla y es chico, o tus datos son ordinales (rankings, escalas Likert), ANOVA no aplica. Las alternativas:
| Comparación | Paramétrica | No paramétrica |
|---|---|---|
| 2 grupos independientes | Prueba t | Mann-Whitney U (Wilcoxon rank-sum) |
| 2 grupos pareados | t pareada | Wilcoxon signed-rank |
| grupos independientes | ANOVA one-way | Kruskal-Wallis |
| grupos pareados | ANOVA repeated measures | Friedman |
# Kruskal-Wallis con scipy
H, p = stats.kruskal(sm_ventas, sa_ventas, lu_ventas)
print(f"H = {H:.2f}, p = {p:.4f}")
# Si rechaza, post-hoc no paramétrico:
import scikit_posthocs as sp
sp.posthoc_dunn(df, val_col='venta', group_col='sucursal', p_adjust='bonferroni')
Las no paramétricas comparan medianas (o mejor: distribuciones), no medias. Pierden algo de poder cuando los datos sí son normales, pero son robustas.
6.9 ANOVA es regresión
💡 Intuición
Algo que muchos textos esconden: ANOVA es matemáticamente equivalente a una regresión lineal con variables categóricas (dummies). El F-test del cap. 5 (regresión) y el F-test de ANOVA son el mismo test.
# Estos dos modelos dan resultados idénticos:
ols('venta ~ C(sucursal)', data=df).fit() # ANOVA
ols('venta ~ sucursal_SA + sucursal_LU', data=df).fit() # Regresión con dummies
Eso significa que regresión múltiple generaliza ANOVA: podés mezclar predictores numéricos y categóricos en un mismo modelo. Esa es la conexión natural con Machine Learning, donde casi todo se modela como regresión.
Si entendés ANOVA, ya entendés casi toda regresión. Y si entendés regresión, ya entendés gran parte de ML.
6.10 Errores comunes
⚠️ Trampa común
Hacer múltiples pruebas t en lugar de ANOVA. "Compararé pares uno por uno y veré cuál es significativo." Como vimos, con 5 grupos y 10 comparaciones, la probabilidad de al menos un falso positivo sube a ~40 %. Vas a "encontrar" diferencias que no existen.
Tip: ANOVA primero. Si rechaza, post-hoc con corrección. Nunca el atajo.
⚠️ Trampa común
Ignorar la interacción en ANOVA two-way. Cuando hay interacción significativa, los efectos principales pierden interpretación: el factor A actúa distinto según el nivel de B. Reportar solo "el efecto de sucursal es significativo" sin mencionar que depende del día es engañoso.
Tip: siempre graficá la interacción (interaction plot: medias por celda). Si las líneas no son paralelas, hay interacción y eso debe ir en la interpretación.
⚠️ Trampa común
Usar ANOVA con varianzas muy distintas y muestras desbalanceadas. ANOVA clásica asume homocedasticidad. Es robusta cuando los grupos están balanceados (mismo ). Pero con grupos desiguales y varianzas distintas, los p-values se vuelven poco confiables.
Tip: chequeá Levene primero. Si rechaza, usá Welch's ANOVA (stats.f_oneway no la incluye; usá pingouin.welch_anova) que no asume igual varianza. O transformá la variable (log si la variabilidad escala con la media).
6.11 Resumen visual
¿Cuántos grupos tenés que comparar?
│
┌────┼────┐
2 │ k>2
│
┌─── ┼ ────┐
Indep. Pareados
│ │
Mann-Wh. Wilcoxon (2 grupos no paramétrica)
t-test t pareada
│ │
¿Normalidad + homocedasticidad OK?
│
┌───┴───┐
Sí No
│ │
ANOVA Kruskal-Wallis (k grupos)
│ │
¿Sig.? ¿Sig.?
│ │
Tukey Dunn
HSD + Bonferroni
6.12 Ejercicios
- Tres profesores califican el mismo examen de 30 estudiantes (cada profe ve los 30, en orden distinto). ¿Qué versión de ANOVA usás (one-way, two-way, repeated measures)? ¿Por qué?
- Diseñá un A/B/C test para 3 versiones de un email de marketing. Calculá el tamaño muestral mínimo para detectar un efecto de 2 puntos porcentuales en click rate, con poder 0.80.
- Bajá el dataset Iris. Hacé ANOVA one-way de "petal_length" por especie. Reportá F, p, y conclusión. Hacé Tukey post-hoc.
- Mostrá con simulación que hacer 10 pruebas t pareadas con produce error tipo I global de ~40 %. (Pista: generá datos sin diferencias, hacé las pruebas, contá cuántas rechazan, repetí 1000 veces.)
- ¿Cuándo usás Kruskal-Wallis y cuándo Welch's ANOVA? Da un ejemplo de cada uno.
6.13 Para profundizar
- Walpole et al., capítulo sobre ANOVA — explicación clásica y completa.
- Field, Discovering Statistics Using R — el libro más amigable sobre ANOVA en práctica.
- statsmodels y pingouin (Python) — librerías con todo lo del capítulo, ya implementado.
- Six Sigma Body of Knowledge — para aplicaciones en control de calidad y manufactura.
- Statistical Rethinking (McElreath) — para entender el puente desde ANOVA a modelos bayesianos modernos.
6.14 Mini-proyecto integrador
🏗️ Proyecto final — Un experimento ANOVA real
Alcance: diseñá, ejecutá y reportá un experimento real con grupos.
Ideas viables (elegí una):
- ¿Tres rutas distintas al campus dan tiempos de viaje significativamente distintos? Mediálas 10 días cada una.
- ¿Cuatro recetas de pupusas tienen el mismo rating en una encuesta a 30 amigos?
- ¿Tres compiladores (gcc -O0, -O2, -O3) producen ejecutables con el mismo tiempo de ejecución sobre 30 benchmarks?
- ¿La calificación de un examen depende de la hora del día (mañana, tarde, noche)?
Entregables:
- Diseño previo (cap. 1-2 + 6) — hipótesis, factor(es), niveles, por grupo, supuesto de poder.
- Recolección — dataset crudo en CSV, sin tocar los outliers.
- EDA (cap. 4 de Estadística Descriptiva) — boxplot por grupo, descriptivos.
- Diagnósticos — Shapiro-Wilk + Levene. Reportá si fallan y qué hacés.
- ANOVA (one-way o two-way según el diseño). Reportá tabla F, p-value, (tamaño de efecto).
- Post-hoc — Tukey o Bonferroni. Identificá qué pares difieren.
- Reporte de 3 páginas con el formato APA: pregunta, métodos, resultados (con gráficos), discusión, limitaciones.
- Bonus: mismo análisis con Kruskal-Wallis. ¿Cambia la conclusión?
Criterio de éxito: alguien sin estadística entiende qué encontraste; alguien con estadística no encuentra agujeros metodológicos.
Tiempo estimado: 2 semanas.
Definiciones nuevas: ANOVA, F-test, SSB (between groups), SSW (within groups), MSB, MSW, distribución F, post-hoc, Bonferroni, Tukey HSD, Dunnett, FWER, ANOVA two-way, interacción, efectos principales, Welch's ANOVA, Kruskal-Wallis, Mann-Whitney U, Wilcoxon, Friedman, Dunn's test, ANOVA como regresión, eta cuadrado.