Matplotlib图例文本与符号垂直对齐偏移问题排查与修复
问题:图例中趋势线符号垂直偏移异常的修复方法
绘制数据并添加线性趋势线时,希望图例包含趋势函数,但图例里的符号相对文本出现了异常垂直偏移(截图中浅蓝色标记处),求原因及修复方法。
原代码
l_y1_1 = ax.plot(x, y1, 'ro', label='Lithium', markersize=10) l_y1_2 = ax.plot(x_extrapolate, y1_extrapolate,'r:', label = "%s" % poly1) l_y2_1 = ax.plot(x, y2, 'bx', label='Chlor', markersize=10) l_y2_2 = ax.plot(x_extrapolate, y2_extrapolate,'b:', label = "%s" % poly2) ax2 = ax.twinx() l_y3_1 = ax2.plot(x, y3, 'gD', label='Fluor', markersize=10) l_y3_2 = ax2.plot(x_extrapolate, y3_extrapolate,'g:',label = "%s" % poly3) l_y_tot = l_y1_1 + l_y1_2 + l_y2_1 + l_y2_2 + l_y3_1 + l_y3_2 y_labs = [l.get_label() for l in l_y_tot] legend = ax.legend(l_y_tot, y_labs, loc = 'upper left')
问题现象
截图显示图例中趋势线的短横线符号相对于右侧的函数文本,出现明显向上偏移,与数据点符号的对齐方式不一致。
原因分析
- 跨轴元素混合:主坐标轴(
ax)和双坐标轴(ax2)的绘图对象被同时放到主轴的图例中,两个轴的坐标系统差异导致副轴元素渲染时出现对齐错位。 plot返回值处理:plot函数返回的是Line2D对象列表,直接拼接列表虽能收集元素,但跨轴场景下会加剧图例渲染的错位问题。
修复方法
方法一:手动调整图例元素对齐
先提取plot返回的单个Line2D对象,创建图例后统一设置所有符号的垂直位置:
# 提取plot返回的单个Line2D对象 l_y1_1 = ax.plot(x, y1, 'ro', label='Lithium', markersize=10)[0] l_y1_2 = ax.plot(x_extrapolate, y1_extrapolate,'r:', label = "%s" % poly1)[0] l_y2_1 = ax.plot(x, y2, 'bx', label='Chlor', markersize=10)[0] l_y2_2 = ax.plot(x_extrapolate, y2_extrapolate,'b:', label = "%s" % poly2)[0] ax2 = ax.twinx() l_y3_1 = ax2.plot(x, y3, 'gD', label='Fluor', markersize=10)[0] l_y3_2 = ax2.plot(x_extrapolate, y3_extrapolate,'g:',label = "%s" % poly3)[0] # 收集图例元素与标签 handles = [l_y1_1, l_y1_2, l_y2_1, l_y2_2, l_y3_1, l_y3_2] labels = [h.get_label() for h in handles] # 创建图例并手动对齐所有符号 legend = ax.legend(handles, labels, loc='upper left') for handle in legend.legendHandles: handle.set_ydata([0.5]) # 将所有符号对齐到文本中线位置
方法二:创建全局图例(推荐)
使用plt.legend创建全局图例,自动处理跨轴元素的对齐问题:
import matplotlib.pyplot as plt # 提取单个Line2D对象 l_y1_1 = ax.plot(x, y1, 'ro', label='Lithium', markersize=10)[0] l_y1_2 = ax.plot(x_extrapolate, y1_extrapolate,'r:', label = "%s" % poly1)[0] l_y2_1 = ax.plot(x, y2, 'bx', label='Chlor', markersize=10)[0] l_y2_2 = ax.plot(x_extrapolate, y2_extrapolate,'b:', label = "%s" % poly2)[0] ax2 = ax.twinx() l_y3_1 = ax2.plot(x, y3, 'gD', label='Fluor', markersize=10)[0] l_y3_2 = ax2.plot(x_extrapolate, y3_extrapolate,'g:',label = "%s" % poly3)[0] # 创建全局图例,自动整合所有轴的元素 plt.legend(handles=[l_y1_1, l_y1_2, l_y2_1, l_y2_2, l_y3_1, l_y3_2], loc='upper left')
额外小技巧
若使用Matplotlib 3.3及以上版本,可尝试设置图例的handlealignment参数快速修复:
legend = ax.legend(handles, labels, loc='upper left', handlealignment='center')
内容的提问来源于stack exchange,提问作者user12726582
相关产品推荐
相关产品推荐

