You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何居中Matplotlib误差棒图例的第二行标记?

解决Matplotlib误差棒图例第二行标记居中问题

尝试将Matplotlib图例第二行的标记居中显示,参考过相关方案但不适用于误差棒代码,推测是误差棒的图例handle结构或坐标轴生成方式导致。以下是问题分析及解决方案:

原示例代码

#EXAMPLE OF MY DATA

x = [0, 2, 5, 10, 15]
y1 = [1, 2, 4, 5, 2]
dev1 = [0.2, 0.3, 0.4, 0.6, 0.4]
y2 =[1, 2, 3, 4, 5]
dev2 = [0.01, 0.2, 0.3, 0.4, 0.5]
y3 =[2, 4, 0, 1, 5]
dev3 = [0.1, 0.2, 0.2, 0.4, 0.5]
y4 =[2, 2, 1, 1, 1]
dev4 = [0.1, 0.1, 0.1, 0, 0]
y5 =[2, 2, 1, 2, 2]
dev5 = [0, 0, 0.1, 0, 0]

#####

fig, ax = plt.subplots()
ax.errorbar(x, y1, yerr=dev1, marker="^", markersize=4, linestyle=" ", capsize=4, capthick=2, color="darkorange", label='line1')
ax.errorbar(x, y2, yerr=dev2, marker="s", markersize=4, linestyle=" ", capsize=4, capthick=2, color="green", label='line2')
ax.errorbar(x, y3, yerr=dev3, marker="v", markersize=4, linestyle=" ", capsize=4, capthick=2, color="blue", label='line3')
ax.errorbar(x, y4, yerr=dev4, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="brown", label='line4')
ax.errorbar(x, y5, yerr=dev5, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="yellow", label='line5')

handles1, labels1 = ax.get_legend_handles_labels()
handles1 = [h[0] for h in handles1]
nlines=6
ncols=3
handles1.insert(nlines//ncols, plt.plot([],[],color=(0,0,0,0))[0])
labels1.insert(nlines//ncols, " ") #--->I tried to insert this although it raises me an error (there are 6 handles and 5 labels)<----
ax.legend(handles=handles1, labels=labels1, ncol=ncols, framealpha=1)

问题分析

  1. 条目数量计算错误:原代码中nlines设为6,但实际只有5个图例条目,导致插入空条目的索引计算错误,引发handles与labels数量不匹配的报错。
  2. 空条目插入位置错误:要让第二行2个标记居中,需在第二行开头插入空条目占位,而非第一行末尾。
  3. 空handle类型不合适:用plt.plot生成空线条可能引入不必要的元素,更适合用透明Patch。

修正方案

  1. 动态计算需要插入的空条目数:根据总条目数和列数,计算第二行需要补充的空条目数量,确保有效标记居中。
  2. 正确插入空handle和label:在第二行起始位置插入透明Patch作为空handle,同时插入对应空label,保证数量一致。
  3. 保留误差棒handle的正确处理:ax.errorbar返回的是(Line2D, ErrorbarContainer),取h[0]获取线条对象用于图例是正确的。

修正后完整代码

import matplotlib.pyplot as plt
from matplotlib.patches import Patch

# 示例数据
x = [0, 2, 5, 10, 15]
y1 = [1, 2, 4, 5, 2]
dev1 = [0.2, 0.3, 0.4, 0.6, 0.4]
y2 =[1, 2, 3, 4, 5]
dev2 = [0.01, 0.2, 0.3, 0.4, 0.5]
y3 =[2, 4, 0, 1, 5]
dev3 = [0.1, 0.2, 0.2, 0.4, 0.5]
y4 =[2, 2, 1, 1, 1]
dev4 = [0.1, 0.1, 0.1, 0, 0]
y5 =[2, 2, 1, 2, 2]
dev5 = [0, 0, 0.1, 0, 0]

fig, ax = plt.subplots()
# 绘制误差棒
ax.errorbar(x, y1, yerr=dev1, marker="^", markersize=4, linestyle=" ", capsize=4, capthick=2, color="darkorange", label='line1')
ax.errorbar(x, y2, yerr=dev2, marker="s", markersize=4, linestyle=" ", capsize=4, capthick=2, color="green", label='line2')
ax.errorbar(x, y3, yerr=dev3, marker="v", markersize=4, linestyle=" ", capsize=4, capthick=2, color="blue", label='line3')
ax.errorbar(x, y4, yerr=dev4, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="brown", label='line4')
ax.errorbar(x, y5, yerr=dev5, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="yellow", label='line5')

handles1, labels1 = ax.get_legend_handles_labels()
# 提取误差棒的Line2D对象作为图例handle
handles1 = [h[0] for h in handles1]
ncols = 3
total_entries = len(labels1)

# 计算需要插入的空条目数:使第二行条目居中
empty_entries_needed = (ncols - (total_entries % ncols)) % ncols
insert_index = ncols  # 第二行起始索引

# 插入空条目占位
for _ in range(empty_entries_needed):
    handles1.insert(insert_index, Patch(color='none'))
    labels1.insert(insert_index, '')

# 生成居中的图例
ax.legend(handles=handles1, labels=labels1, ncol=ncols, framealpha=1)
plt.show()

效果说明

修正后,图例第二行的2个标记会自动居中显示,插入的空条目占据第二行第一个位置,让有效标记处于图例的中间列。

内容的提问来源于stack exchange,提问作者Djova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:35:35