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

75 python numpy graph matplotlib scipy

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

plt.hist(myarray, normed=True)
Run Code Online (Sandbox Code Playgroud)

以及:

plt.hist(myarray, normed=1)
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Car*_*nig 186

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

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)
Run Code Online (Sandbox Code Playgroud)

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

  • 很好的答案.注意,如果myarray是一个python`array_like`而不是一个numpy数组,你需要将`len(myarray)`强制转换为`float`. (8认同)
  • 此外,如果 myarray 是多维的并且您只使用一维,例如 myarray[0,:],那么您可以将 len(myarray) 替换为 np.size(myarray[0,:]) 并且这将起作用同样的方法。(否则,它说该对象不可调用。) (3认同)

dtl*_*ier 44

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

我尝试了以下方法:

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()
Run Code Online (Sandbox Code Playgroud)

这确实会产生一个条形图直方图,其y轴来自[0,1].

此外,根据hist文件(即ax.hist?来自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))
Run Code Online (Sandbox Code Playgroud)

在上面的命令之后尝试一下:

np.sum(n * np.diff(bins))
Run Code Online (Sandbox Code Playgroud)

我得到了1.0预期的返回值.请记住,normed=True这并不意味着每个柱子上的值的总和将是统一的,而不是棒上的积分是统一的.在我的情况下np.sum(n)返回约7.2767.

  • 是的,那是概率密度图,我想他想要一个概率质量图。 (3认同)

Kil*_*ler 19

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

我在下面的问题中找到了一个提示 - Python:直方图,区域标准化为1以外的其他值

但我无法找到一种方法来制作模仿histt​​ype ="step"特征hist()的条形图.这使我转向: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.
Run Code Online (Sandbox Code Playgroud)

这对我来说非常有效,尽管在某些情况下我注意到直方图的最左边的"条形"或最右边的"条形"没有通过触摸Y轴的最低点而关闭.在这种情况下,在y的乞讨或结束处添加元素0实现了必要的结果.

只是想我会分享我的经验.谢谢.


Yur*_*man 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)
Run Code Online (Sandbox Code Playgroud)

您确实可以检查总和最多为1:

> print sum(results*binWidth)
1.0
Run Code Online (Sandbox Code Playgroud)


Tre*_*ney 9

进口和数据

import seaborn as sns
import matplotlib.pyplot as plt

# load data
df = sns.load_dataset('penguins')
Run Code Online (Sandbox Code Playgroud)

sns.histplot

# create figure and axes
fig, ax = plt.subplots(figsize=(6, 5))

p = sns.histplot(data=df, x='flipper_length_mm', stat='probability', ax=ax)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

sns.displot

# create figure and axes
fig, ax = plt.subplots(figsize=(6, 5))

p = sns.histplot(data=df, x='flipper_length_mm', stat='probability', ax=ax)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述