Python Data Science Program
📓 Abrir notebook en GitHub

Clase 179 — ANOVA (one-way, two-way)

Parte: 3 — Estadística Inferencial y Causal · Fuente: ISLP, cap. 13 + Bruce & Bruce, cap. 3 ANOVA. ⏱️ Duración estimada: 80 min.

🎯 Objetivo

Que el alumno aplique ANOVA de una vía (≥ 3 grupos, una variable categórica) y ANOVA de dos vías (dos factores categóricos + interacción), entienda por qué no se hacen "t-tests todos contra todos" (inflación de α) y sepa hacer post-hoc con Tukey HSD. Reconocer los supuestos (independencia, normalidad por grupo, homogeneidad de varianzas) y cuándo usar la alternativa robusta Welch ANOVA o el no paramétrico Kruskal-Wallis (Clase 150).

📚 Resultados de aprendizaje

Al finalizar, el estudiante podrá:

🗺️ Temas

📖 Definiciones y características

📂 Dataset / recursos

🧪 Ejercicios

  1. One-way: aplicá scipy.stats.f_oneway(*[grupo for grupo in penguins.groupby('species').body_mass_g]). Reportá F, p y dof_between, dof_within.
  2. Supuestos: testá normalidad por grupo (pingouin.normality(penguins, dv='body_mass_g', group='species')) y homocedasticidad (pingouin.homoscedasticity). Si Levene rechaza, repetí con pingouin.welch_anova.
  3. Post-hoc Tukey: pingouin.pairwise_tukey(data=penguins, dv='body_mass_g', between='species'). Identificá qué pares de especies difieren significativamente.
  4. Two-way con interacción: pingouin.anova(data=tips, dv='total_bill', between=['day', 'time']). Mirá las tres filas de la tabla (day, time, day×time).
  5. Interaction plot: sns.pointplot(data=tips, x='day', y='total_bill', hue='time'). Si las líneas se cruzan o no son paralelas → hay interacción visual; cruzala con el p-value del término day*time.

📝 Homework verificable

Sobre penguins (filtrando filas con NA):

  1. ANOVA one-way de flipper_length_mm por species.
  2. Chequear Levene y Shapiro; decidir entre ANOVA clásico y Welch ANOVA, justificando.
  3. Tukey HSD post-hoc.
  4. Reportar ω² (pingouin.anova(... effsize='n2', y calcular ω² manualmente).
  5. Conclusión en 3 líneas: qué pares difieren, magnitud del efecto general (η²/ω²), si hay alguna comparación dudosa.

Criterio de aceptación: el ANOVA debe rechazar H₀ (p < 0.001), Tukey debe mostrar las tres parejas significativas, y η² debe ser > 0.5 (efecto grande — las tres especies tienen aletas claramente distintas).

⚠️ Errores comunes

Síntoma / mensaje Causa y cómo arreglar
Hago ttest_ind entre cada par de 4 grupos y reporto los p-values Con 4 grupos son 6 comparaciones; α efectivo ≈ 0.26. Fix: ANOVA + Tukey post-hoc, o ajustar con Bonferroni (Clase 151).
ANOVA da p < 0.05 pero ningún Tukey lo da Puede pasar con varianzas muy distintas. Fix: Welch ANOVA + Games-Howell post-hoc (pingouin.pairwise_gameshowell).
Aplico ANOVA con varianzas muy distintas (Levene p < 0.01) El F-test clásico es sensible a esto, especialmente con grupos desbalanceados. Fix: Welch ANOVA.
Los residuos no son normales y reporto ANOVA igual Si los grupos son grandes (n ≥ 30 c/u), TCL salva. Si son chicos y muy asimétricos, Fix: Kruskal-Wallis (Clase 150) o ANOVA con bootstrap.
Interpreto "efecto de A" sin mirar la interacción A×B significativa Si hay interacción, el efecto principal de A no es interpretable solo — depende del nivel de B. Fix: interpretar interacción primero; los main effects solo si la interacción es no significativa.

❓ Preguntas frecuentes

❓ ¿ANOVA o regresión lineal con dummies?

Son matemáticamente equivalentes. ANOVA es la presentación tradicional; OLS con dummies (statsmodels.formula.api.ols('y ~ C(species)', data).fit()) da los mismos F y p. La regresión también te da los coeficientes de cada nivel respecto a la categoría de referencia, lo cual es más informativo.

❓ ¿Tukey o Bonferroni post-hoc?

Tukey es mejor para todas-las-parejas porque controla el family-wise error rate de manera específica para ANOVA (es uniformemente más poderoso que Bonferroni en ese caso). Bonferroni es más conservador (peor poder). Ver Clase 151 para alternativas modernas (Holm, BH).

❓ ¿Qué pasa si los grupos están desbalanceados (n distinto)?

ANOVA aguanta moderadamente, pero con varianzas distintas el F-test se rompe. Welch ANOVA lo maneja bien.

❓ ¿Two-way ANOVA cuando alguna celda tiene n=0?

Modelo no balanceado: usar Type III SS (statsmodels lo soporta vía sm.stats.anova_lm(model, typ=3)). Type I (default) depende del orden de los factores en la fórmula.

❓ ¿Y si tengo medidas repetidas (mismo sujeto en cada nivel)?

pingouin.rm_anova (repeated measures ANOVA). Modela la correlación intra-sujeto, lo cual ANOVA clásico ignora.

🔗 Referencias

📥 Material descargable

➡️ Siguiente clase

Clase 180 — Tests no paramétricos: Mann-Whitney, Wilcoxon, Kruskal-Wallis