Pandas & NumPy Academy · Lección

Estadística descriptiva y pruebas de normalidad

Calcule la asimetría y la curtosis con scipy.stats, ejecute una prueba de Shapiro-Wilk para la normalidad e interprete el valor p.

Lección 1 de 413 pasos

Estadística descriptiva y pruebas de normalidad es una lección gratuita de Pandas & NumPy Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Pandas & NumPy Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.

Estadística descriptiva frente a estadística inferencial

La estadística descriptiva resume lo que contienen sus datos: media, mediana, desviación estándar y asimetría. La estadística inferencial formula afirmaciones sobre una población a partir de una muestra: pruebas de hipótesis, intervalos de confianza y valores p. El módulo scipy.stats de SciPy conecta ambos ámbitos: ofrece medidas descriptivas que van más allá de describe() de Pandas y el conjunto completo de pruebas de hipótesis clásicas. Combinar Pandas para manipular los datos y SciPy para realizar pruebas estadísticas es el flujo de trabajo estándar de la ciencia de datos en Python.

Estadística descriptiva ampliada

describe() de Pandas proporciona el recuento, la media, la desviación estándar, los valores mínimo y máximo, y los cuartiles. scipy.stats añade la asimetría (la falta de simetría de la distribución) y la curtosis (el peso de las colas). Una asimetría de 0 indica simetría; una asimetría positiva indica una cola derecha más larga (muchos valores pequeños y unos pocos muy grandes). Una curtosis de 3 (o de 0 en su forma de exceso) es normal; los valores superiores indican colas más pesadas, con más valores atípicos extremos de los que produciría una distribución normal.

import pandas as pd
from scipy import stats
import numpy as np

np.random.seed(0)
data = np.concatenate([
    np.random.exponential(scale=2, size=500),  # right-skewed
    np.random.normal(loc=5, scale=1, size=500)
])

print('Mean:', round(data.mean(), 3))
print('Std:', round(data.std(), 3))
print('Skewness:', round(stats.skew(data), 3))
print('Kurtosis (excess):', round(stats.kurtosis(data), 3))

Comprender la asimetría

La asimetría es importante para elegir pruebas estadísticas y transformaciones. Una distribución asimétrica hacia la derecha (sesgo positivo) tiene una media mayor que la mediana, como suele ocurrir con los datos de ingresos, los tiempos de reacción y los importes de ventas. Una distribución asimétrica hacia la izquierda (sesgo negativo) tiene una media menor que la mediana. Como regla general: |skewness| < 0.5 indica una distribución aproximadamente simétrica; 0.5–1.0, una asimetría moderada; > 1.0, una asimetría elevada que puede beneficiarse de una transformación logarítmica o de raíz cuadrada antes de aplicar pruebas que supongan normalidad.

import numpy as np
from scipy import stats

# Right-skewed: income-like data
right_skewed = np.random.lognormal(mean=1, sigma=1, size=1000)
print('Right skew:', round(stats.skew(right_skewed), 3))

# After log transform
print('After log transform:', round(stats.skew(np.log(right_skewed)), 3))

# Symmetric normal
normal_data = np.random.normal(0, 1, 1000)
print('Normal skew:', round(stats.skew(normal_data), 3))

Por qué es importante comprobar la normalidad

Muchas pruebas estadísticas —pruebas t, ANOVA y correlación de Pearson— suponen que los datos (o los residuos) siguen una distribución normal (gaussiana). Si este supuesto no se cumple con muestras pequeñas, los valores p de la prueba pueden ser inexactos. La comprobación de normalidad verifica si se cumple este supuesto. En muestras grandes (n > 100), las pruebas de normalidad se vuelven muy sensibles y casi siempre rechazan la normalidad ante desviaciones triviales; en ese caso, confíe en el teorema del límite central (las medias muestrales son aproximadamente normales) en lugar de comprobar los datos sin procesar.

La prueba de Shapiro-Wilk

La prueba de Shapiro-Wilk (scipy.stats.shapiro(data)) es la prueba de normalidad más potente para tamaños de muestra de hasta aproximadamente 5.000. Devuelve un estadístico W y un valor p. Si p > 0.05, no se rechaza la normalidad: los datos son compatibles con una distribución normal. Si p ≤ 0.05, se rechaza la normalidad. Recuerde que no rechazar la normalidad no demuestra que los datos sean normales; solo significa que no hay evidencia suficiente para afirmar que no lo sean.

import numpy as np
from scipy import stats

np.random.seed(42)

# Normal data
normal = np.random.normal(0, 1, 100)
stat, p = stats.shapiro(normal)
print(f'Normal data: W={stat:.4f}, p={p:.4f}')
print('Conclusion:', 'Looks normal' if p > 0.05 else 'Not normal')

# Skewed data
skewed = np.random.exponential(1, 100)
stat2, p2 = stats.shapiro(skewed)
print(f'Skewed data: W={stat2:.4f}, p={p2:.4f}')
print('Conclusion:', 'Looks normal' if p2 > 0.05 else 'Not normal')

La prueba de Kolmogorov-Smirnov

La prueba de Kolmogorov-Smirnov (K-S) (scipy.stats.kstest(data, 'norm', args)) comprueba si una muestra sigue una distribución especificada. A diferencia de Shapiro-Wilk, funciona con cualquier distribución (no solo la normal) y con muestras grandes. Calcula la diferencia máxima entre la función de distribución acumulada empírica de sus datos y la función de distribución acumulada teórica. Una variante, la prueba K-S de dos muestras (stats.ks_2samp(a, b)), comprueba si dos muestras proceden de la misma distribución; resulta útil para comparar distribuciones de antes y después.

import numpy as np
from scipy import stats

np.random.seed(0)
data = np.random.normal(loc=5, scale=2, size=200)

# One-sample K-S test against N(5, 2) distribution
stat, p = stats.kstest(data, 'norm', args=(5, 2))
print(f'K-S test: stat={stat:.4f}, p={p:.4f}')
print('Follows N(5,2)?', 'Yes' if p > 0.05 else 'No')

# Two-sample K-S test
data2 = np.random.normal(loc=5.5, scale=2, size=200)
stat2, p2 = stats.ks_2samp(data, data2)
print(f'Two-sample K-S: stat={stat2:.4f}, p={p2:.4f}')

Comprobación visual de la normalidad: gráfico Q-Q

El gráfico Q-Q (cuantil-cuantil) es una comprobación visual de la normalidad: representa los cuantiles de sus datos frente a los cuantiles de una distribución normal. Si los datos son normales, los puntos se sitúan sobre una línea diagonal recta. Las desviaciones respecto a la línea indican una falta de normalidad: las curvas en forma de S indican curtosis y los cambios de dirección indican asimetría. Las pruebas estadísticas indican si las desviaciones son significativas; los gráficos Q-Q muestran su naturaleza y ubicación. Use scipy.stats.probplot() para generar los datos del gráfico Q-Q.

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

np.random.seed(1)
data = np.random.exponential(2, 200)

# Q-Q plot
(osm, osr), (slope, intercept, r) = stats.probplot(data, dist='norm')
print(f'R-squared of Q-Q fit: {r**2:.4f}')  # Close to 1 = normal
# Visual inspection: if plotting, points on the line = normal
# plt.figure()
# stats.probplot(data, dist='norm', plot=plt)
# plt.show()

El teorema del límite central en la práctica

El teorema del límite central (CLT) establece que la distribución de las medias muestrales se aproxima a la normalidad a medida que aumenta el tamaño de la muestra, independientemente de la distribución subyacente. Para n ≥ 30, la media muestral es aproximadamente normal incluso si las observaciones individuales presentan asimetría. Por eso las pruebas t son robustas con muestras grandes: se comprueba si la media difiere, y la media es aproximadamente normal aunque los datos sin procesar no lo sean. Para muestras pequeñas procedentes de poblaciones no normales, use pruebas no paramétricas.

import numpy as np
from scipy import stats

np.random.seed(0)
# Population: heavily right-skewed (exponential)
population = np.random.exponential(scale=1, size=10000)
print('Population skewness:', round(stats.skew(population), 3))

# Sample means are approximately normal (CLT)
sample_means = [np.random.choice(population, 50).mean()
                for _ in range(1000)]
print('Sample means skewness:', round(stats.skew(sample_means), 3))
_, p = stats.shapiro(sample_means)
print('Shapiro p-value for means:', round(p, 4))

Normalidad por grupo

En las pruebas de comparación de grupos (prueba t y ANOVA), la normalidad se requiere dentro de cada grupo, no en el conjunto de datos global. Al comprobar si las ventas difieren por región, evalúe por separado la normalidad de las ventas dentro de cada región. Una distribución que no sea normal en conjunto puede cumplir la normalidad dentro de los subgrupos. Aplique stats.shapiro() a cada grupo mediante groupby() de Pandas e itere sobre los grupos para comprobar el supuesto de forma sistemática.

import pandas as pd
import numpy as np
from scipy import stats

np.random.seed(0)
df = pd.DataFrame({
    'region': ['N']*50 + ['S']*50 + ['E']*50,
    'sales': np.concatenate([
        np.random.normal(100, 20, 50),
        np.random.normal(110, 25, 50),
        np.random.normal(95, 15, 50)
    ])
})

for region, group in df.groupby('region'):
    stat, p = stats.shapiro(group['sales'])
    print(f'Region {region}: W={stat:.4f}, p={p:.4f} -> '
          f'{"Normal" if p>0.05 else "Not normal"}')

Alternativas no paramétricas

Cuando no se cumple la normalidad, use pruebas no paramétricas que no hagan suposiciones sobre la distribución. La prueba U de Mann-Whitney (stats.mannwhitneyu) sustituye a la prueba t para muestras independientes; la prueba de rangos con signo de Wilcoxon (stats.wilcoxon) sustituye a la prueba t para muestras emparejadas; y la prueba de Kruskal-Wallis (stats.kruskal) sustituye al ANOVA de un factor. Estas pruebas utilizan rangos en lugar de valores sin procesar y son robustas frente a valores atípicos, pero tienen menor potencia estadística que sus equivalentes paramétricas cuando la normalidad sí se cumple.

import numpy as np
from scipy import stats

np.random.seed(0)
# Non-normal data
group_a = np.random.exponential(2, 40)
group_b = np.random.exponential(2.5, 40)

# Parametric would be wrong here; use non-parametric
stat, p = stats.mannwhitneyu(group_a, group_b, alternative='two-sided')
print(f'Mann-Whitney U test: U={stat:.1f}, p={p:.4f}')
print('Groups differ?' , 'Yes' if p < 0.05 else 'No')

Resumen de estadísticas para varias columnas

En el análisis exploratorio de datos, a menudo debe comprobar la normalidad y la asimetría de todas las columnas numéricas a la vez. Combine select_dtypes de Pandas con un bucle por las columnas que llame a stats.shapiro() y stats.skew(). Cree un DataFrame de resumen con columnas para la asimetría, la curtosis y el valor p de Shapiro, para obtener una visión general de qué columnas no son normales y necesitan una transformación antes de crear modelos. Esto forma parte de una lista de comprobación sistemática de la calidad de los datos.

import pandas as pd
import numpy as np
from scipy import stats

np.random.seed(0)
df = pd.DataFrame({
    'age': np.random.normal(35, 10, 200),
    'income': np.random.lognormal(10, 1, 200),
    'score': np.random.uniform(0, 100, 200)
})

rows = []
for col in df.select_dtypes(include='number').columns:
    s = stats.skew(df[col])
    _, p = stats.shapiro(df[col][:200])
    rows.append({'column': col, 'skewness': round(s, 3),
                 'shapiro_p': round(p, 4), 'normal': p > 0.05})

print(pd.DataFrame(rows).to_string(index=False))

Comprobación rápida

Compruebe su comprensión de los conceptos de análisis de datos de esta lección.

Resumen de la lección

En esta lección ha aprendido que scipy.stats.skew() y kurtosis() describen la forma de una distribución más allá de lo que proporciona describe(), que scipy.stats.shapiro() comprueba la normalidad, donde p > 0.05 significa que no hay evidencia contra la normalidad, y que el teorema del límite central hace que las pruebas t sean robustas con muestras grandes incluso cuando los datos no son normales. A continuación aplicaremos pruebas de hipótesis con pruebas t para comparar medias de grupos.

Gratis para empezar

Aprende Python con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
30
Lecciones
120

Preguntas frecuentes

¿La lección «Estadística descriptiva y pruebas de normalidad» es gratis?

Sí — el texto completo de «Estadística descriptiva y pruebas de normalidad» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Pandas & NumPy Academy, actualiza a CoddyKit PRO. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Estadística descriptiva y pruebas de normalidad»?

Calcule la asimetría y la curtosis con scipy.stats, ejecute una prueba de Shapiro-Wilk para la normalidad e interprete el valor p. Practicas Pandas & NumPy Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Pandas & NumPy Academy?

No se requiere experiencia previa. Pandas & NumPy Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Estadística descriptiva y pruebas de normalidad»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Pandas & NumPy Academy?

Sí. Cada lección de Pandas & NumPy Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Estadística descriptiva y pruebas de normalidad
  2. Pruebas t para comparar medias
  3. Prueba de chi cuadrado de independencia
  4. ANOVA y pruebas post hoc
← Volver a Pandas & NumPy Academy