【问题标题】:Normalizing two histograms in the same plot在同一个图中对两个直方图进行归一化
【发布时间】:2018-06-08 12:15:19
【问题描述】:

我将不胜感激以下任何见解。

我想在一个常见的直方图上绘制两个数据集,这样两个直方图都没有顶部截止并且概率分布范围为 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)             

在一般情况下,一种概率分布比另一种高得多,因此很难清楚地阅读情节。

因此,我尝试对两者进行归一化,以使它们在 y 轴上的范围都在 0 到 1 之间,并且仍然保持它们的形状。例如,我尝试过以下代码:

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

取自 How to normalize a histogram in python? 此处的讨论,但 python 向我抛出一条错误消息,说没有 get_height 这样的质量。

我的问题很简单:我怎样才能让 y 轴的范围从 0 到 1 并保持两个分布的形状?

【问题讨论】:

    标签: database matplotlib histogram bar-chart normalization


    【解决方案1】:

    我建议使用numpy 预先计算直方图,然后使用barmatplotlib 中绘制它们。然后可以通过除以每个直方图的最大幅度来简单地对直方图进行归一化(按幅度)。请注意,为了在两个直方图之间进行任何有意义的比较,最好对两个直方图使用相同的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。我会在接下来的几天里试试这个,让你知道它是怎么回事。
    • 整洁!也就是说,必须有一种内置的方式来使用 seaborn/matplotlib 执行此操作。这似乎是一个常见的场景……?
    • @GrimSqueaker 可能有。另一方面,我不太确定比较两个幅度归一化直方图有多大用处。回想起来,也许在这里使用twinx() 并保持直方图不缩放会更直观。
    【解决方案2】:

    我尝试对两者进行归一化,使它们在 y 轴上的范围都在 0 到 1 之间,并且仍然保持它们的形状。

    这种方法不会使您的地块达到 0 到 1 的比例,但它会使它们彼此之间相对具有相同的比例:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-16
      • 1970-01-01
      • 2014-12-31
      • 2013-06-20
      • 2015-01-10
      • 2015-01-15
      相关资源
      最近更新 更多