【问题标题】:Dividing matplotlib histogram by maximum bin value将 matplotlib 直方图除以最大 bin 值
【发布时间】:2015-07-10 23:39:43
【问题描述】:

我想在同一个图上绘制多个直方图,我需要比较数据的分布。我想通过将每个直方图除以其最大值来做到这一点,这样所有分布都具有相同的比例。但是,matplotlib 的直方图函数的工作方式,我还没有找到一种简单的方法来做到这一点。

这是因为n在

n, bins, patches = ax1.hist(y, bins = 20, histtype = 'step', color = 'k')

是每个 bin 中的计数数,但我无法将其重新传递给 hist,因为它会重新计算。

我尝试了范数和密度函数,但这些函数是对分布区域的归一化,而不是对分布的高度进行归一化。我可以复制 n 然后使用 bins 输出重复 bin 边缘,但这很乏味。当然 hist 函数必须允许将 bin 值除以常数吗?

示例代码如下,演示了问题。

y1 = np.random.randn(100)
y2 = 2*np.random.randn(50)
x1 = np.linspace(1,101,100)
x2 = np.linspace(1,51,50)
gs = plt.GridSpec(1,2, wspace = 0, width_ratios = [3,1])
ax = plt.subplot(gs[0])
ax1 = plt.subplot(gs[1])
ax1.yaxis.set_ticklabels([])   # remove the major ticks

ax.scatter(x1, y1, marker='+',color = 'k')#, c=SNR, cmap=plt.cm.Greys)
ax.scatter(x2, y2, marker='o',color = 'k')#, c=SNR, cmap=plt.cm.Greys)
n1, bins1, patches1 = ax1.hist(y1, bins = 20, histtype = 'step', color = 'k',linewidth = 2, orientation = 'horizontal')
n2, bins2, patched2 = ax1.hist(y2, bins = 20, histtype = 'step', linestyle = 'dashed', color = 'k', orientation = 'horizontal')

【问题讨论】:

  • 在我看来normed 是要走的路。
  • 不幸的是,normed 标准化了曲线下的面积,而不是高度。
  • 是的,但这通常是比较直方图的正确方法。您是否正在寻找不同的统计数据?
  • 我同意。但这是两种不同的分布,我想比较数据的分布,这在我缩放到高度时最为明显,因为一个的最大 bin 值为 150,另一个的最大 bin 值为 30。

标签: python numpy matplotlib histogram


【解决方案1】:

我不知道 matplotlib 默认是否允许这种标准化,但我自己写了一个函数来做。

它从 plt.hist 中获取n 和bins 的输出(如上),然后将其传递给下面的函数。

def hist_norm_height(n,bins,const):
    ''' Function to normalise bin height by a constant. 
        Needs n and bins from np.histogram or ax.hist.'''

    n = np.repeat(n,2)
    n = float32(n) / const
    new_bins = [bins[0]]
    new_bins.extend(np.repeat(bins[1:],2))
    return n,new_bins[:-1]

现在要绘制(我喜欢步进直方图),你将它传递给 plt.step。

如plt.step(new_bins,n)。这将为您提供一个高度由常数标准化的直方图。

【讨论】:

  • 难道不能从n中提取const吗?
【解决方案2】:

您可以将参数bins 分配为等于值列表。使用np.arange() 或np.linspace() 生成值。 http://matplotlib.org/api/axes_api.html?highlight=hist#matplotlib.axes.Axes.hist

【讨论】:

    【解决方案3】:

    用于比较的方法略有不同。可以适应步进样式:

    # -*- coding: utf-8 -*-
    import matplotlib.pyplot as plt
    import numpy as np
    
    y = []
    y.append(np.random.normal(2, 2, size=40))
    y.append(np.random.normal(3, 1.5, size=40))
    y.append(np.random.normal(4,4,size=40))
    ls = ['dashed','dotted','solid']
    
    fig, (ax1, ax2, ax3) = plt.subplots(ncols=3)
    for l, data in zip(ls, y):
        n, b, p = ax1.hist(data, normed=False,
                           #histtype='step', #step's too much of a pain to get the bins
                           #color='k', linestyle=l,
                           alpha=0.2
                           )
        ax2.hist(data, normed=True,
                 #histtype = 'step', color='k', linestyle=l,
                 alpha=0.2
                 )
    
        n, b, p = ax3.hist(data, normed=False,
                           #histtype='step', #step's too much of a pain to get the bins
                           #color='k', linestyle=l,
                           alpha=0.2
                           )
        high = float(max([r.get_height() for r in p]))
        for r in p:
            r.set_height(r.get_height()/high)
            ax3.add_patch(r)
        ax3.set_ylim(0,1)
    
    ax1.set_title('hist')
    ax2.set_title('area==1')
    ax3.set_title('fix height')
    plt.show()
    

    几个输出:

    【讨论】:

    • 我仍然认为规范版本更容易比较高大和宽分布...
    【解决方案4】:

    这可以使用numpy 来获得先验直方图值,然后使用bar plot 绘制它们。

    import numpy as np
    import matplotlib.pyplot as plt
    
    # Define random data and number of bins to use
    x = np.random.randn(1000)
    bins = 10
    
    plt.figure()
    # Obtain the bin values and edges using numpy
    hist, bin_edges = np.histogram(x, bins=bins, density=True)
    # Plot bars with the proper positioning, height, and width.
    plt.bar(
        (bin_edges[1:] + bin_edges[:-1]) * .5, hist / hist.max(),
        width=(bin_edges[1] - bin_edges[0]), color="blue")
    
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-22
      • 2013-04-03
      • 2016-10-14
      • 1970-01-01
      • 2018-09-22
      • 2016-04-26
      • 2016-12-30
      • 1970-01-01
      相关资源
      最近更新 更多