在matplotlib中绘制条形高度总和为1的直方图

时间:2010-10-05 18:21:10

标签: python graph numpy matplotlib scipy

我想使用matplotlib从矢量绘制标准化的直方图。我尝试了以下方法:

plt.hist(myarray, normed=True)

以及:

plt.hist(myarray, normed=1)

但两个选项都不会从[0,1]生成y轴,使得直方图的条形高度总和为1.我想生成这样的直方图 - 我该怎么做?

谢谢!

5 个答案:

答案 0 :(得分:178)

如果您希望所有柱的总和等于1,请将每个仓的重量乘以总值:

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)

希望有所帮助,虽然线程很老......

答案 1 :(得分:42)

如果你提出一个更完整的工作(或在这种情况下是非工作)的例子会更有帮助。

我尝试了以下内容:

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文档(即来自ax.hist?的{​​{1}}),我认为总和也很好:

ipython

在上述命令之后尝试一下:

*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返回约np.sum(n)

答案 2 :(得分:17)

我知道这个答案为时已晚,因为问题是2010年,但我遇到了这个问题,因为我自己也遇到了类似的问题。正如答案中已经说明的那样,normed = True表示直方图下的总面积等于1,但高度之和不等于1.但是,为了方便直方图的物理解释,我想做一个总和等于1。

我在以下问题中找到了一个提示 - Python: Histogram with area normalized to something other than 1

但是我无法找到一种方法来制作模仿histt​​ype =“step”特征hist()的条形图。这使我转向:Matplotlib - Stepped histogram with already binned data

如果社区认为可以接受,我想提出一个解决方案,综合上述帖子中的想法。

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轴的最低点而关闭,但这对我来说非常有效。在这种情况下,在乞讨或结束时添加元素0可以获得必要的结果。

想到我会分享我的经验。谢谢。

答案 3 :(得分:10)

这是使用np.histogram()方法的另一个简单解决方案。

myarray = np.random.random(100)
results, edges = np.histogram(myarray, normed=True)
binWidth = edges[1] - edges[0]
plt.bar(edges[:-1], results*binWidth, binWidth)

您确实可以通过以下方式检查总和最多为1

> print sum(results*binWidth)
1.0

答案 4 :(得分:0)

自 matplotlib 3.0.2 起,normed=True 已弃用。为了获得所需的输出,我必须这样做:

import numpy as np
data=np.random.randn(1000)
bins=np.arange(-3.0,3.0,51)
counts, _ = np.histogram(data,bins=bins)
if density: # equivalent of normed=True
    counts_weighter=counts.sum()
else: # equivalent of normed=False
    counts_weighter=1.0
plt.hist(bins[:-1],bins=bins,weights=counts/counts_weighter)

尝试同时指定 weightsdensity 作为 plt.hist() 的参数对我不起作用。如果有人知道无需访问规范关键字参数即可使其工作的方法,请在评论中告诉我,我将删除/修改此答案。

如果您想要 bin 中心,则不要使用 bins[:-1] 作为 bin 边缘 - 您需要选择合适的方案来计算中心(可能会也可能不会简单地推导出)。

>