20. Testing de Hipótesis
T-tests, chi-cuadrado, ANOVA y interpretación de p-valores
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.