绘制高度总和为1的直方图(概率)
我想用 matplotlib
从一个向量绘制一个归一化的直方图。我试过以下方法:
plt.hist(myarray, normed=True)
还有:
plt.hist(myarray, normed=1)
但是这两种方法都没有让y轴的范围从0到1,并且直方图的柱子高度加起来等于1。
6 个回答
我知道这个回答有点晚,因为这个问题是2010年的,但我在遇到类似问题时看到了这个问题。正如回答中提到的,normed=True意味着直方图下的总面积等于1,但高度的总和并不等于1。不过,我想为了方便理解直方图,让高度的总和等于1。
我在以下问题中找到了一个提示 - Python: 直方图的面积归一化为其他值而不是1
但我找不到让条形图模仿histtype="step"特性的办法。这让我转向了另一个问题:Matplotlib - 使用已分箱数据的阶梯直方图
如果大家觉得可以接受,我想提出一个结合了以上两个帖子想法的解决方案。
import matplotlib.pyplot as plt
# Let X be the array whose histogram needs to be plotted.
nx, xbins, ptchs = plt.hist(X, bins=20)
plt.clf() # Get rid of this histogram since not the one we want.
nx_frac = nx/float(len(nx)) # Each bin divided by total number of objects.
width = xbins[1] - xbins[0] # Width of each bin.
x = np.ravel(zip(xbins[:-1], xbins[:-1]+width))
y = np.ravel(zip(nx_frac,nx_frac))
plt.plot(x,y,linestyle="dashed",label="MyLabel")
#... Further formatting.
这个方法对我来说效果很好,不过在某些情况下,我注意到直方图最左边或最右边的“条”没有触碰到Y轴的最低点。在这种情况下,在y的开头或结尾添加一个0就能达到所需的效果。
只是想分享一下我的经验。谢谢。
如果你想让所有的柱状图的总和等于1,就需要根据总的数值来给每个柱子加权:
weights = np.ones_like(myarray) / len(myarray)
plt.hist(myarray, weights=weights)
注意:如果你使用的是Python 2.x版本,记得在除法的其中一个操作数上加上float()
,否则你可能会因为整数除法而得到0。
如果你能提供一个更完整的示例(无论是能运行的还是不能运行的),那会更有帮助。
我试了以下代码:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.randn(1000)
fig = plt.figure()
ax = fig.add_subplot(111)
n, bins, rectangles = ax.hist(x, 50, density=True)
fig.canvas.draw()
plt.show()
这确实会生成一个条形图直方图,y轴的范围是从 [0,1]
。
另外,根据 hist
的文档(也就是从 ipython
里可以查到的 ax.hist?
),我觉得总和也是可以的:
*normed*:
If *True*, the first element of the return tuple will
be the counts normalized to form a probability density, i.e.,
``n/(len(x)*dbin)``. In a probability density, the integral of
the histogram should be 1; you can verify that with a
trapezoidal integration of the probability density function::
pdf, bins, patches = ax.hist(...)
print np.sum(pdf * np.diff(bins))
在执行上面的命令后,我又试了这个:
np.sum(n * np.diff(bins))
我得到了一个返回值 1.0
,这正是我预期的。记住,normed=True
并不意味着每个条的值的总和是1,而是这些条的整体面积是1。在我的情况下,np.sum(n)
返回了大约 7.2767
。