Matplotlib 中的 bin 大小(直方图)

Posted

技术标签:

【中文标题】Matplotlib 中的 bin 大小(直方图)【英文标题】:Bin size in Matplotlib (Histogram) 【发布时间】:2011-10-22 15:40:36 【问题描述】:

我正在使用 matplotlib 制作直方图。

有没有办法手动设置 bin 的大小而不是 bin 的数量?

【问题讨论】:

【参考方案1】:

实际上,这很简单:您可以给出一个包含 bin 边界的列表,而不是 bin 的数量。它们也可能分布不均:

plt.hist(data, bins=[0, 10, 20, 30, 40, 50, 100])

如果你只是想让它们均匀分布,你可以简单地使用 range:

plt.hist(data, bins=range(min(data), max(data) + binwidth, binwidth))

添加到原始答案中

以上行适用于仅填充整数的data。正如macrocosme 指出的那样,您可以使用浮点数:

import numpy as np
plt.hist(data, bins=np.arange(min(data), max(data) + binwidth, binwidth))

【讨论】:

将 range(...) 替换为 np.arange(...) 以使其与浮点数一起使用。 这里的 binwidth 是多少?你之前设置过那个值吗? 我相信这个例子中的 binwidth 可以通过:(data.max() - data.min()) / number_of_bins_you_want 找到。 + binwidth 可以更改为 1 以使其更易于理解。 进一步了解上面 CodingCat 的出色解决方案,对于浮点数据,如果您希望直方图条以整数 x-ticks 为中心,而不是在 x-ticks 处设置条形边界,请尝试以下调整: bins = np.arange(dmin - 0.5, dmax + 0.5 + binwidth, binwidth) option lw = 5, color = "white" 或类似的在条之间插入白色间隙【参考方案2】:

对于 N 个 bin,bin 边缘由 N+1 个值的列表指定,其中第一个 N 给出 bin 下边缘,+1 给出最后一个 bin 的上边缘。

代码:

from numpy import np; from pylab import *

bin_size = 0.1; min_edge = 0; max_edge = 2.5
N = (max_edge-min_edge)/bin_size; Nplus1 = N + 1
bin_list = np.linspace(min_edge, max_edge, Nplus1)

注意 linspace 生成从 min_edge 到 max_edge 的数组,分成 N+1 个值或 N 个 bin

【讨论】:

请注意,bin 包括其下限,不包括其上限,但 N+1(最后一个)bin 除外,它包含两个边界。【参考方案3】:

我使用分位数来统一分类并拟合样本:

bins=df['Generosity'].quantile([0,.05,0.1,0.15,0.20,0.25,0.3,0.35,0.40,0.45,0.5,0.55,0.6,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1]).to_list()

plt.hist(df['Generosity'], bins=bins, normed=True, alpha=0.5, histtype='stepfilled', color='steelblue', edgecolor='none')

【讨论】:

好主意。您可以用np.arange(0, 1.01, 0.5)np.linspace(0, 1, 21) 替换分位数列表。没有边缘,但我知道盒子的面积相等,但 X 轴的宽度不同?【参考方案4】:

我想最简单的方法是计算你拥有的数据的最小值和最大值,然后计算L = max - min。然后你将L 除以所需的 bin 宽度(我假设这就是你所说的 bin 大小),并使用这个值的上限作为 bin 的数量。

【讨论】:

这正是我的想法,谢谢。只是想知道是否有更简单的方法,但这似乎找到了谢谢! 使用整数我没有用这种方法得到一个圆形的 bin 大小。有人经历过吗?【参考方案5】:

我喜欢事情自动发生,并且让垃圾箱落在“不错”的价值上。以下似乎工作得很好。

import numpy as np
import numpy.random as random
import matplotlib.pyplot as plt
def compute_histogram_bins(data, desired_bin_size):
    min_val = np.min(data)
    max_val = np.max(data)
    min_boundary = -1.0 * (min_val % desired_bin_size - min_val)
    max_boundary = max_val - max_val % desired_bin_size + desired_bin_size
    n_bins = int((max_boundary - min_boundary) / desired_bin_size) + 1
    bins = np.linspace(min_boundary, max_boundary, n_bins)
    return bins

if __name__ == '__main__':
    data = np.random.random_sample(100) * 123.34 - 67.23
    bins = compute_histogram_bins(data, 10.0)
    print(bins)
    plt.hist(data, bins=bins)
    plt.xlabel('Value')
    plt.ylabel('Counts')
    plt.title('Compute Bins Example')
    plt.grid(True)
    plt.show()

结果的 bin 大小间隔很好。

[-70. -60. -50. -40. -30. -20. -10.   0.  10.  20.  30.  40.  50.  60.]

【讨论】:

正是我想要的!但是,在某些情况下,由于浮点精度,n_bins 会向下舍入。例如。对于desired_bin_size=0.05min_boundary=0.850max_boundary=2.05n_bins 的计算变为int(23.999999999999993),导致 23 而不是 24,因此一个 bin 太少。整数转换之前的舍入对我有用:n_bins = int(round((max_boundary - min_boundary) / desired_bin_size, 0)) + 1【参考方案6】:

我遇到了与 OP 相同的问题(我想!),但我无法让它按照 Lastalda 指定的方式工作。我不知道我是否正确解释了这个问题,但我找到了另一种解决方案(虽然这可能是一种非常糟糕的方法)。

我就是这样做的:

plt.hist([1,11,21,31,41], bins=[0,10,20,30,40,50], weights=[10,1,40,33,6]);

这是由谁创造的:

所以第一个参数基本上“初始化”了 bin - 我专门创建了一个介于我在 bins 参数中设置的范围之间的数字。

为了证明这一点,请查看第一个参数 ([1,11,21,31,41]) 中的数组和第二个参数 ([0,10,20,30,40, 50]):

数字 1(来自第一个数组)介于 0 和 10 之间(在“bins”数组中) 数字 11(来自第一个数组)介于 11 和 20 之间(在 'bins' 数组中) 数字 21(来自第一个数组)介于 21 和 30 之间(在“bins”数组中),等等。

然后我使用 'weights' 参数来定义每个 bin 的大小。这是用于权重参数的数组:[10,1,40,33,6]。

所以 0 到 10 的 bin 的值为 10,11 到 20 的 bin 的值为 1,21 到 30 的 bin 的值为 40,以此类推。

【讨论】:

我认为您对直方图函数的工作原理有一个基本的误解。它需要原始数据。因此,在您的示例中,您的数据数组应包含 0 到 10 之间的 10 个值,10 到 20 之间的 1 个值,依此类推。然后该函数进行总结和绘图。您在上面所做的是一种解决方法,因为您已经有了总和(然后您通过滥用“权重”选项将其插入到图表中)。希望这能消除一些困惑。【参考方案7】:

此答案支持@macrocosme 建议。

我使用热图作为 hist2d 图。此外,我使用 cmin=0.5 表示无计数值,使用 cmap 表示颜色,r 表示给定颜色的反转。

描述统计数据。

# np.arange(data.min(), data.max()+binwidth, binwidth)
bin_x = np.arange(0.6, 7 + 0.3, 0.3)
bin_y = np.arange(12, 58 + 3, 3)
plt.hist2d(data=fuel_econ, x='displ', y='comb', cmin=0.5, cmap='viridis_r', bins=[bin_x, bin_y]);
plt.xlabel('Dispalcement (1)');
plt.ylabel('Combine fuel efficiency (mpg)');

plt.colorbar();

【讨论】:

【参考方案8】:

对于具有整数 x 值的直方图,我最终使用了

plt.hist(data, np.arange(min(data)-0.5, max(data)+0.5))
plt.xticks(range(min(data), max(data)))

0.5 的偏移量使 bin 位于 x 轴值的中心。 plt.xticks 调用为每个整数添加一个刻度。

【讨论】:

【参考方案9】:

如果您也在查看可视化方面,您可以添加 edgecolor='white', linewidth=2 并将分箱分开:

date_binned = new_df[(new_df['k']>0)&(new_df['k']<360)]['k']
plt.hist(date_binned, bins=range(min(date_binned), max(date_binned) + binwidth, binwidth), edgecolor='white', linewidth=2)

【讨论】:

以上是关于Matplotlib 中的 bin 大小(直方图)的主要内容,如果未能解决你的问题,请参考以下文章

使用 matplotlib 在单个图表上绘制两个直方图

matplotlib hist() 中的条之间的间距与数千个箱

直方图 Matplotlib

Matplotlib 直方图或 Seaborn 分布图的 bin 上没有轮廓

不写一行代码,即可调用 Matplotlib 绘图!

matplotlib可视化篇hist()--直方图