Matplotlib:如何制作具有相等面积区间的直方图?

时间:2016-06-06 03:58:33

标签: python matplotlib histogram binning

给定一些任意分布后的数字列表,如何定义tslint.json的bin位置,以便每个bin中的区域等于(或接近)某个常量区域A?应该通过将箱子中的物品数量乘以箱子的宽度来计算该面积,其值应不大于A.

这是一个MWE,用于显示具有正态分布的样本数据的直方图:

matplotlib.pyplot.hist()

此处import matplotlib.pyplot as plt import numpy as np x = np.random.randn(100) plt.hist(x, bin_pos) plt.show() 是表示区间边界位置的列表(请参阅相关问题here

1 个答案:

答案 0 :(得分:10)

我发现这个问题很有趣。解决方案取决于您是要绘制密度函数还是真实直方图。后一种情况变得更具挑战性。 Here更多关于直方图和密度函数之间差异的信息。

密度函数

这将为密度函数提供所需的功能:

def histedges_equalN(x, nbin):
    npt = len(x)
    return np.interp(np.linspace(0, npt, nbin + 1),
                     np.arange(npt),
                     np.sort(x))

x = np.random.randn(1000)
n, bins, patches = plt.hist(x, histedges_equalN(x, 10), normed=True)

请注意normed=True的使用,它指定我们正在计算和绘制密度函数。在这种情况下,区域相同(您可以通过查看n * np.diff(bins)来查看)。另请注意,此解决方案涉及查找具有相同点数的分档。

equal area density function

直方图

这是一个为直方图提供大致相等的面积框的解决方案:

def histedges_equalA(x, nbin):
    pow = 0.5
    dx = np.diff(np.sort(x))
    tmp = np.cumsum(dx ** pow)
    tmp = np.pad(tmp, (1, 0), 'constant')
    return np.interp(np.linspace(0, tmp.max(), nbin + 1),
                     tmp,
                     np.sort(x))

n, bins, patches = plt.hist(x, histedges_equalA(x, nbin), normed=False)

然而,这些盒子并非都是平等的。特别是,第一个和最后一个比其他的大约30%。这是正态分布尾部数据稀疏分布的人为因素,我相信只要数据集中人口稀少,它就会持续存在。

旁注:我稍微使用了值pow,发现大约0.56的值对于正态分布而言RMS error较低。我坚持使用平方根,因为当数据紧密间隔时(相对于bin宽度)它表现最好,而且我很确定它有一个理论基础,我没有费心去挖掘(人?)。

nearly equal area histogram

等面积直方图的问题

据我所知,无法获得此问题的确切解决方案。这是因为它对数据的离散化很敏感。例如,假设数据集中的第一个点是-13的异常值,下一个值是-3,如此图像中的红点所示:

Diagram demonstrating histogram bin areas

现在假设你的直方图的总“面积”是150,你想要10个箱子。在这种情况下,每个直方图条的面积应该是大约15,但是你无法到达那里,因为只要你的条包含第二个点,它的区域就会从10跳到20.也就是说,数据不允许这个条形一个解决方案可能是调整框的下限以增加其面积,但这开始变得任意,如果这个'间隙'在数据集。

相关问题