【问题标题】:How do I include the upper boundary of the bins in Matplotlib hist [closed]如何在 Matplotlib hist 中包含 bin 的上边界 [关闭]
【发布时间】:2021-01-17 04:54:18
【问题描述】:

当使用来自 Matplotlib 的 hist() 创建直方图时,数据会这样落入 bin 中:

lb ≤ x < ub。我如何强制它表现得像这样:lb < x ≤ ub

此外,与 Excel 相比,频率表被移动了一个 bin,这对我的目的产生了不准确的测量结果。使用该表作为参考,我如何强制 hist() 使 28 到 30 之间的值落在 bin 30 而不是 bin 25 中?同样,值 23.5 在 Python 中的 bin 20 中下降,因为 bin 20 = 20 ≤ x

data = np.array([23.5, 28, 29, 29, 29.5, 29.5, 30, 30, 30])
bins = np.array([20, 25, 30])
# Excel               1, 8
# Python          1,  5

【问题讨论】:

  • 你用什么来计算的?我刚刚检查了我的机器,调用 plt.hist(a, bins=[20, 25, 30]) 会产生两个计数为 [1, 8] 的 bin。
  • 请不要发布代码、数据或 Tracebacks 的图像。将其复制并粘贴为文本,然后将其格式化为代码(选择它并输入ctrl-k)...Discourage screenshots of code and/or errors
  • how do I force hist() to... 查看 Matplotlib 源码;复制此功能并将其放入您的项目中;修改它来做你想做的事。?或者编写自己的 hist 函数。
  • 也许你可以利用它的一个或多个参数来捏造结果 - matplotlib.org/3.2.1/api/_as_gen/matplotlib.axes.Axes.hist.html
  • @Physmatik。抱歉,我提取了结果。我的垃圾箱实际上是范围(0,200,5)。如果包含 35 个 bin,则得到 [1, 5, 3]。我可以发布所有数据和结果,但这是我的核心问题,不想成为多余。

标签: python matplotlib histogram bins


【解决方案1】:

也许numpy.digitize 对您来说可能很有趣(来自文档):

Return the indices of the bins to which each value in input array belongs.

`right`    order of bins  returned index `i` satisfies
=========  =============  ============================
``False``  increasing     ``bins[i-1] <= x < bins[i]``
``True``   increasing     ``bins[i-1] < x <= bins[i]``
``False``  decreasing     ``bins[i-1] > x >= bins[i]``
``True``   decreasing     ``bins[i-1] >= x > bins[i]``

希望这也能消除使用垃圾箱时的常见误解。 bins 对应于一个网格的顶点,一个数据点位于 一个 bin 中的两个顶点/之间。因此,一个数据点不对应于bins 数组中的一个点,而是对应于两个。 从这个符号中可以看到另一件事,bins=[20, 25, 30] bin 1 从 20-25 到 bin 2 从 25-30,也许 excel 中的符号不​​同?

将关键字right 用于自定义直方图函数会产生以下代码和绘图。

import numpy as np
import matplotlib.pyplot as plt

data = np.array([15,
                 17, 18, 20, 20, 20,
                 23.5, 24, 25, 25,
                 28, 29, 30, 30, 30])
bins = np.array([15, 20, 25, 30])


def custom_hist(x, bins, right=False):
    x_dig = np.digitize(x, bins=bins, right=right)
    u, c = np.unique(x_dig, return_counts=True)
    h = np.zeros(len(bins), dtype=int)
    h[u] = c
    return h


plt.hist(data, bins=bins,  color='b', alpha=0.7, label='plt.hist')
# array([3., 5., 7.]

height = custom_hist(x=data, bins=bins, right=True)
width = np.diff(bins)
width = np.concatenate((width, width[-1:]))
plt.bar(bins-width, height=height, width=width,
        align='edge', color='r', alpha=0.7, label='np.digitize')
plt.legend()
# This function also allows different sized bins

注意在right=True的情况下15属于bin ?bins 中,它也会在直方图中为您提供第四个条形图。如果不希望这样做,您必须单独处理边缘情况,并可能将值添加到第一个有效的 bin。 我想这也是我们看到意外的原因 您的示例数据的行为。 Matplotlib 将lb ≤ x &lt; ub 应用于垃圾箱,但第 30 位与垃圾箱 25-30 相关联。 如果我们添加一个额外的 bin 30-35,我们可以看到现在 30ths 被放入了这个 bin。我猜他们除了边缘以外的所有地方都应用了规则lb ≤ x &lt; ub,这里使用lb ≤ x ≤ ub,这也是合理的,但必须注意这一点。

data = np.array([23.5, 28, 29, 29, 29.5, 29.5, 30, 30, 30])
plt.hist(data, bins=np.array([20, 25, 30]),  color='b', alpha=0.7, label='[20, 25, 30]')
plt.hist(data, bins=np.array([20, 25, 30, 35]),  color='r', alpha=0.7, label='[20, 25, 30, 35]')
plt.legend()

【讨论】:

  • 谢谢科学。使用 np.digitize 的 custom_hist() 效果很好。它现在与 Excel 对齐。我在直方图的第一个聚类中获得了更准确的结果。
猜你喜欢
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 2014-08-05
  • 2016-04-05
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多