Matplotlib直方图未正确计算每个bin中的值数量

问题描述

我正在尝试使用matplotlib.pyplot.hist创建一个非常简单的直方图,而且似乎没有正确地计算每个bin中的值数量。这是我的代码

    import numpy as np
    import matplotlib.pyplot as plt
    plt.hist([.2,.3,.5,.6],bins=np.arange(0,1.1,.1))

我将间隔[0,1]划分为宽度为.1的区间,所以我应该得到四个高度为1的条形图。但是输出图形仅包含两个高度为2的条形图:正在计算.3值作为[.2,.3)bin的一部分,并且类似地,它会将.6值作为[.5,.6)bin的一部分。我在Spyder和Google Colab上都尝试过。有人知道发生了什么吗?谢谢!

解决方法

问题在于值仅落在垃圾箱的边界上。 Floating point rounding可以将它们放在上一个或下一个垃圾箱中。您需要在数据点之间很好地划分bin边界。请注意,matplotlib的直方图主要用于浮点舍入没有太大影响的连续分布。

以下代码说明了两种情况下发生的情况:

import numpy as np
import matplotlib.pyplot as plt

data = [.2,.3,.5,.6]

fig,axes = plt.subplots(ncols=2,figsize=(12,4))

for ax in axes:
    if ax == axes[0]:
        bins = np.arange(0,1.1,.1)
        ax.set_title('data on bin boundaries')
    else:
        bins = np.arange(-0.05,.1)
        ax.set_title('data between bin boundaries')
    values,bin_bounds,bars = ax.hist(data,bins=bins,alpha=0.3)

    ax.vlines(bin_bounds,max(values),color='crimson',ls=':')
    ax.scatter(data,np.full_like(data,0.5),color='lime',s=30)
    ax.set_ylim(0,2.2)
    ax.set_yticks(range(3))
plt.show()

illustrating plot

,

来自the docs

如果 bins 是一个序列,则它定义bin边缘,包括第一个bin的左边缘和最后一个bin的右边缘;在这种情况下,垃圾箱的间距可能不相等。除了最后一个(最右边)的垃圾箱外,其他所有垃圾箱都是半开的。换句话说,如果bin是:

[1,2,3,4]

然后,第一个容器是[1,2)(包括1,但不包括2),第二个容器是[2,3]。但是,最后一个bin是[3,4],其中包括4。

因为间隔是封闭打开的,所以.2和.3都落在同一容器中,而.5和.6都落在另一个容器中。

您应该通过稍微移动边界来固定垃圾箱,以免数字落在边缘。