如何在 matplotlib 中创建密度图?

在 R 中,我可以通过以下步骤创建所需的输出:

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))

Density plot in R

在 python (使用 matplotlib)中,我得到的最接近的结果是一个简单的直方图:

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()

Histogram in matplotlib

我也尝试了 参数,但是除了试图将高斯分布图与直方图进行匹配之外,我什么也得不到。

我最近的尝试是围绕 scipy.statsgaussian_kde,下面的例子在网络上,但我一直没有成功到目前为止。

305006 次浏览

也许可以试试这样:

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()

您可以很容易地用不同的内核密度估计来替换 gaussian_kde()

Sven 已经展示了如何使用来自 Scipy 的类 gaussian_kde,但是您会注意到,它看起来与您使用 R 生成的类不太一样。这是因为 gaussian_kde尝试自动推断带宽。您可以通过改变 gaussian_kde类的函数 covariance_factor来使用带宽。首先,在不改变函数的情况下可以得到以下结果:

alt text

但是,如果我使用以下代码:

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()

我明白

alt text

这和你从 R 那里得到的很接近。我做了什么?gaussian_kde使用一个可变函数 covariance_factor来计算它的带宽。在更改函数之前,协方差 _ factor 为这个数据返回的值大约是5。降低这个频率会降低带宽。在更改该函数之后,我必须调用 _compute_covariance,以便正确计算所有因子。它与 R 中的 bw 参数并不完全一致,但希望它能帮助您找到正确的方向。

五年后,当我在谷歌上搜索“如何使用 python 创建内核密度图”时,这个线程仍然出现在顶部!

现在,一种更简单的方法是使用 海运,它提供了许多方便的绘图函数和良好的样式管理。

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)

enter image description here

选择1:

使用 pandas数据帧图(建立在 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()

enter image description here

选择2:

使用 seaborndistplot:

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)

enter image description here

还可以使用 matplotlib 创建密度图: 函数 plt.hist (data)返回密度图所需的 y 和 x 值(参见文档 https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.hist.html)。 结果,下面的代码使用 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])

此代码返回以下密度图

enter image description here

你可以这样做:

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()