Database 规范化同一绘图中的两个直方图

Database 规范化同一绘图中的两个直方图,database,matplotlib,histogram,bar-chart,normalization,Database,Matplotlib,Histogram,Bar Chart,Normalization,我希望您能对以下内容有所了解 我想在一个公共直方图上绘制两个数据集,这样两个直方图的顶部都没有截断,并且概率分布在0到1之间 让我解释一下我的意思。到目前为止,我可以很好地将两个数据集绘制在一个直方图上,并通过在ax.hist()中写入normed=1,强制两个分布的积分为1,如下图所示: 这是由这样的代码生成的: x1, w1, patches1 = ax.hist(thing1, bins=300, edgecolor='b', color='b', histtype='s

我希望您能对以下内容有所了解

我想在一个公共直方图上绘制两个数据集,这样两个直方图的顶部都没有截断,并且概率分布在0到1之间

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

这是由这样的代码生成的:

        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)             
plt.hist([array_1, array2], density=True)
在一般情况下,一个概率分布比另一个概率分布高得多,这使得很难清晰地阅读图

所以,我试着对它们进行归一化,这样它们在y轴上的范围都在0到1之间,并且仍然保持它们的形状。例如,我尝试了以下代码:

for item in patches1:
    item.set_height(item.get_height()/sum(x1))
这是从这里的讨论中得到的,但是python向我抛出了一条错误消息,说没有像
get\u height
这样的质量


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

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

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()
这张照片是什么样子的:

希望这有帮助

我已经尝试将两者归一化,这样它们在y轴上的范围都在0到1之间,并且仍然保持它们的形状

此方法不会以0到1的比例绘制曲线图,但会以相同的比例绘制曲线图:

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

        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)             
plt.hist([array_1, array2], density=True)

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

谢谢您的建议,Thomas。我会在接下来的几天里试试这个,让你知道它是怎么回事。太棒了!也就是说,必须有一种内置的方式来使用seaborn/matplotlib实现这一点。。这似乎是一种常见的情况…?@GrimSqueaker可能有。另一方面,我不确定比较两个振幅归一化直方图有多有用。回顾这一点,在这里使用
twinx()
并保持直方图不缩放可能会更直观。