Matplotlib柱状图:按柱宽1/5偏移调整柱顶文本位置失效问题
Matplotlib柱状图数值文本偏移失效问题解决
我想在Matplotlib绘制的柱状图中,把每个柱形的数值文本放在柱顶下方,偏移量设为柱宽(barwidth)的1/5,但代码里的text_y -= bar.get_width()/5完全没生效。以下是完整代码和当前效果:
#!/usr/bin/env python3 import numpy as np import matplotlib import matplotlib.pyplot as plt import pandas as pd import matplotlib.patheffects as PathEffects import math import numpy as np def save_fig(fig,pngname): fig.savefig(pngname, dpi=fig.dpi, bbox_inches="tight") print("[[%s]]"%pngname) return def plot_bar(df): xname = df.columns[0] fig, ax = plt.subplots(figsize=(10, 5)) x = np.arange(len(df[xname])) n = len(df.columns[1:]) bar_width = 0.95/n fontsize = 20 colors = ['#5891ad','#004561','#ff6f31','#1c7685','#0f45a8','#4cdc8b','#0097a7'] dy = -bar_width/10 bars = [] # add bars for i,colname in enumerate(df.columns[1:]): bar = ax.bar(x+i*bar_width, df[colname], width=bar_width,color=colors[i]) bars.append(bar) # add text on bars for bar in ax.patches: bar_value = bar.get_height() text = f'{bar_value:,}' text_x = bar.get_x() + bar.get_width() / 2 text_y = bar.get_y() + bar_value text_y -= bar.get_width()/5 # <- 这里未生效 bar_color = bar.get_facecolor() t = ax.text(text_x, text_y, text, ha='center', va='top', color=bar_color, size=fontsize) t.set_path_effects([PathEffects.withStroke(linewidth=bar_width*15, foreground='w')]) ax.set_xticks(x + 1/ 2 - bar_width/2) ax.set_xticklabels(df[xname]) ax.legend() ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) #ax.spines['left'].set_visible(False) #ax.spines['bottom'].set_color('#DDDDDD') ax.tick_params(bottom=False, left=False) ax.set_axisbelow(True) ax.yaxis.grid(True, color='#EEEEEE') ax.xaxis.grid(False) ax.set_xlabel('x', labelpad=15) ax.set_ylabel('y', labelpad=15) ax.set_title('title', pad=15) fig.tight_layout() plt.show() return data = [['a',3,2,1], ['b',2,3,1], ['c',3,1,3], ['d',5,1,3], ] df = pd.DataFrame(data,columns=['f1','f2','f3','f4']) plot_bar(df)

问题原因
bar.get_width()获取的是x轴方向的刻度单位宽度,但text_y是y轴的坐标值,x轴和y轴的尺度差异极大(比如你图里x轴范围0-3,y轴范围0-5),用x轴的数值去调整y轴坐标,偏移量小到肉眼根本察觉不到,所以看起来像没生效。
解决方法
方法1:用y轴相对比例设置偏移(最稳妥)
把失效的那行代码替换成:
# 取y轴总范围的1%作为向下偏移量,可根据需求调整比例 y_range = ax.get_ylim()[1] - ax.get_ylim()[0] text_y -= y_range * 0.01
方法2:固定像素偏移(直观可控)
如果想要固定像素的偏移,用坐标转换实现:
# 向下偏移8个像素,数值可按需调整 pixel_offset = -8 # 把数据坐标转成屏幕显示坐标,调整后再转回去 display_pos = ax.transData.transform((text_x, text_y)) new_display_pos = (display_pos[0], display_pos[1] + pixel_offset) text_x, text_y = ax.transData.inverted().transform(new_display_pos)
方法3:把x轴宽度转成y轴等效偏移(坚持原需求逻辑)
如果一定要用柱宽的1/5作为偏移,计算x和y轴的显示尺度比例,转换后再调整:
# 计算x、y轴每个刻度单位对应的像素数 x_pixel_per_unit = ax.transData.transform((1, 0))[0] - ax.transData.transform((0, 0))[0] y_pixel_per_unit = ax.transData.transform((0, 1))[1] - ax.transData.transform((0, 0))[1] # 把x轴的宽度值转换成y轴的等效偏移量 scale_ratio = y_pixel_per_unit / x_pixel_per_unit text_y -= (bar.get_width() / 5) * scale_ratio
内容的提问来源于stack exchange,提问作者lucky1928
相关产品推荐
相关产品推荐

