【问题标题】:Matplotlib - label each binMatplotlib - 标记每个 bin
【发布时间】:2011-09-15 05:09:42
【问题描述】:

我目前正在使用 Matplotlib 创建直方图:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as pyplot
...
fig = pyplot.figure()
ax = fig.add_subplot(1,1,1,)
n, bins, patches = ax.hist(measurements, bins=50, range=(graph_minimum, graph_maximum), histtype='bar')

#ax.set_xticklabels([n], rotation='vertical')

for patch in patches:
    patch.set_facecolor('r')

pyplot.title('Spam and Ham')
pyplot.xlabel('Time (in seconds)')
pyplot.ylabel('Bits of Ham')
pyplot.savefig(output_filename)

我想让 x 轴标签更有意义。

首先,这里的 x 轴刻度似乎被限制为五个刻度。无论我做什么,我似乎都无法改变这一点——即使我添加更多 xticklabels,它也只使用前五个。我不确定 Matplotlib 是如何计算的,但我认为它是根据范围/数据自动计算的?

有什么方法可以提高 x-tick 标签的分辨率 - 甚至可以提高每个条形图/bin 的分辨率?

(理想情况下,我还希望以微秒/毫秒为单位重新格式化秒,但这是另一天的问题)。

其次,我想标记每个单独的条 - 带有该箱中的实际数量,以及所有箱总数的百分比。

最终输出可能如下所示:

使用 Matplotlib 可以实现类似的功能吗?

干杯, 维克多

【问题讨论】:

    标签: python matplotlib visualization histogram graphing


    【解决方案1】:

    当然!要设置刻度,只需...设置刻度(请参阅matplotlib.pyplot.xticksax.set_xticks)。 (另外,您不需要手动设置补丁的 facecolor。您只需传入关键字参数即可。)

    对于其余部分,您需要对标签做一些更花哨的事情,但 matplotlib 让它变得相当容易。

    举个例子:

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.ticker import FormatStrFormatter
    
    data = np.random.randn(82)
    fig, ax = plt.subplots()
    counts, bins, patches = ax.hist(data, facecolor='yellow', edgecolor='gray')
    
    # Set the ticks to be at the edges of the bins.
    ax.set_xticks(bins)
    # Set the xaxis's tick labels to be formatted with 1 decimal place...
    ax.xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))
    
    # Change the colors of bars at the edges...
    twentyfifth, seventyfifth = np.percentile(data, [25, 75])
    for patch, rightside, leftside in zip(patches, bins[1:], bins[:-1]):
        if rightside < twentyfifth:
            patch.set_facecolor('green')
        elif leftside > seventyfifth:
            patch.set_facecolor('red')
    
    # Label the raw counts and the percentages below the x-axis...
    bin_centers = 0.5 * np.diff(bins) + bins[:-1]
    for count, x in zip(counts, bin_centers):
        # Label the raw counts
        ax.annotate(str(count), xy=(x, 0), xycoords=('data', 'axes fraction'),
            xytext=(0, -18), textcoords='offset points', va='top', ha='center')
    
        # Label the percentages
        percent = '%0.0f%%' % (100 * float(count) / counts.sum())
        ax.annotate(percent, xy=(x, 0), xycoords=('data', 'axes fraction'),
            xytext=(0, -32), textcoords='offset points', va='top', ha='center')
    
    
    # Give ourselves some more room at the bottom of the plot
    plt.subplots_adjust(bottom=0.15)
    plt.show()
    

    【讨论】:

    • 啊哈,太棒了=)。另一个注意事项 - 最初,我使用“fig = pyplot.figure(figsize=(32,24),)”和“ax = fig.add_subplot(1,1,1,)”来设置图形的大小。但是,如果我将第二个留置权换成你的“fig, ax = pyplot.subplots()”,它现在似乎忽略了我的 figsize?知道为什么吗?
    • @victorhooi - 如果您只是将 figsize 指定为 subplots 的 kwarg,它应该可以工作。例如。 fig, ax = plt.subplots(figsize=(32, 34)) 如果不是,那可能是一个错误? subplots 仅作为便利功能添加到 1.0 中。
    • Kingston:啊哈,太好了,是的,那条线有效 =)。你太棒了,伙计。我不明白最后一个错误/小问题 - 注释文本正下方的 xlabel 文本 - 不知道如何抵消它。我尝试了“ax.xaxis.LABELPAD=30”,但它似乎忽略了这一点。
    • @victorhooi - 有几种不同的方法可以设置刻度填充,但最简单的是ax.tick_params(axis='x', pad=30)(这有点违反直觉。)希望对您有所帮助!
    • @Joe Kingston:嗯,试过了,但它同时移动了 x 轴标签和刻度线。干这个。哈哈。无论如何,我认为这值得另一个问题,所以我在这里转发了它:stackoverflow.com/questions/6406368/…
    【解决方案2】:

    要将 SI 前缀添加到您要使用的轴标签,请使用 QuantiPhy。事实上,在其文档中,它有一个示例说明了如何执行此操作:MatPlotLib Example

    我想你会在你的代码中添加这样的东西:

    from matplotlib.ticker import FuncFormatter
    from quantiphy import Quantity
    
    time_fmtr = FuncFormatter(lambda v, p: Quantity(v, 's').render(prec=2))
    ax.xaxis.set_major_formatter(time_fmtr)
    

    【讨论】:

      【解决方案3】:

      我想用“密度 = True”添加到直方图中的图中的一件事是每个箱的相对频率值,搜索但我找不到可以做到这一点的函数。我提出的解决方案如下图所示:

      功能:

      def label_densityHist(ax, n, bins, x=4, y=0.01, r=2, **kwargs):
      """
      Add labels,relative value of bin, to each bin in a density histogram .
      :param ax: Object axe of matplotlib
              The axis to plot.
      :param n: list, array of int, float
              The values of the histogram bins.
      :param bins: list, array of int, float
              The edges of the bins.
      :param x: int, float
              Related the x position of the bin labels. The higher, the lower the value on the x-axis.
              Default: 4
      :param y: int, float
              Related the y position of the bin labels. The higher, the greater the value on the y-axis.
              Default: 0.01
      :param r: int
              Number of decimal places.
              Default: 2
      :param **kwargs: Text properties in matplotlib
      :return: None
      
      
      Example
      
      import matplotlib.pyplot as plt
      import numpy as np
      
      dados = np.random.randn(100)
      
      axe = plt.gca()
      n, bins, _ = axe.hist(x=dados, edgecolor='black')
      label_densityHist(axe,n, bins)
      plt.show()
      
      Example:
      import matplotlib.pyplot as plt
      import numpy as np
      
      
      dados = np.random.randn(100)
      
      axe = plt.gca()
      n, bins, _ = axe.hist(x=dados, edgecolor='black')
      label_densityHist(axe,n, bins, x=6, fontsize='large')
      plt.show()
      
      
      Reference:
      [1]https://matplotlib.org/3.1.1/api/text_api.html#matplotlib.text.Text
      
      """
      
      k = []
      # calculate the relative frequency of each bin
      for i in range(0,len(n)):
          k.append((bins[i+1]-bins[i])*n[i])
      
      # rounded
      k = around(k,r); #print(k)
      
      # plot the label/text to each bin
      for i in range(0, len(n)):
          x_pos = (bins[i + 1] - bins[i]) / x + bins[i]
          y_pos = n[i] + (n[i] * y)
          label = str(k[i]) # relative frequency of each bin
          ax.text(x_pos, y_pos, label, kwargs)
      

      【讨论】:

        猜你喜欢
        • 2021-07-22
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 2012-10-16
        • 2013-04-03
        • 2020-06-12
        • 2019-11-03
        相关资源
        最近更新 更多