statistics.kde incorpora la estimación de densidad por kernel a la biblioteca estándar de Python. Es una herramienta útil cuando la media, la mediana o un histograma no alcanzan para describir cómo se distribuyen los datos. En lugar de dividir los valores en intervalos rígidos, KDE crea una función suave que permite observar concentraciones, huecos y posibles grupos.
Esta guía explica qué significa la estimación de densidad, cómo utilizar statistics.kde, cómo elegir el ancho de banda, qué cambia al seleccionar otro kernel y cómo interpretar el resultado sin confundir densidad con probabilidad.
Qué es una estimación de densidad por kernel
La técnica coloca una pequeña curva alrededor de cada observación. Después suma y normaliza todas esas curvas para producir una función continua. El resultado se parece a un histograma suavizado, pero su aspecto depende principalmente del ancho de banda y no de los límites de las barras.
Imagina una muestra de tiempos de respuesta. Un histograma necesita intervalos como 0–50, 50–100 y 100–150 milisegundos. Cambiar esos límites puede modificar la interpretación. KDE evita esa división fija y calcula cuánto debe influir cada observación en los puntos cercanos.
Ejemplo básico
from statistics import kde
muestra = [1.2, 1.5, 1.7, 2.0, 2.1, 2.2, 3.8, 4.0, 4.2]
densidad = kde(muestra, h=0.35)
for x in [1.0, 1.5, 2.0, 2.5, 3.0, 4.0]:
print(x, densidad(x))
La llamada devuelve otra función. Esa función recibe un número y retorna la densidad estimada en ese punto. El valor no representa la probabilidad exacta de observar ese número. La probabilidad corresponde al área de la curva dentro de un intervalo.
Cómo interpretar la curva
Para visualizar la estimación, evalúa la función en una secuencia ordenada de puntos. Las zonas altas indican mayor concentración relativa. Las zonas bajas muestran regiones con pocas observaciones. En la muestra anterior deberían aparecer dos grupos: uno entre 1 y 2.2 y otro alrededor de 4.
Esta característica ayuda a descubrir estructuras que una media puede ocultar. Un promedio cercano a 2.5 podría sugerir un centro que en realidad contiene pocos datos.
El ancho de banda
El argumento h controla la suavidad. Un valor demasiado pequeño produce muchos picos y puede seguir el ruido de la muestra. Un valor demasiado grande puede unir grupos diferentes y borrar información importante.
valores = [10, 10.5, 11, 11.2, 14, 14.3, 15]
estrecha = kde(valores, h=0.2)
equilibrada = kde(valores, h=0.8)
amplia = kde(valores, h=2.0)
No existe un ancho correcto para todos los problemas. La escala, el tamaño de la muestra y el objetivo del análisis influyen. Durante la exploración conviene comparar varios valores. Para decisiones automatizadas, valida el parámetro con datos independientes y conocimiento del dominio.
Selección del kernel
El parámetro kernel define la forma de la curva alrededor de cada punto. La documentación incluye opciones como normal, logistic, sigmoid, rectangular, triangular y parabolic. El kernel normal suele ser un buen punto de partida. Los kernels de soporte limitado pueden ser adecuados cuando no quieres que observaciones lejanas tengan influencia.
normal = kde(muestra, h=0.35, kernel="normal")
triangular = kde(muestra, h=0.35, kernel="triangular")
En muchos casos, el ancho de banda cambia más la curva que el tipo de kernel. Aun así, registra ambos parámetros para que el análisis sea reproducible.
Crear puntos para un gráfico
inicio = min(muestra) - 1
fin = max(muestra) + 1
pasos = 200
xs = [inicio + i * (fin - inicio) / (pasos - 1) for i in range(pasos)]
ys = [densidad(x) for x in xs]
La función no dibuja el gráfico. Los arreglos pueden enviarse a Matplotlib, a una interfaz web, a una hoja de cálculo o a una API. Para trabajar con secuencias vecinas, consulta itertools.pairwise en Python. Para resultados acumulados, revisa itertools.accumulate en Python.
Limpiar los datos antes del cálculo
KDE no corrige entradas defectuosas. Comprueba unidades, elimina valores no finitos e investiga extremos. Mezclar segundos y milisegundos genera una curva llamativa pero incorrecta. Decide si los outliers son errores, eventos válidos o miembros de otra población.
import math
from statistics import kde
brutos = [1.2, None, 1.5, float("nan"), 2.0, 2.1]
limpios = [x for x in brutos if isinstance(x, (int, float)) and math.isfinite(x)]
if len(limpios) < 2:
raise ValueError("Muestra insuficiente")
f = kde(limpios, h=0.3)
Para diseñar modelos con argumentos explícitos, revisa dataclasses.KW_ONLY en Python. Para objetos ligeros usados en resultados exploratorios, consulta SimpleNamespace en Python.
KDE frente a histogramas
El histograma comunica conteos de forma directa. KDE ofrece una vista continua y facilita comparar formas. En muchos informes conviene mostrar ambos. El histograma conserva las cantidades por intervalo y KDE ayuda a observar la estructura general.
No permitas que una curva suave oculte una muestra pequeña. Informa siempre el número de observaciones, el ancho de banda, el kernel y, si es posible, los datos originales o un histograma de apoyo.
Muestras pequeñas
Cuando hay pocos valores, cada observación tiene una influencia grande. La función puede calcularse, pero debe interpretarse con cautela. La estimación describe la muestra y no demuestra que toda la población tenga exactamente la misma forma.
La incertidumbre no desaparece por usar una curva continua. Si el análisis se presenta a otras personas, explica el tamaño de la muestra y evita conclusiones demasiado precisas.
Problemas en los límites
Algunas variables solo pueden ser positivas, como duración, precio o peso. Un kernel simétrico puede asignar densidad a valores negativos cerca del límite cero. Eso no significa que existan observaciones negativas; indica que el método estándar puede necesitar una transformación o una corrección de frontera.
Una transformación logarítmica puede ser útil en ciertos dominios positivos, pero debe aplicarse y revertirse correctamente. También es importante explicar la escala utilizada.
Detección de valores atípicos
Una aplicación sencilla consiste en evaluar nuevos valores y marcar los que tengan densidad muy baja.
historico = [100, 102, 98, 101, 99, 103, 97, 100]
f = kde(historico, h=2.0)
nuevo = 118
score = f(nuevo)
if score < 0.001:
print("Valor poco común; revisar")
Una densidad baja no convierte automáticamente el valor en error. Puede ser un evento raro pero legítimo. El umbral debe calibrarse con casos conocidos y revisarse cuando cambie la distribución.
Pruebas automatizadas
La estimación es determinista para la misma muestra y configuración. Por eso, puedes verificar propiedades simples: resultados no negativos, densidad mayor cerca de los grupos y cambios coherentes al modificar el ancho.
def test_densidad_mayor_cerca_de_la_muestra():
from statistics import kde
f = kde([0.0, 0.1, 0.2, 0.3], h=0.2)
assert f(0.15) > f(3.0)
assert f(0.15) >= 0
Evita comparar números flotantes con igualdad estricta cuando no sea necesario. Usa tolerancias o relaciones de comportamiento.
Rendimiento
Evaluar miles de puntos sobre una muestra grande puede ser costoso. No generes una resolución mayor de la necesaria. Reutiliza una cuadrícula cuando el gráfico se consulta varias veces y mide el rendimiento antes de optimizar.
Separa la limpieza, la construcción del estimador y la presentación. Esta arquitectura facilita las pruebas y permite reemplazar la implementación en el futuro. Para gestionar recursos dinámicos en pipelines, consulta contextlib.ExitStack en Python.
Cuándo usar bibliotecas externas
statistics.kde es excelente para aprendizaje, scripts, prototipos y proyectos que prefieren la biblioteca estándar. Sistemas científicos más complejos pueden necesitar KDE multidimensional, pesos por observación, selección automática del ancho, integración avanzada u operaciones vectorizadas. En esos casos, SciPy, NumPy, pandas, statsmodels o scikit-learn pueden ser mejores opciones.
La documentación oficial de statistics describe la API y los kernels disponibles. El NIST Engineering Statistics Handbook ofrece fundamentos estadísticos confiables.
Función auxiliar
from statistics import kde
def crear_densidad(valores, ancho, kernel="normal"):
limpios = [float(valor) for valor in valores]
if len(limpios) < 2:
raise ValueError("Se requieren al menos dos observaciones")
if ancho <= 0:
raise ValueError("El ancho debe ser positivo")
return kde(limpios, h=ancho, kernel=kernel)
Un wrapper centraliza validaciones y hace explícita la configuración. En una aplicación real puede añadir controles de valores finitos, unidades, logs y versiones de la muestra.
Buenas prácticas
Registra la versión de Python, porque la API depende de versiones modernas. Mantén unidades consistentes. Conserva la muestra original. Compara varios anchos antes de elegir. Guarda el kernel y el ancho junto con los resultados. No llames probabilidad al valor puntual de densidad.
También debes vigilar cambios de distribución. Un estimador creado con datos antiguos puede dejar de representar tráfico, precios o comportamiento actuales. Define una política para reconstruirlo y recalibrar umbrales.
Conclusión
statistics.kde permite analizar distribuciones sin instalar dependencias externas. Puede revelar grupos, comparar formas, alimentar gráficos y crear scores básicos de anomalía. Sin embargo, su utilidad depende de datos limpios, un ancho justificado y una comunicación clara de las limitaciones.
Comienza con una muestra pequeña, evalúa una cuadrícula y compara varios anchos. Después añade pruebas, documentación y monitoreo. De esa forma, la curva deja de ser solamente visual y se convierte en una herramienta estadística reproducible.







