Cómo crear un gráfico de densidad

6 minutos de lectura

avatar de usuario de unode
unode

En RI puede crear la salida deseada haciendo:

data = c(rep(1.5, 7), rep(2.5, 2), rep(3.5, 8),
         rep(4.5, 3), rep(5.5, 1), rep(6.5, 8))
plot(density(data, bw=0.5))

Diagrama de densidad en R

En python (con matplotlib) lo más cercano que obtuve fue con un histograma simple:

import matplotlib.pyplot as plt
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
plt.hist(data, bins=6)
plt.show()

Histograma en matplotlib

yo también probé el parámetro normed=True pero no pudo obtener nada más que tratar de ajustar un gaussiano al histograma.

Mis últimos intentos estaban alrededor scipy.stats y gaussian_kdesiguiendo ejemplos en la web, pero hasta ahora no he tenido éxito.

Cinco años después, cuando busqué en Google “cómo crear un diagrama de densidad del kernel usando Python”, ¡este hilo todavía aparece en la parte superior!

Hoy en día, una forma mucho más fácil de hacer esto es usar nacido en el marun paquete que proporciona muchas funciones de trazado convenientes y una buena gestión de estilo.

import numpy as np
import seaborn as sns
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
sns.set_style('whitegrid')
sns.kdeplot(np.array(data), bw=0.5)

ingrese la descripción de la imagen aquí

  • Muchas gracias. He estado buscando algo como esto desde hace días. ¿Pueden explicar por qué el bw=0.5 ¿es dado?

    – Sitz Blogz

    19/04/2016 a las 15:00

  • @SitzBlogz El bw parámetro significa ancho de banda. Estaba tratando de hacer coincidir la configuración de OP (ver su primer ejemplo de código original). Para una explicación detallada de lo que bw controles, ver es.wikipedia.org/wiki/…. Básicamente, controla qué tan suave desea que sea el gráfico de densidad. Cuanto mayor sea el bw, más suave será.

    – Xin

    19/04/2016 a las 19:26

  • Tengo otra consulta para pedir que mis datos sean de naturaleza discreta y estoy tratando de trazar el PDF para eso, después de leer el documento scipy entendí que PMF = PDF ¿alguna sugerencia sobre cómo trazarlo?

    – Sitz Blogz

    19/04/2016 a las 19:31

  • Cuando pruebo esto me sale TypeError: slice indices must be integers or None or have an __index__ method

    – endolito

    16 de febrero de 2017 a las 2:26

  • Solo quiero agregar que el bw El parámetro está en desuso y se puede quitar como punto de partida.

    – Pasas

    1 de diciembre de 2021 a las 16:27

Avatar de usuario de Justin Peel
justin pelar

Sven ha mostrado cómo usar la clase. gaussian_kde de Scipy, pero notará que no se parece mucho a lo que generó con R. Esto se debe a que gaussian_kde intenta inferir el ancho de banda automáticamente. Puedes jugar con el ancho de banda de alguna manera cambiando la función covariance_factor del gaussian_kde clase. Primero, esto es lo que obtienes sin cambiar esa función:

texto alternativo

Sin embargo, si uso el siguiente código:

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
density = gaussian_kde(data)
xs = np.linspace(0,8,200)
density.covariance_factor = lambda : .25
density._compute_covariance()
plt.plot(xs,density(xs))
plt.show()

yo obtengo

texto alternativo

que es bastante parecido a lo que obtienes de R. ¿Qué he hecho? gaussian_kde utiliza una función cambiable, covariance_factor para calcular su ancho de banda. Antes de cambiar la función, el valor devuelto por covariance_factor para estos datos era de aproximadamente 0,5. Reducir esto redujo el ancho de banda. tuve que llamar _compute_covariance después de cambiar esa función para que todos los factores se calculen correctamente. No es una correspondencia exacta con el parámetro bw de R, pero espero que lo ayude a ir en la dirección correcta.

  • A set_bandwidth método y un bw_method el argumento del constructor se agregó a gaussian_kde en scipy 0.11.0 por número 1619

    – eddygeek

    22 de enero de 2015 a las 14:46

  • Para vincular con otras respuestas, en la implementación de kde seaborn o pandas, el kde predeterminado es el gaussian_kde.

    – Ger

    5 de diciembre de 2017 a las 15:01

Avatar de usuario de Aziz Alto
Aziz Alto

Opción 1:

Usar pandas gráfico de marco de datos (construido sobre matplotlib):

import pandas as pd
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
pd.DataFrame(data).plot(kind='density') # or pd.Series()

ingrese la descripción de la imagen aquí

Opcion 2:

Usar distplot de seaborn:

import seaborn as sns
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
sns.distplot(data, hist=False)

ingrese la descripción de la imagen aquí

  • Para agregar el parámetro de ancho de banda: df.plot.density(bw_method=0.5)

    – Anake

    25 de agosto de 2016 a las 13:41

  • @Aziz No es necesario pandas.DataFramepuedo usar pandas.Series(data).plot(kind='density') @Anake, no es necesario configurar df.plot.density como un paso separado; puede simplemente pasar en su bw_method kwarg en pd.Series(data).plot(kind='density', bw_method=0.5)

    –Nate Anderson

    18 de diciembre de 2017 a las 1:29


Tal vez intente algo como:

import matplotlib.pyplot as plt
import numpy
from scipy import stats
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
density = stats.kde.gaussian_kde(data)
x = numpy.arange(0., 8, .1)
plt.plot(x, density(x))
plt.show()

Puedes reemplazar fácilmente gaussian_kde() por una estimación diferente de la densidad del kernel.

avatar de usuario de tetrisforjeff
tetrisforjeff

El gráfico de densidad también se puede crear usando matplotlib: La función plt.hist(data) devuelve los valores de y y x necesarios para el gráfico de densidad (consulte la documentación https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.hist.html). Como resultado, el siguiente código crea un gráfico de densidad utilizando la biblioteca matplotlib:

import matplotlib.pyplot as plt
dat=[-1,2,1,4,-5,3,6,1,2,1,2,5,6,5,6,2,2,2]
a=plt.hist(dat,density=True)
plt.close()
plt.figure()
plt.plot(a[1][1:],a[0])      

Este código devuelve el siguiente diagrama de densidad

ingrese la descripción de la imagen aquí

  • Esta respuesta merece un voto negativo. Sin embargo, no lo haré, los votos negativos son malos, pero explique qué está mal: las estimaciones de densidad de una muestra (conjunto de puntos de datos) generalmente involucran alisado. Esto es lo que R density() hace la función, o lo que SciPy’s gaussian_kde() hace. El resultado es una aproximación de la densidad continua de la que supuestamente provienen los puntos de datos, y eso es lo que buscaba el OP.

    –András Aszodi

    13 oct 2020 a las 13:38

avatar de usuario de zerryberry
zarzamora

Puedes hacer algo como:

s = np.random.normal(2, 3, 1000)
import matplotlib.pyplot as plt
count, bins, ignored = plt.hist(s, 30, density=True)
plt.plot(bins, 1/(3 * np.sqrt(2 * np.pi)) * np.exp( - (bins - 2)**2 / (2 * 3**2) ), 
linewidth=2, color="r")
plt.show()

  • Esta respuesta merece un voto negativo. Sin embargo, no lo haré, los votos negativos son malos, pero explique qué está mal: las estimaciones de densidad de una muestra (conjunto de puntos de datos) generalmente involucran alisado. Esto es lo que R density() hace la función, o lo que SciPy’s gaussian_kde() hace. El resultado es una aproximación de la densidad continua de la que supuestamente provienen los puntos de datos, y eso es lo que buscaba el OP.

    –András Aszodi

    13 oct 2020 a las 13:38

¿Ha sido útil esta solución?