如何在Matplotlib子图的条形图上显示对应Y值?
给Matplotlib子图条形图添加数值标签的解决方案
问题场景
通过以下Python代码创建了5个Matplotlib子图的条形图,但无法在每个条形上正确标注对应的Y值:
values = {"x_values" : ["ENN", "CNN", "ENN-CNN"], "eu" : [11, 79.97, 91], "man" : [11, 80, 90], "min3" : [11, 79.70, 90], "min4" : [11, 79.50, 90], "che" : [12, 78, 89]} df = pd.DataFrame(data=values) fig, axs = plt.subplots(2, 3, figsize=(10,6)) eu = axs[0, 0].bar(df["x_values"], df["eu"]) man = axs[0, 1].bar(df["x_values"], df["man"]) min3 = axs[0, 2].bar(df["x_values"], df["min3"]) min4 = axs[1, 0].bar(df["x_values"], df["min4"]) che = axs[1, 1].bar(df["x_values"], df["che"]) fig.delaxes(axs[1, 2])
尝试plt.text、fig.text无效果,调用BarContainer的text方法报错,使用axs[子图索引].text时数值显示在图外。
解决方案
核心思路是遍历每个子图的BarContainer中的条形对象,在每个条形的顶部位置添加文本标签,同时调整文本位置和轴范围避免标签超出图外。
修改后的完整代码
import pandas as pd import matplotlib.pyplot as plt values = {"x_values" : ["ENN", "CNN", "ENN-CNN"], "eu" : [11, 79.97, 91], "man" : [11, 80, 90], "min3" : [11, 79.70, 90], "min4" : [11, 79.50, 90], "che" : [12, 78, 89]} df = pd.DataFrame(data=values) fig, axs = plt.subplots(2, 3, figsize=(10,6)) # 批量管理子图、对应数据和标题 bar_plots = [ (axs[0, 0], df["eu"], "Euclidean"), (axs[0, 1], df["man"], "Manhattan"), (axs[0, 2], df["min3"], "Min3"), (axs[1, 0], df["min4"], "Min4"), (axs[1, 1], df["che"], "Chebyshev") ] for ax, data, title in bar_plots: bars = ax.bar(df["x_values"], data) ax.set_title(title) # 给每个条形添加数值标签 for bar in bars: height = bar.get_height() # 计算文本位置:条形顶部居中,y轴偏移1个单位避免贴紧条形 ax.text( bar.get_x() + bar.get_width() / 2, # 水平居中位置 height + 1, # 垂直位置(条形顶部+偏移) f"{height:.2f}", # 格式化显示数值 ha="center", va="bottom" # 对齐方式 ) # 调整y轴上限,确保标签不会超出图外 ax.set_ylim(0, max(data) + 5) fig.delaxes(axs[1, 2]) plt.tight_layout() # 自动调整子图间距 plt.show()
关键要点
- 遍历条形对象:
ax.bar()返回的BarContainer包含所有条形的patches,遍历这些对象可以获取每个条形的位置和高度信息。 - 精准定位文本:通过
bar.get_x()和bar.get_width()计算条形的水平中心,height + 1设置文本与条形的垂直间距,确保标签位置合理。 - 调整轴范围:使用
ax.set_ylim()扩大y轴的上限,避免数值标签超出子图可视区域。 - 批量处理优化:将子图、数据和标题整理为列表批量处理,减少重复代码,提升可维护性。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

