Normalidad
Residuos ~ N(0, σ²). Test: Shapiro-Wilk o Q-Q plot. ANOVA es robusto si n es grande.
Capítulo 2
Comparar k grupos con t-tests por pares requiere pruebas. Con k=5 grupos son 10 tests — la probabilidad de al menos un falso positivo se dispara (inflación del error tipo I). ANOVA prueba si todos los grupos tienen la misma media en un solo test.
Descomponemos la variabilidad total:
Donde y.
Un F grande indica que las medias de los grupos son significativamente diferentes.
import numpy as np
from scipy import stats
# Tres grupos
np.random.seed(42)
g1 = np.random.normal(5, 1, 30)
g2 = np.random.normal(6, 1, 30)
g3 = np.random.normal(7, 1, 30)
F, p = stats.f_oneway(g1, g2, g3)
print(f"F = {F:.3f}, p = {p:.4f}")
# p < 0.05 → rechazamos H0, al menos un grupo difiereDos factores (A y B) y su interacción:
Prueba tres hipótesis simultáneamente: efecto de A, efecto de B, e interacción A×B. Ej: ¿El fármaco funciona? ¿El sexo influye? ¿Hay interacción (el fármaco funciona solo en mujeres)?
import statsmodels.api as sm
from statsmodels.formula.api import ols
import pandas as pd
df = pd.DataFrame({
'rendimiento': np.random.randn(60),
'metodo': np.repeat(['A', 'B', 'C'], 20),
'nivel': np.tile(['bajo', 'alto'], 30)
})
modelo = ols('rendimiento ~ C(metodo) + C(nivel) + C(metodo):C(nivel)', data=df).fit()
print(sm.stats.anova_lm(modelo, typ=2))Residuos ~ N(0, σ²). Test: Shapiro-Wilk o Q-Q plot. ANOVA es robusto si n es grande.
Varianza igual entre grupos. Test: Levene o Bartlett.
Observaciones independientes dentro y entre grupos. Diseño experimental.
# Tests de supuestos
from scipy import stats
# Normalidad (Shapiro-Wilk)
for i, g in enumerate([g1, g2, g3]):
W, p = stats.shapiro(g)
print(f"Grupo {i+1}: W={W:.3f}, p={p:.3f}")
# Homocedasticidad (Levene)
W, p = stats.levene(g1, g2, g3)
print(f"Levene: W={W:.3f}, p={p:.3f}")Si ANOVA es significativo, necesitamos pruebas post-hoc con corrección por comparaciones múltiples:
Compara todos los pares. Controla el error familiar (FWER). Más potente que Bonferroni.
Ajusta α dividiendo por número de comparaciones. Conservador.
from scipy.stats import tukey_hsd
result = tukey_hsd(g1, g2, g3)
print("Tukey HSD:")
for i in range(3):
for j in range(i+1, 3):
print(f" Grupo {i+1} vs {j+1}: p={result.pvalue[i,j]:.4f}")