Lección 20 de 29Módulo 4: Estadística Aplicada

20. Testing de Hipótesis

T-tests, chi-cuadrado, ANOVA y interpretación de p-valores

25 minutos

Aprende a tomar decisiones basadas en datos con rigor estadístico. El testing de hipótesis te permite validar si tus hallazgos son estadísticamente significativos o simplemente producto del azar.

¿Por qué testing de hipótesis?

En análisis de datos, no basta con observar diferencias. Necesitas evidencia estadística para afirmar que:

  • Una campaña de marketing realmente aumentó las conversiones
  • El nuevo diseño de producto mejora la retención
  • Los usuarios de iOS gastan más que los de Android
  • La versión A de tu landing page convierte mejor que la B

El testing de hipótesis cuantifica la probabilidad de que tus hallazgos sean reales, no casualidad.

Caso real: E-commerce

Tu jefe dice: "Los usuarios que recibieron el email promocional gastaron $120 en promedio vs. $110 de los que no lo recibieron. ¡El email funciona!"

¿Pero es cierto? Con solo 50 usuarios en cada grupo, esa diferencia de $10 podría ser aleatoria. El testing de hipótesis te da la respuesta definitiva.

Conceptos fundamentales

1. Hipótesis nula (H₀) vs. alternativa (H₁)

  • H₀ (hipótesis nula): "No hay diferencia/efecto" → Es lo que queremos rechazar
  • H₁ (hipótesis alternativa): "Sí hay diferencia/efecto" → Es lo que queremos probar

Ejemplo:

  • H₀: La media de conversión del grupo A = grupo B (diferencia = 0)
  • H₁: La media de conversión del grupo A ≠ grupo B (diferencia ≠ 0)

2. P-valor: La métrica clave

El p-valor es la probabilidad de obtener tus resultados (o más extremos) si la hipótesis nula fuera cierta.

  • p < 0.05: Rechazamos H₀ → Evidencia significativa de diferencia
  • p ≥ 0.05: No rechazamos H₀ → Sin evidencia suficiente

💡 Interpretación correcta del p-valor: p=0.03 significa "hay 3% de probabilidad de ver esta diferencia por azar si no hubiera efecto real". NO significa "97% de probabilidad de que H₁ sea cierta".

3. Nivel de significancia (α)

El umbral que elegimos para rechazar H₀. Estándares comunes:

  • α = 0.05 (5%): Estándar en la mayoría de industrias
  • α = 0.01 (1%): Para decisiones más conservadoras
  • α = 0.10 (10%): Para análisis exploratorios

4. Tipos de errores

Error Descripción Consecuencia
Tipo I (α) Rechazar H₀ cuando es verdadera "Falso positivo" - Pensar que hay efecto cuando no lo hay
Tipo II (β) No rechazar H₀ cuando es falsa "Falso negativo" - Perder un efecto real

T-Test: Comparando dos grupos

T-test independiente (grupos diferentes)

Úsalo cuando comparas dos grupos distintos (ej: usuarios iOS vs. Android).

import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns

# Datos de ejemplo: Gasto promedio de usuarios iOS vs. Android
np.random.seed(42)

gasto_ios = np.random.normal(125, 30, 200)      # Media=$125, SD=$30, n=200
gasto_android = np.random.normal(110, 28, 220)  # Media=$110, SD=$28, n=220

# Visualización preliminar
plt.figure(figsize=(12, 5))

# Histogramas
plt.subplot(1, 2, 1)
plt.hist(gasto_ios, bins=30, alpha=0.7, label='iOS', color='blue', edgecolor='black')
plt.hist(gasto_android, bins=30, alpha=0.7, label='Android', color='green', edgecolor='black')
plt.xlabel('Gasto ($)')
plt.ylabel('Frecuencia')
plt.title('Distribución de Gasto por Plataforma')
plt.legend()
plt.grid(True, alpha=0.3)

# Boxplots
plt.subplot(1, 2, 2)
data_plot = pd.DataFrame({
    'Gasto': np.concatenate([gasto_ios, gasto_android]),
    'Plataforma': ['iOS']*len(gasto_ios) + ['Android']*len(gasto_android)
})
sns.boxplot(data=data_plot, x='Plataforma', y='Gasto', palette=['blue', 'green'])
plt.title('Comparación de Gasto: iOS vs. Android')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('comparacion_plataformas.png', dpi=300)
plt.show()

# Estadísticas descriptivas
print("=== ESTADÍSTICAS DESCRIPTIVAS ===\n")
print(f"iOS: Media=${gasto_ios.mean():.2f}, SD=${gasto_ios.std():.2f}, n={len(gasto_ios)}")
print(f"Android: Media=${gasto_android.mean():.2f}, SD=${gasto_android.std():.2f}, n={len(gasto_android)}")
print(f"Diferencia observada: ${gasto_ios.mean() - gasto_android.mean():.2f}")

# T-TEST INDEPENDIENTE
t_statistic, p_value = stats.ttest_ind(gasto_ios, gasto_android)

print(f"\n=== T-TEST INDEPENDIENTE ===\n")
print(f"Estadístico t: {t_statistic:.4f}")
print(f"P-valor: {p_value:.6f}")

# Interpretación
alpha = 0.05
if p_value < alpha:
    print(f"\n✅ RESULTADO: Rechazamos H₀ (p < {alpha})")
    print("Conclusión: Hay evidencia estadísticamente significativa de que")
    print("los usuarios iOS gastan más que los usuarios Android.")
else:
    print(f"\n❌ RESULTADO: No rechazamos H₀ (p ≥ {alpha})")
    print("Conclusión: No hay evidencia suficiente de diferencia en gasto.")

# Tamaño del efecto (Cohen's d)
def cohens_d(group1, group2):
    """Calcula el tamaño del efecto Cohen's d"""
    n1, n2 = len(group1), len(group2)
    var1, var2 = np.var(group1, ddof=1), np.var(group2, ddof=1)
    pooled_std = np.sqrt(((n1-1)*var1 + (n2-1)*var2) / (n1+n2-2))
    return (np.mean(group1) - np.mean(group2)) / pooled_std

d = cohens_d(gasto_ios, gasto_android)
print(f"\nTamaño del efecto (Cohen's d): {d:.3f}")

if abs(d) < 0.2:
    print("  → Efecto pequeño (d < 0.2)")
elif abs(d) < 0.5:
    print("  → Efecto pequeño a moderado (0.2 ≤ d < 0.5)")
elif abs(d) < 0.8:
    print("  → Efecto moderado a grande (0.5 ≤ d < 0.8)")
else:
    print("  → Efecto grande (d ≥ 0.8)")

T-test pareado (mismo grupo, antes/después)

Úsalo cuando comparas el mismo grupo en dos momentos (ej: usuarios antes y después de un cambio).

# Datos de ejemplo: Tiempo en página antes y después de rediseño
np.random.seed(123)
n_usuarios = 150

tiempo_antes = np.random.normal(180, 45, n_usuarios)  # 180 segundos promedio
tiempo_despues = tiempo_antes + np.random.normal(25, 30, n_usuarios)  # Aumenta ~25 seg

# Crear DataFrame
data_pareado = pd.DataFrame({
    'usuario_id': range(1, n_usuarios + 1),
    'antes': tiempo_antes,
    'despues': tiempo_despues,
    'diferencia': tiempo_despues - tiempo_antes
})

print("=== DATOS PAREADOS: REDISEÑO DE PÁGINA ===\n")
print(data_pareado.head(10))

# Visualización
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Antes vs. Después
axes[0].scatter(data_pareado['antes'], data_pareado['despues'], alpha=0.5)
axes[0].plot([0, 300], [0, 300], 'r--', linewidth=2, label='Sin cambio')
axes[0].set_xlabel('Tiempo Antes (seg)')
axes[0].set_ylabel('Tiempo Después (seg)')
axes[0].set_title('Comparación Antes vs. Después')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

# Distribución de diferencias
axes[1].hist(data_pareado['diferencia'], bins=30, edgecolor='black')
axes[1].axvline(x=0, color='red', linestyle='--', linewidth=2, label='Sin diferencia')
axes[1].set_xlabel('Diferencia (Después - Antes)')
axes[1].set_ylabel('Frecuencia')
axes[1].set_title('Distribución de Diferencias')
axes[1].legend()
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('ttest_pareado.png', dpi=300)
plt.show()

# T-TEST PAREADO
t_stat_pareado, p_value_pareado = stats.ttest_rel(data_pareado['despues'], data_pareado['antes'])

print(f"\n=== T-TEST PAREADO ===\n")
print(f"Media antes: {data_pareado['antes'].mean():.2f} seg")
print(f"Media después: {data_pareado['despues'].mean():.2f} seg")
print(f"Diferencia promedio: {data_pareado['diferencia'].mean():.2f} seg")
print(f"\nEstadístico t: {t_stat_pareado:.4f}")
print(f"P-valor: {p_value_pareado:.6f}")

if p_value_pareado < 0.05:
    print("\n✅ El rediseño aumentó significativamente el tiempo en página")
else:
    print("\n❌ No hay evidencia de cambio significativo")

⚠️ Cuándo usar cada t-test:

  • Independiente: Grupos diferentes (iOS vs. Android, Control vs. Tratamiento)
  • Pareado: Mismo grupo medido dos veces (Antes vs. Después, Pre vs. Post)

Chi-Cuadrado: Variables categóricas

Test de independencia

Úsalo para saber si dos variables categóricas están relacionadas (ej: ¿El género influye en la preferencia de producto?).

# Datos de ejemplo: Conversión por fuente de tráfico
data_conversion = pd.DataFrame({
    'Fuente': ['Orgánico']*500 + ['Redes Sociales']*450 + ['Email']*350 + ['Paid Ads']*400,
    'Conversión': (
        ['Sí']*85 + ['No']*415 +      # Orgánico: 17%
        ['Sí']*54 + ['No']*396 +      # Redes Sociales: 12%
        ['Sí']*77 + ['No']*273 +      # Email: 22%
        ['Sí']*72 + ['No']*328        # Paid Ads: 18%
    )
})

# Tabla de contingencia
tabla_contingencia = pd.crosstab(
    data_conversion['Fuente'],
    data_conversion['Conversión'],
    margins=True  # Agregar totales
)

print("=== TABLA DE CONTINGENCIA ===\n")
print(tabla_contingencia)

# Tabla de porcentajes
tabla_porcentajes = pd.crosstab(
    data_conversion['Fuente'],
    data_conversion['Conversión'],
    normalize='index'
) * 100

print("\n=== TASAS DE CONVERSIÓN POR FUENTE ===\n")
print(tabla_porcentajes.round(2))

# Visualización
tabla_porcentajes.plot(kind='bar', stacked=False, figsize=(10, 6), color=['red', 'green'])
plt.title('Tasa de Conversión por Fuente de Tráfico', fontsize=14, weight='bold')
plt.xlabel('Fuente')
plt.ylabel('Porcentaje (%)')
plt.xticks(rotation=45)
plt.legend(title='Conversión')
plt.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.savefig('conversion_fuente.png', dpi=300)
plt.show()

# CHI-CUADRADO TEST
chi2, p_value_chi, dof, expected_freq = stats.chi2_contingency(
    pd.crosstab(data_conversion['Fuente'], data_conversion['Conversión'])
)

print(f"\n=== TEST CHI-CUADRADO ===\n")
print(f"Estadístico χ²: {chi2:.4f}")
print(f"P-valor: {p_value_chi:.6f}")
print(f"Grados de libertad: {dof}")

if p_value_chi < 0.05:
    print("\n✅ RESULTADO: Rechazamos H₀")
    print("Conclusión: La fuente de tráfico SÍ afecta la tasa de conversión")
    print("\nRecomendación: Analiza qué fuentes convierten mejor y ajusta presupuesto")
else:
    print("\n❌ RESULTADO: No rechazamos H₀")
    print("Conclusión: No hay evidencia de que la fuente afecte conversión")

# Frecuencias esperadas vs. observadas
print("\n=== FRECUENCIAS ESPERADAS (bajo H₀) ===")
expected_df = pd.DataFrame(
    expected_freq,
    index=pd.crosstab(data_conversion['Fuente'], data_conversion['Conversión']).index,
    columns=['No', 'Sí']
)
print(expected_df.round(2))

ANOVA: Comparando múltiples grupos

One-Way ANOVA

Úsalo cuando comparas más de dos grupos (ej: conversión en 5 versiones de landing page).

# Datos de ejemplo: Tiempo de carga de 4 versiones de app
np.random.seed(456)

version_a = np.random.normal(2.1, 0.4, 100)   # 2.1 seg
version_b = np.random.normal(1.8, 0.35, 100)  # 1.8 seg (mejor)
version_c = np.random.normal(2.3, 0.5, 100)   # 2.3 seg
version_d = np.random.normal(2.0, 0.45, 100)  # 2.0 seg

# Crear DataFrame
data_anova = pd.DataFrame({
    'tiempo_carga': np.concatenate([version_a, version_b, version_c, version_d]),
    'version': (['A']*100 + ['B']*100 + ['C']*100 + ['D']*100)
})

# Estadísticas por grupo
stats_grupos = data_anova.groupby('version')['tiempo_carga'].agg(['mean', 'std', 'count'])
print("=== ESTADÍSTICAS POR VERSIÓN ===\n")
print(stats_grupos.round(3))

# Visualización
plt.figure(figsize=(12, 5))

# Boxplot
plt.subplot(1, 2, 1)
sns.boxplot(data=data_anova, x='version', y='tiempo_carga', palette='Set2')
plt.title('Tiempo de Carga por Versión de App')
plt.ylabel('Tiempo (segundos)')
plt.grid(True, alpha=0.3, axis='y')

# Violin plot
plt.subplot(1, 2, 2)
sns.violinplot(data=data_anova, x='version', y='tiempo_carga', palette='Set2')
plt.title('Distribución de Tiempo de Carga')
plt.ylabel('Tiempo (segundos)')
plt.grid(True, alpha=0.3, axis='y')

plt.tight_layout()
plt.savefig('anova_versiones.png', dpi=300)
plt.show()

# ONE-WAY ANOVA
f_statistic, p_value_anova = stats.f_oneway(version_a, version_b, version_c, version_d)

print(f"\n=== ONE-WAY ANOVA ===\n")
print(f"Estadístico F: {f_statistic:.4f}")
print(f"P-valor: {p_value_anova:.6f}")

if p_value_anova < 0.05:
    print("\n✅ RESULTADO: Rechazamos H₀")
    print("Conclusión: Al menos una versión tiene tiempo de carga diferente")
    print("\n⚠️ ANOVA solo dice que HAY diferencias, no DÓNDE están")
    print("   Necesitas Post-hoc tests (Tukey HSD) para saber qué versiones difieren")
else:
    print("\n❌ RESULTADO: No hay diferencias significativas entre versiones")

# Post-hoc: Tukey HSD (si ANOVA es significativo)
if p_value_anova < 0.05:
    from scipy.stats import tukey_hsd

    print("\n=== POST-HOC: TUKEY HSD ===\n")
    res = tukey_hsd(version_a, version_b, version_c, version_d)
    print("Comparaciones pareadas (diferencias significativas si p < 0.05):")
    print(res)

    # Interpretación simplificada
    comparaciones = [
        ('A vs B', res.pvalue[0, 1]),
        ('A vs C', res.pvalue[0, 2]),
        ('A vs D', res.pvalue[0, 3]),
        ('B vs C', res.pvalue[1, 2]),
        ('B vs D', res.pvalue[1, 3]),
        ('C vs D', res.pvalue[2, 3])
    ]

    print("\nComparaciones significativas (p < 0.05):")
    for comp, p in comparaciones:
        if p < 0.05:
            print(f"  ✅ {comp}: p={p:.4f}")

P-valores: Interpretación correcta

Errores comunes al interpretar p-valores

def interpretar_p_valor(p, alpha=0.05):
    """
    Interpreta correctamente un p-valor
    """
    print(f"=== INTERPRETACIÓN DE P-VALOR ===\n")
    print(f"P-valor: {p:.6f}")
    print(f"Nivel de significancia (α): {alpha}\n")

    # ✅ CORRECTO
    print("✅ INTERPRETACIÓN CORRECTA:")
    if p < alpha:
        print(f"  El p-valor ({p:.6f}) es menor que α ({alpha})")
        print("  → Rechazamos la hipótesis nula (H₀)")
        print("  → Hay evidencia estadísticamente significativa del efecto")
        print(f"  → Si H₀ fuera cierta, veríamos estos resultados solo {p*100:.2f}% de las veces por azar")
    else:
        print(f"  El p-valor ({p:.6f}) es mayor o igual que α ({alpha})")
        print("  → NO rechazamos la hipótesis nula (H₀)")
        print("  → No hay evidencia suficiente del efecto")
        print("  → NO significa que H₀ sea verdadera, solo que no tenemos evidencia para rechazarla")

    # ❌ INCORRECTO
    print("\n❌ INTERPRETACIONES INCORRECTAS (¡NO DECIR!):")
    print("  • 'Hay X% de probabilidad de que H₀ sea verdadera'")
    print("  • 'Hay X% de probabilidad de que H₁ sea verdadera'")
    print("  • 'El resultado es X% confiable'")
    print("  • 'No rechazar H₀' = 'Aceptar H₀'")

    # Contexto de negocio
    print("\n💼 PARA REPORTES DE NEGOCIO:")
    if p < 0.001:
        print("  'Evidencia MUY FUERTE del efecto (p < 0.001)'")
    elif p < 0.01:
        print("  'Evidencia FUERTE del efecto (p < 0.01)'")
    elif p < 0.05:
        print("  'Evidencia MODERADA del efecto (p < 0.05)'")
    elif p < 0.10:
        print("  'Evidencia DÉBIL del efecto (p < 0.10) - considerar con precaución'")
    else:
        print("  'Sin evidencia suficiente del efecto (p ≥ 0.10)'")

# Ejemplo de uso
interpretar_p_valor(0.023)

💡 Regla de oro: El p-valor NO es la probabilidad de que tu hipótesis sea cierta. Es la probabilidad de observar tus datos (o más extremos) asumiendo que NO hay efecto.

Proyecto práctico: Análisis de campaña de email marketing

# Caso real: A/B test de subject line de email
np.random.seed(789)

# Grupo A: Subject tradicional
emails_enviados_a = 5000
clicks_a = np.random.binomial(1, 0.12, emails_enviados_a)  # 12% CTR

# Grupo B: Subject con emoji
emails_enviados_b = 5200
clicks_b = np.random.binomial(1, 0.15, emails_enviados_b)  # 15% CTR

# Crear dataset
data_email = pd.DataFrame({
    'grupo': ['A']*emails_enviados_a + ['B']*emails_enviados_b,
    'click': np.concatenate([clicks_a, clicks_b])
})

# 1. ANÁLISIS DESCRIPTIVO
print("=== ANÁLISIS DE CAMPAÑA EMAIL ===\n")
stats_email = data_email.groupby('grupo')['click'].agg(['sum', 'count', 'mean'])
stats_email['ctr_pct'] = stats_email['mean'] * 100
print(stats_email)

# 2. VISUALIZACIÓN
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Barplot de CTR
axes[0].bar(['Grupo A\n(Sin emoji)', 'Grupo B\n(Con emoji)'],
            stats_email['ctr_pct'],
            color=['blue', 'green'],
            edgecolor='black')
axes[0].set_ylabel('Click-Through Rate (%)')
axes[0].set_title('CTR por Grupo')
axes[0].grid(True, alpha=0.3, axis='y')

# Agregar valores encima de barras
for i, v in enumerate(stats_email['ctr_pct']):
    axes[0].text(i, v + 0.2, f'{v:.2f}%', ha='center', fontweight='bold')

# Proporción de clicks
tabla_email = pd.crosstab(data_email['grupo'], data_email['click'])
tabla_email.plot(kind='bar', stacked=True, ax=axes[1], color=['red', 'green'])
axes[1].set_title('Distribución de Clicks')
axes[1].set_ylabel('Cantidad de Emails')
axes[1].set_xlabel('Grupo')
axes[1].legend(['No Click', 'Click'], title='Acción')
axes[1].set_xticklabels(['Grupo A', 'Grupo B'], rotation=0)

plt.tight_layout()
plt.savefig('email_ab_test.png', dpi=300)
plt.show()

# 3. CHI-CUADRADO TEST (para proporciones)
chi2_email, p_email, _, _ = stats.chi2_contingency(tabla_email)

print(f"\n=== TEST ESTADÍSTICO ===\n")
print(f"Chi-cuadrado: {chi2_email:.4f}")
print(f"P-valor: {p_email:.6f}")

# 4. INTERPRETACIÓN PARA STAKEHOLDERS
print("\n=== REPORTE EJECUTIVO ===\n")
ctr_a = stats_email.loc['A', 'ctr_pct']
ctr_b = stats_email.loc['B', 'ctr_pct']
mejora = ((ctr_b - ctr_a) / ctr_a) * 100

print(f"Grupo A (Sin emoji): {ctr_a:.2f}% CTR")
print(f"Grupo B (Con emoji): {ctr_b:.2f}% CTR")
print(f"Mejora relativa: +{mejora:.1f}%")

if p_email < 0.05:
    print(f"\n✅ CONCLUSIÓN:")
    print(f"  El subject line con emoji aumenta el CTR significativamente")
    print(f"  (p = {p_email:.6f} < 0.05)")
    print(f"\n📊 PROYECCIÓN DE IMPACTO:")
    emails_mensuales = 100000
    clicks_adicionales = emails_mensuales * (ctr_b - ctr_a) / 100
    print(f"  Con {emails_mensuales:,} emails/mes, esperamos {clicks_adicionales:.0f} clicks adicionales")
    print(f"\n💡 RECOMENDACIÓN: Implementar emojis en subject lines")
else:
    print(f"\n❌ CONCLUSIÓN:")
    print(f"  No hay evidencia suficiente de diferencia (p = {p_email:.6f} ≥ 0.05)")
    print(f"\n💡 RECOMENDACIÓN: Continuar testing con mayor muestra o diferentes emojis")

Power Analysis: Planeando tus tests

Calculando el tamaño de muestra necesario

from statsmodels.stats.power import TTestIndPower

# Parámetros de diseño
effect_size = 0.3       # Tamaño del efecto esperado (Cohen's d)
alpha = 0.05           # Nivel de significancia
power = 0.80           # Poder estadístico deseado (80%)

# Calcular tamaño de muestra
analysis = TTestIndPower()
sample_size = analysis.solve_power(
    effect_size=effect_size,
    alpha=alpha,
    power=power,
    alternative='two-sided'
)

print("=== POWER ANALYSIS ===\n")
print(f"Para detectar un efecto de tamaño d={effect_size}")
print(f"Con α={alpha} y poder={power}")
print(f"\nTamaño de muestra necesario por grupo: {sample_size:.0f}")
print(f"Total de participantes: {sample_size * 2:.0f}")

# Curva de poder
effect_sizes = np.arange(0.1, 1.0, 0.05)
sample_sizes_range = []

for es in effect_sizes:
    ss = analysis.solve_power(effect_size=es, alpha=0.05, power=0.80, alternative='two-sided')
    sample_sizes_range.append(ss)

plt.figure(figsize=(10, 6))
plt.plot(effect_sizes, sample_sizes_range, linewidth=2)
plt.xlabel('Tamaño del Efecto (Cohen\'s d)')
plt.ylabel('Tamaño de Muestra Necesario')
plt.title('Relación entre Tamaño del Efecto y Muestra Necesaria', fontsize=14, weight='bold')
plt.grid(True, alpha=0.3)
plt.axhline(y=100, color='red', linestyle='--', label='n=100 (común en A/B tests)')
plt.legend()
plt.tight_layout()
plt.savefig('power_analysis.png', dpi=300)
plt.show()

💡 Tip: Siempre haz power analysis ANTES de lanzar un experimento. Te evitará desperdiciar recursos en tests con muestras insuficientes.

Resumen de la lección

T-test compara medias de dos grupos (independiente o pareado) ✅ Chi-cuadrado analiza relación entre variables categóricas ✅ ANOVA compara medias de 3+ grupos simultáneamente ✅ P-valor < 0.05 = evidencia estadísticamente significativa ✅ P-valor NO es la probabilidad de que tu hipótesis sea cierta ✅ Significancia estadística ≠ Significancia práctica (efecto puede ser pequeño) ✅ Power analysis asegura que tu test tenga suficiente muestra ✅ Siempre reporta tamaño del efecto además del p-valor

Checklist para testing de hipótesis profesional

  • Define H₀ y H₁ claramente antes de ver los datos
  • Verifica supuestos del test (normalidad, independencia, etc.)
  • Calcula tamaño de muestra necesario (power analysis)
  • Elige el test correcto (t-test, chi-cuadrado, ANOVA)
  • Visualiza tus datos antes del test
  • Reporta p-valor, tamaño del efecto e intervalos de confianza
  • Interpreta resultados en contexto de negocio
  • Considera significancia práctica, no solo estadística

🎯 Próxima lección: 21. Caso Práctico: A/B Testing

En la siguiente lección aplicarás todo lo aprendido en un proyecto completo de A/B Testing desde el diseño hasta la presentación de resultados. ¡Nos vemos! 🚀

¿Completaste esta lección?

Marca esta lección como completada. Tu progreso se guardará en tu navegador.