【问题标题】:matplotlib to combine lower binsmatplotlib 组合较低的垃圾箱
【发布时间】:2016-08-29 08:58:29
【问题描述】:

我是 matplotlib 的新手,正在尝试绘制直方图。我对较低的 bin 范围感兴趣,因此拆分了我的 bin 范围,但它看起来有点难看,右侧有很多空白。 我有一些代码可以生成这个直方图,但我想改变它:

  • 将 xaxis 位置 150 之后的所有条组合为 150+,以便更好地显示较低范围的条。
  • 改变条的颜色
  • 最左边的栏换成不同的颜色
  • 代表 x 轴刻度在 5-40 之间的条具有不同的颜色
  • 来自 40 多种不同颜色的条形

    import matplotlib
    matplotlib.use('PS')
    import matplotlib.pyplot as plt
    # sample data, These are not actual values since I have a large csv file  
    # with 1000's of rows.
    values=[1,1,1,1,1,1,1,2,2,2,2,4,4,4,5,6,7,8,9,10,111,12,23,30,30,35,353,35,25,25,25,15,15,15,20,20,20,40,40,40,45,50,55,50,50,100,200,300,400]
    
    limit1, limit2 = 50, 500
    binwidth1, binwidth2 = 5, 100
    binr=list(range(0, limit1, binwidth1)) + list(range(100, limit2, binwidth2))
    n, bins, patches=plt.hist(values, bins = binr)
    one, fifty = np.percentile(values, [0.5,50])
    for patch, rightside, leftside in zip(patches, bins[1:], bins[:-1]):
        if rightside < one:
            patch.set_facecolor('green')
        elif leftside > fifty:
            patch.set_facecolor('red')
    plt.title("Frequency Histogram")
    plt.xlabel("Word Count")
    plt.ylabel("Frequency")
    plt.savefig(plot_file)
    plt.close()
    

【问题讨论】:

  • 感谢(点赞)制作了一个小例子。

标签: python numpy matplotlib histogram


【解决方案1】:

我并不完全清楚您要做什么,尤其是您的期望似乎与您的简单示例有些矛盾(我的意思是基于百分位的着色)。

无论如何,我建议你直接使用np.histogram(因为你已经导入了numpy),然后手动调用plt.bar。这样做的主要优点(除了更好地控制输出,代价是稍微增加一些工作量)是您可以传递一个包含每个条形颜色的列表。

您的示例的修改版本:

values=[1,1,1,1,1,1,1,2,2,2,2,4,4,4,5,6,7,8,9,10,111,12,23,30,30,35,353,35,25,25,25,15,15,15,20,20,20,40,40,40,45,50,55,50,50,100,200,300,400]

limit1, limit2 = 50, 500
binwidth1, binwidth2 = 5, 100
binr=list(range(0, limit1, binwidth1)) + list(range(100, limit2, binwidth2))

# improvement 1: merge bins above 150, keep the same maximum
thresh = 150
# keep the first value after the threshold too
binr_tmp = [val for val in binr if val<=thresh] 
binr = binr_tmp + [binr[len(binr_tmp)], binr[-1]]

# improvement 2: use np.histogram explicitly, feed into plt.bar later (for colors)
bin_vals, bins = np.histogram(values, bins=binr)
bins_left = binr[:-1]
bins_width = np.diff(bins)
bins_right = bins_left + bins_width
one, fifty = np.percentile(values, [0.5,50])

# "change the color of bars": you did the same thing earlier
# improvement: use a numpy.array for a colour list, set for each bar separately
# (possibility for array indexing)
# just don't forget to turn into a list() when calling plt.bar
bins_color = np.array(['blue']*len(bins_left), dtype=object)
bins_color[bins_left>fifty] = 'red'
bins_color[bins_left+bins_width<one] = 'green'

# "leftmost bar to a different color":
bins_color[0] = 'magenta'

# "bars from 40+ different color": would conflict with percentile-based original version
thresh2 = 40
#bins_color[bins_right>thresh2] = 'olive'

hbars = plt.bar(left=bins_left, height=bin_vals, width=bins_width, color=list(bins_color))
plt.title("Frequency Histogram")
plt.xlabel("Word Count")
plt.ylabel("Frequency")
#plt.savefig(plot_file)
#plt.close()
plt.show()

我试图留下信息丰富的 cmets。主要需要注意的是np.histogram 生成bin 值,这些值被输入plt.bar。与plt.hist 相比,后者的输入要复杂一些(尤其是每个栏的左侧和右侧必须手动指定),但这也允许更大的自定义。

正如您在“改进 1”中看到的那样,我将您的垃圾箱合并到 thresh 值以上,而其他垃圾箱保持不变。我知道您要求这样做是为了为您的x&lt;50 区域留出更多空间。您可以通过手动移动binr 的最后一个值来执行此操作,将最后一个(合并的)条拉得更紧。如果你这样做,你应该在 x 轴上使用plt.xlabel 来表示。

我不这样做的原因是这样的操作会严重扭曲您的数据,从而导致很多偏见。您通常应该避免这样做。如果您打算在视觉上扭曲条形并且您对此没问题,只需按照我在上一段中写的操作即可。

我将上述结果包括在内,当然与原始结果相比差异并不大。但是,我相信您想要进行的大多数操作都会随着 bins_color array 的引入而变得容易得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 2019-03-15
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多