在同一图中归一化两个直方图

9

我很乐意为您提供以下帮助。

我想在一个共同的直方图上绘制两个数据集,使得两个直方图都不被截断,并且概率分布范围从0到1。

让我解释一下我的意思。到目前为止,我可以很好地在一个直方图上绘制两个数据集,并通过在ax.hist()中写入normed = 1来强制两个分布的积分为1,如下图所示: enter image description here

这是通过类似以下代码生成的:

        x1, w1, patches1 = ax.hist(thing1, bins=300, edgecolor='b', color='b', histtype='stepfilled', alpha=0.2, normed = 1)

        x2, w2, patches2 = ax.hist(thing2, bins=300, edgecolor='g', color='g', histtype='stepfilled', alpha=0.2, normed = 1)             

通常情况下,一个概率分布远高于另一个,这使得难以清晰地阅读图形。

因此,我尝试将它们归一化,使它们在y轴上的范围都从0到1,并仍然保持其形状。例如,我尝试使用以下代码:

for item in patches1:
    item.set_height(item.get_height()/sum(x1))

这段文字是从这里的讨论中提取的(如何在Python中对直方图进行归一化?),但是Python会报错,说没有get_height这样的质量。

我的问题很简单:我该如何使y轴范围从0到1,并保留两个分布的形状?

2个回答

12

我建议使用numpy预先计算直方图,然后使用matplotlib中的bar绘制它们。然后可以通过除以每个直方图的最大振幅来简单地对直方图进行归一化。请注意,为了在两个直方图之间获得任何有意义的比较,最好对它们都使用相同的bins。以下是如何实现的一个示例:

from matplotlib import pyplot as plt
import numpy as np

##some random distribution
dist1 = np.random.normal(0.5, 0.25, 1000)
dist2 = np.random.normal(0.8, 0.1, 1000)

##computing the bin properties (same for both distributions)
num_bin = 50
bin_lims = np.linspace(0,1,num_bin+1)
bin_centers = 0.5*(bin_lims[:-1]+bin_lims[1:])
bin_widths = bin_lims[1:]-bin_lims[:-1]

##computing the histograms
hist1, _ = np.histogram(dist1, bins=bin_lims)
hist2, _ = np.histogram(dist2, bins=bin_lims)

##normalizing
hist1b = hist1/np.max(hist1)
hist2b = hist2/np.max(hist2)

fig, (ax1,ax2) = plt.subplots(nrows = 1, ncols = 2)

ax1.bar(bin_centers, hist1, width = bin_widths, align = 'center')
ax1.bar(bin_centers, hist2, width = bin_widths, align = 'center', alpha = 0.5)
ax1.set_title('original')

ax2.bar(bin_centers, hist1b, width = bin_widths, align = 'center')
ax2.bar(bin_centers, hist2b, width = bin_widths, align = 'center', alpha = 0.5)
ax2.set_title('ampllitude-normalized')

plt.show()

这是它的外观:

在此输入图像描述

希望这可以帮到您。


谢谢你的建议,Thomas。我会在接下来的几天尝试一下,并告诉你结果如何。 - inquiries
不错!话说,使用seaborn/matplotlib肯定有内置的方法来做到这一点。这似乎是一个常见的情况...? - GrimSqueaker
@GrimSqueaker 可能有。另一方面,我不确定比较两个幅度归一化的直方图有多大用处。回顾一下,也许在这里使用 twinx() 并保留未缩放的直方图会更直观。 - Thomas Kühn

3

我已经尝试将两个图形归一化,使它们在y轴上的值都在0到1之间,并且仍保持它们的形状。

这种方法不能将您的图形放在0到1的比例尺上,但是它可以使它们相对于彼此处于相同的比例尺:

只需在plt.hist()函数调用中设置参数density=True,如下所示:

plt.hist([array_1, array2], density=True)

这将在相同的比例尺下绘制两个分布,使得每个曲线下的面积之和为1。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接