Análisis Estadístico
Resumen
Realiza pruebas de hipótesis (pruebas t, ANOVA, chi-cuadrado), regresión, correlación y análisis bayesianos con verificación sistemática de supuestos, tamaños del efecto y redacción en estilo APA. El objetivo es un análisis que un revisor no pueda desarmar: la prueba correcta, supuestos verificados, tamaños del efecto honestos y un informe completo.
Cuándo Usar Esta Habilidad
Usa esta habilidad cuando:
- Realices pruebas de hipótesis estadísticas (pruebas t, ANOVA, chi-cuadrado, no paramétricas)
- Realices análisis de regresión o correlación
- Ejecutes análisis estadísticos bayesianos
- Verifiques supuestos y diagnósticos estadísticos
- Calcules tamaños del efecto y realices análisis de potencia
- Reportes resultados estadísticos en formato APA
- Analices datos experimentales u observacionales para investigación
Instalación
Usa uv para instalar las bibliotecas utilizadas en esta habilidad. Fija versiones en producción; las instalaciones sin fijar son adecuadas para exploración.
# Stack frecuentista principal (Python 3.10+; se recomienda 3.12+ para SciPy/ArviZ más recientes)
uv pip install "pingouin>=0.6" "scipy>=1.11" "statsmodels>=0.14.6" pandas matplotlib seaborn
# Modelado bayesiano (PyMC 5 + ArviZ)
uv pip install "pymc>=5.0" "arviz>=1.0"
Notas de compatibilidad (verificadas con pingouin 0.6.1, statsmodels 0.14.6, arviz 1.2, 2026):
- Pingouin 0.6.0 renombró las columnas de salida para eliminar caracteres especiales:
p_val,cohen_d,CI95,p_unc(anteriormentep-val,cohen-d,CI95%,p-uncen 0.5.x). Los ejemplos a continuación usan los nombres actuales; si estás atascado en 0.5.x, usa las formas con guiones. - statsmodels + SciPy: usa
statsmodels>=0.14.6conscipy>=1.11para evitar errores de importación_lazywhereen SciPy 1.16+. - ArviZ 1.x:
az.summary()ahora usa por defecto intervalos del 89% (columnaseti89) y el parámetro de ancho esci_prob(nohdi_prob). Para reportar un intervalo creíble convencional del 95%, pasaaz.summary(trace, ci_prob=0.95). - Los factores de Bayes unilaterales desaparecieron de Pingouin:
pg.ttest(..., alternative='greater')omite silenciosamente la columnaBF10, ypg.bayesfactor_ttestgenera un error en alternativas unilaterales. Para pruebas bayesianas unilaterales, usa PyMC directamente (calcula la probabilidad posterior de la hipótesis direccional) o JASP/R's BayesFactor.
Para APIs específicas de modelos (OLS, GLM, ARIMA), consulta la habilidad statsmodels. Para flujos de trabajo de PyMC, consulta la habilidad pymc.
Flujo de Trabajo de Análisis
Todo análisis sólido sigue el mismo arco. Saltarse pasos es cómo los análisis terminan retractados, así que trabaja en orden y di lo que hiciste en cada uno.
- Formula la pregunta antes de tocar los datos. Enuncia la hipótesis, las variables de resultado y predictoras, y el diseño (independiente vs. pareado, número de grupos). Comprométete ahora con una prueba planificada: elegir la prueba después de echar un vistazo a los resultados es p-hacking, incluso cuando se hace de forma inocente.
- Inspecciona los datos. Por grupo: n, media, DE, mediana, valores faltantes. Grafica los datos brutos (histogramas o diagramas de caja) antes de cualquier prueba. Los tamaños de grupo desiguales, la falta de datos, los efectos de suelo/techo y los valores atípicos cambian qué prueba es apropiada: muéstralos al usuario en lugar de solucionarlos silenciosamente.
- Selecciona la prueba usando la referencia rápida a continuación, o
references/test_selection_guide.mdpara diseños más allá de lo básico (conteos, tiempo hasta evento, confiabilidad, factorial). - Verifica los supuestos con
scripts/assumption_checks.py. Si un supuesto falla, cambia a la prueba correctiva (tabla a continuación) y reporta tanto el plan como el cambio. - Ejecuta la prueba y siempre calcula el tamaño del efecto junto con ella: un valor p dice que existe un efecto; el tamaño del efecto dice si a alguien le debería importar.
- Redacta el informe usando las plantillas APA a continuación, incluyendo estadísticos descriptivos, estadísticos exactos, tamaños del efecto con IC y las verificaciones de supuestos realizadas.
Si el usuario solo necesita un paso (por ejemplo, "¿cuántos participantes necesito?"), salta directamente a esa sección, pero aún así confirma los supuestos de diseño en los que se basa el cálculo.
Guía de Selección de Pruebas
Referencia Rápida: Elegir la Prueba Correcta
Usa references/test_selection_guide.md para una guía completa (conteos, supervivencia, confiabilidad, diseños factoriales). Referencia rápida:
Comparación de Dos Grupos:
- Independiente, continua, normal → Prueba t independiente
- Independiente, continua, no normal → Prueba U de Mann-Whitney
- Pareada, continua, normal → Prueba t pareada
- Pareada, continua, no normal → Prueba de rangos con signo de Wilcoxon
- Resultado binario → Chi-cuadrado o prueba exacta de Fisher
Comparación de 3+ Grupos:
- Independiente, continua, normal → ANOVA de una vía
- Independiente, continua, no normal → Prueba de Kruskal-Wallis
- Pareada, continua, normal → ANOVA de medidas repetidas
- Pareada, continua, no normal → Prueba de Friedman
Relaciones:
- Dos variables continuas → Correlación de Pearson (normal) o Spearman (no normal)
- Resultado continuo con predictor(es) → Regresión lineal
- Resultado binario con predictor(es) → Regresión logística
Alternativas Bayesianas:
Todas las pruebas tienen versiones bayesianas que proporcionan declaraciones de probabilidad directas sobre hipótesis, factores de Bayes que cuantifican la evidencia y la capacidad de respaldar la hipótesis nula. Consulta references/bayesian_statistics.md.
Verificación de Supuestos
Siempre verifica los supuestos antes de interpretar los resultados de la prueba, y reporta las verificaciones: los revisores las buscan.
Usa el módulo incluido scripts/assumption_checks.py. Ejecuta Python desde el directorio de la habilidad (skills/statistical-analysis/) o agrega scripts/ a sys.path:
from assumption_checks import comprehensive_assumption_check
# Valores atípicos + normalidad (por grupo) + homogeneidad de varianza, con gráficos
resultados = comprehensive_assumption_check(
data=df,
value_col='puntaje',
group_col='grupo', # Opcional: para comparaciones de grupos
alpha=0.05
)
Para verificaciones específicas, importa funciones individuales:
from assumption_checks import (
check_normality, # Shapiro-Wilk + gráfico Q-Q + histograma
check_normality_per_group,
check_homogeneity_of_variance, # Prueba de Levene + diagramas de caja
check_linearity, # gráfico de dispersión + residual para regresión simple
check_regression_diagnostics, # diagnósticos OLS completos (ver Regresión a continuación)
detect_outliers # Métodos IQR o puntuación z
)
resultado = check_normality(data=df['puntaje'], name='Puntaje de Prueba', alpha=0.05, plot=True)
print(resultado['interpretation'])
print(resultado['recommendation'])
Qué Hacer Cuando se Violan los Supuestos
Normalidad violada:
- Violación leve + n > 30 por grupo → Procede con prueba paramétrica (robusta)
- Violación moderada → Usa alternativa no paramétrica
- Violación severa → Transforma los datos o usa prueba no paramétrica
Homogeneidad de varianza violada:
- Para prueba t → Usa prueba t de Welch (
pg.ttestla aplica automáticamente concorrection='auto') - Para ANOVA → Usa ANOVA de Welch (
pg.welch_anova) o Brown-Forsythe - Para regresión → Usa errores estándar robustos o mínimos cuadrados ponderados
Linealidad violada (regresión):
- Agrega términos polinómicos, transforma variables, o usa modelos no lineales / GAM
Las pruebas formales se vuelven demasiado sensibles a medida que n crece: para n ≥ 100, pesa más el gráfico Q-Q que el valor p de Shapiro-Wilk. Consulta references/assumptions_and_diagnostics.md para una guía completa.
Ejecución de Pruebas Estadísticas
Bibliotecas principales:
- pingouin: pruebas fáciles de usar que devuelven tamaños del efecto por defecto — prefierela para pruebas estándar
- scipy.stats: pruebas estadísticas principales
- statsmodels: regresión, diagnósticos, análisis de potencia
- pymc + arviz: modelado y diagnósticos bayesianos
Prueba t con Informe Completo
import pingouin as pg
# correction='auto' aplica la corrección de Welch cuando las varianzas son desiguales
resultado = pg.ttest(grupo_a, grupo_b, correction='auto')
# Nombres de columnas de Pingouin >= 0.6
t_stat = resultado['T'].values[0]
gl = resultado['dof'].values[0]
p_valor = resultado['p_val'].values[0]
d_cohen = resultado['cohen_d'].values[0]
ci_inferior, ci_superior = resultado['CI95'].values[0] # IC para la diferencia de medias
print(f"t({gl:.0f}) = {t_stat:.2f}, p = {p_valor:.3f}, d = {d_cohen:.2f}")
ANOVA con Pruebas Post-Hoc
import pingouin as pg
aov = pg.anova(dv='puntaje', between='grupo', data=df, detailed=True)
print(aov)
# Tamaño del efecto: eta-cuadrado parcial
eta_p2 = aov['np2'].values[0]
# Si es significativo, realiza pruebas post-hoc (Tukey HSD controla el error familiar)
if aov['p_unc'].values[0] < 0.05:
posthoc = pg.pairwise_tukey(dv='puntaje', between='grupo', data=df)
print(posthoc) # incluye g de Hedges por par
Regresión Lineal con Diagnósticos
import statsmodels.api as sm
from assumption_checks import check_regression_diagnostics
X = sm.add_constant(X_predictores) # Agrega intersección
modelo = sm.OLS(y, X).fit()
print(modelo.summary())
# Gráfico de residuos de 4 paneles + Shapiro-Wilk, Breusch-Pagan, Durbin-Watson, VIF
diag = check_regression_diagnostics(modelo)
print(diag['interpretation'])
print(diag['vif'])
# Si se señaló heterocedasticidad, reporta errores estándar robustos en su lugar
robusto = modelo.get_robustcov_results('HC3')
Prueba t Bayesiana
import pymc as pm
import arviz as az
import numpy as np
with pm.Model() as modelo:
# Priors
mu1 = pm.Normal('mu_grupo1', mu=0, sigma=10)
mu2 = pm.Normal('mu_grupo2', mu=0, sigma=10)
sigma = pm.HalfNormal('sigma', sigma=10)
# Verosimilitud
y1 = pm.Normal('y1', mu=mu1, sigma=sigma, observed=grupo_a)
y2 = pm.Normal('y2', mu=mu2, sigma=sigma, observed=grupo_b)
# Cantidad derivada
diff = pm.Deterministic('diferencia', mu1 - mu2)
traza = pm.sample(2000, tune=1000)
# ArviZ 1.x usa intervalos del 89% por defecto; solicita 95% explícitamente para el informe
print(az.summary(traza, var_names=['diferencia'], ci_prob=0.95))
# Declaración de probabilidad directa (esto es en lo que se convierten las preguntas unilaterales)
prob_mayor = np.mean(traza.posterior['diferencia'].values > 0)
print(f"P(mu1 > mu2 | datos) = {prob_mayor:.3f}")
# ArviZ 1.x eliminó az.plot_posterior; usa plot_dist (en 0.x, plot_posterior aún funciona)
az.plot_dist(traza, var_names=['diferencia'], ci_prob=0.95)
Escala los priors a los datos (por ejemplo, sigma=10 es adecuado para resultados con DE cerca de 10; usa la DE observada como guía) y enuncia los priors en el informe.
Tamaños del Efecto
Los tamaños del efecto cuantifican la magnitud; los valores p solo indican existencia. Reporta uno para cada prueba. Consulta references/effect_sizes_and_power.md para la guía completa.
Referencia Rápida: Tamaños del Efecto Comunes
| Prueba | Tamaño del Efecto | Pequeño | Mediano | Grande |
|---|---|---|---|---|
| Prueba t | d de Cohen | 0.20 | 0.50 | 0.80 |
| ANOVA | η²_p | 0.01 | 0.06 | 0.14 |
| Correlación | r | 0.10 | 0.30 | 0.50 |
| Regresión | R² | 0.02 | 0.13 | 0.26 |
| Chi-cuadrado | V de Cramér | 0.07 | 0.21 | 0.35 |
Los puntos de referencia son convenciones, no leyes: un efecto "pequeño" puede importar enormemente (efectos secundarios de medicamentos) y uno "grande" puede ser trivial. Interpreta en contexto.
Cálculo de Tamaños del Efecto
Pingouin devuelve tamaños del efecto con sus pruebas (cohen_d de pg.ttest, np2 de pg.anova, hedges de pg.pairwise_tukey; r de pg.corr ya es un tamaño del efecto).
Intervalos de Confianza para Tamaños del Efecto
Reporta un IC para el tamaño del efecto para mostrar su precisión. Usa pg.compute_esci (nota: pg.compute_effsize_from_t devuelve solo la estimación puntual — no devuelve un IC):
import pingouin as pg
d = pg.compute_effsize(grupo_a, grupo_b, eftype='cohen')
ci_inferior, ci_superior = pg.compute_esci(stat=d, nx=len(grupo_a), ny=len(grupo_b),
eftype='cohen', confidence=0.95)
print(f"d = {d:.2f}, IC del 95% [{ci_inferior:.2f}, {ci_superior:.2f}]")
Análisis de Potencia
Análisis de Potencia a Priori (Planificación del Estudio)
Determina el tamaño de muestra requerido antes de la recolección de datos:
from statsmodels.stats.power import tt_ind_solve_power, FTestAnovaPower
# Prueba t: ¿Qué n por grupo se necesita para detectar d = 0.5?
n_requerido = tt_ind_solve_power(
effect_size=0.5,
alpha=0.05,
power=0.80,
ratio=1.0,
alternative='two-sided'
)
print(f"n requerido por grupo: {n_requerido:.0f}")
# ANOVA de una vía: ¿Qué n se necesita para detectar el f de Cohen = 0.25?
# Notas: el parámetro es k_groups; effect_size es el f de Cohen (f = sqrt(eta2/(1-eta2)));
# y solve_power devuelve el TAMAÑO TOTAL de la muestra, no n por grupo.
import math
potencia_anova = FTestAnovaPower()
n_total = potencia_anova.solve_power(
effect_size=0.25,
k_groups=3,
alpha=0.05,
power=0.80
)
print(f"N total requerido: {math.ceil(n_total)} ({math.ceil(n_total / 3)} por grupo)")
Análisis de Sensibilidad (Post-Estudio)
Determina qué tamaño del efecto podría detectar el estudio:
# Con n=50 por grupo, ¿qué efecto podríamos detectar con un 80% de potencia?
d_detectable = tt_ind_solve_power(
effect_size=None, # Resuelve para esto
nobs1=50,
alpha=0.05,
power=0.80,
ratio=1.0,
alternative='two-sided'
)
print(f"El estudio podría detectar d >= {d_detectable:.2f}")
Nota: La "potencia observada" post-hoc (calcular la potencia a partir del efecto observado) es circular y engañosa — es una función determinista del valor p. Si un estudio está terminado y alguien pregunta sobre la potencia, realiza un análisis de sensibilidad en su lugar.
Consulta references/effect_sizes_and_power.md para obtener orientación detallada.
Reporte de Resultados
Sigue references/reporting_standards.md para el estilo APA. Cada informe necesita:
- Estadísticos descriptivos: M, DE, n para todos los grupos/variables
- Estadísticos de prueba: Nombre de la prueba, estadístico, gl, valor p exacto (
p = .034, nop < .05; usap < .001solo por debajo de .001) - Tamaños del efecto: Con intervalos de confianza
- Verificaciones de supuestos: Qué pruebas se realizaron, resultados y acciones tomadas
- Todos los análisis planificados: Incluyendo hallazgos no significativos — omitirlos es cherry-picking
Ejemplos de Plantillas de Informe
Prueba t Independiente
El Grupo A (n = 48, M = 75.2, DE = 8.5) obtuvo una puntuación significativamente más alta que
el Grupo B (n = 52, M = 68.3, DE = 9.2), t(98)
...
(El contenido se trunca para la traducción; el informe completo debe seguir las pautas APA).