【问题标题】:Custom Histogram Normalization in matplotlibmatplotlib 中的自定义直方图归一化
【发布时间】:2021-05-14 22:37:23
【问题描述】:

我正在尝试在 matplotlib 中制作一个标准化直方图,但是我希望它标准化以便总面积为 1000。有没有办法做到这一点?

我知道要将其标准化为 1,您只需在 plt.hist() 的参数中包含 density=True,stacked=True。一个等效的解决方案是执行此操作并将每列的高度乘以 1000,如果这比更改直方图的归一化更可行的话。

非常感谢您!

【问题讨论】:

    标签: python matplotlib histogram


    【解决方案1】:

    以下方法使用np.histogram 计算每个直方图箱的计数。使用 1000 / total_count / bin_width 作为归一化因子,总面积将为 1000。相反,要使所有条形高度的总和为 1000,则需要因子 1000 / total_countplt.bar 用于显示最终结果。

    示例代码使用 density=True, 计算相同的组合直方图,以将其与总和为 1000 的新直方图进行比较。

    import matplotlib.pyplot as plt
    import numpy as np
    
    data = [np.random.randn(100) * 5 + 10, np.random.randn(300) * 4 + 14, np.random.randn(100) * 3 + 17]
    fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12, 4))
    
    ax1.hist(data, stacked=True, density=True)
    ax1.set_title('Histogram with density=True')
    
    xmin = min([min(d) for d in data])
    xmax = max([max(d) for d in data])
    bins = np.linspace(xmin, xmax, 11)
    bin_width = bins[1] - bins[0]
    
    counts = [np.histogram(d, bins=bins)[0] for d in data]
    total_count = sum([sum(c) for c in counts])
    # factor = 1000 / total_count # to sum to 1000
    factor = 1000 / total_count / bin_width # for an area of 1000
    thousands = [c * factor for c in counts]
    
    bottom = 0
    for t in thousands:
        ax2.bar(bins[:-1], t, bottom=bottom, width=bin_width, align='edge')
        bottom += t
    ax2.set_title('Histogram with total area of 1000')
    
    plt.show()
    

    【讨论】:

      【解决方案2】:

      一个简单的方法是设置第二个 y 轴,其刻度标签是原来的乘以 1000,然后隐藏原始轴的刻度:

      import matplotlib.pyplot as plt
      import numpy as np
      
      data = [np.random.randn(5000)]
      fig, ax1 = plt.subplots()
      ax2 = ax1.twinx()
      
      #hist returns a tuple that contains a list of y values at its 0 index:
      y,_,_ = ax1.hist(data, density=True, bins=10, edgecolor = 'black')
      
      #find max y value of histogram and multiply by 1000:
      max_y = np.round(y.max(),1)*1000
      
      #set up the second y-axis ticks as increments of max_y:
      ax2.set_ylim(0,max_y)
      ax2.set_yticks(np.linspace(0, max_y, 9))
      
      #hide original y-axis ticks:
      ax1.axes.yaxis.set_ticks([])
      plt.show()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-20
        • 2017-05-04
        • 1970-01-01
        • 1970-01-01
        • 2015-01-15
        • 1970-01-01
        • 2018-06-24
        • 1970-01-01
        相关资源
        最近更新 更多