【matplotlib】可视化解决方案——柱状图标注问题

柱状图标注问题

前言

很多时候我们画柱状图都是光秃秃的几个柱体,缺少相应的标注会让我们的可视化效果变差许多,例如下图所示,所以为了更好的可视化效果,我们需要对柱状图进行标注。
错误的无标注柱状图:
在这里插入图片描述

解决方案一

如果你的matplotlib库版本为3.4.1,那么pyplot库会自带一个方法bar_label,它的函数原型如下:

bar_label(container,labels = None,fmt = ‘%g’,label_type = ‘edge’,padding = 0,**kwargs)

参数说明:

参数1:container:指定包含所有柱状图和错误条形图的容器,基本从bar函数或者barh函数返回的BarContainer的patches属性得来。
参数2:labels:指定应显示的标签文本列表。如果未给出,则标签文本将是使用fmt格式化的数据值
参数3:fmt:字符型,指定标签的格式字符串
参数4:label_type:限定字符串,指定标签的类型,可选:

  • edge:标签放置在柱体的端点,显示的值将是该端点的位置
  • center:标签位于柱体的中心,显示的值将是该段的长度

参数5:padding:浮点型,指定标签到柱状图末端的距离
参数6:** kwargs:接收到的关键字参数都会传递给Axes.annotate

返回值:包含Text实例的列表


参数详解:

1.fmt参数格式跟其他字符串显示格式是一致的。
2.container参数不一定是bar函数的返回值,他可以是所有Patch类的子类实例


3.4.1版本标注程序如下:

#添加标签等函数
def label(ax):
    ax.set_xlabel('X', fontsize=15)
    ax.set_ylabel('Y', fontsize=15)
    ax.legend(loc='best')

figure = plt.figure(figsize=(8, 6))
ax1 = figure.add_subplot(2, 1, 1)
ax2 = figure.add_subplot(2, 1, 2)

#初始化数据
x = np.random.randint(0, 10, 10)

#画图1label_type='center'
Rectangle1 = ax1.bar(range(10), x, width=0.8, label='有标注,label_type=center')
ax1.bar_label(Rectangle1, label_type='center')    #进行标注
label(ax1)
ax1.set_title('bar画图', fontsize=25)

#画图2label_type='edge'
Rectangle2 = ax2.bar(range(10), x, width=0.8, label='有标注,label_type=edge')
ax2.bar_label(Rectangle2, label_type='edge')    #进行标注
label(ax2)

plt.show()

画图结果如下:
在这里插入图片描述
从上图我们可以看出对于单一的柱状图,label_type参数没有多大实质影响,知识简单的改变了标注的位置。label_type参数真正的影响在于叠加柱状图时对两种不同的柱状图进行标注。一个简单的示例如下:

#初始化数据
N = 5
Y1 = np.random.randint(0, 20, N)
Y2 = np.random.randint(0, 20, N)

fig, ax = plt.subplots()

#绘制叠加柱状图
p1 = ax.bar(range(N), Y1, width=0.6, label='Y1')
p2 = ax.bar(range(N), Y2, width=0.6, bottom=Y1, label='Y2')

#设置标签等
ax.set_ylabel('Y', fontsize=15)
ax.set_xlabel('X', fontsize=15)
ax.set_title('叠加柱状图', fontsize=25)
ax.legend()	#打开图例
	
#使用bar_label方法对柱状图进行标注,默认是在顶端进行标注
ax.bar_label(p1, label_type='center', fontsize=13)	#label_type='center'
ax.bar_label(p2, label_type='center', fontsize=13)	#label_type='center'
ax.bar_label(p2, fontsize=13)	#label_type='edge'

plt.show()

画图结果如下:
在这里插入图片描述
从上图可以看到柱体中心的数字代表该柱体的高度,柱体顶端的数字代表两个柱体加在一起的高度,即定点的高度。这样我们就完成了两个叠加柱状图的标注。

!!!!bar_label方法不光可以标注柱状图还可以标注直方图等返回值具有patches属性的图


解决方案二

如果matplotlib库版本较低,pyplot并不支持bar_label方法,那么只能使用自定义的添加函数进行柱状图标注了,使用annotate方法进行标注。具体程序如下:

    def autolabel(rects):
        """
        自动标定柱状图柱体高度
        rects:要进行标定的Rectangle类列表
        """
        for rect in rects:
            height = rect.get_height()
            self.fig1.axes.annotate(format(height, '.2f'),
                                    xy=(rect.get_x() +
                                        rect.get_width() / 2, height),
                                    xytext=(0, 2),  # 垂直偏移两格
                                    textcoords="offset points",
                                    ha='center',
                                    va='bottom')
            self.fig1.draw()

单柱状图画图结果如下:
在这里插入图片描述
叠加柱状图画图结果如下:
在这里插入图片描述
由上两图可知,单一的柱状图标注使用该函数没有什么问题,但是叠加柱状图就出现了很大的问题,其原因在于height = rect.get_height()这句话,标注位置的高度使用的是柱体的高度而不是柱体顶点的值,那么对于叠加柱状图中的bottom参数则无法很好的响应,故而对叠加柱状图进行标注的效果很糟糕。


总结

如果能更新matplotlib库,那么最好更新到3.4.1使用库自带方法进行标注,比自建函数要好上不少。但是旧版本可以通过添加参数或修改函数逻辑的方法增加其适用范围,作为备选方法是可行的。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猪猪家的大猪猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值