Matplotlib中errorbar图例内符号透明度设置问题
解决Matplotlib中Errorbar图例符号透明度无法调整的问题
在绘制包含线条与errorbar的网格图时,想让图例里的符号正常显示,但死活调不了errorbar图例符号的透明度。试了相关方案也没解决,相关代码和当前效果如下:
import matplotlib.pyplot as plt from matplotlib.collections import PathCollection from matplotlib.legend_handler import HandlerPathCollection, HandlerLine2D, HandlerErrorbar import numpy as np # 原代码漏了导入numpy,这里补上 x1 = np.linspace(0,1,8) y1 = np.random.rand(8) # 计算预测区间 sum_of_squares_mid = np.sum((x1 - y1) ** 2) std_mid = np.sqrt(1 / (len(x1) - 2) * sum_of_squares_mid) # 绘制预测区间 y_err_mid = np.vstack([std_mid, std_mid]) * 1.96 plt.plot(x1, y1, 'bo', label='label', marker=r"$\clubsuit$", alpha=0.2) # 默认alpha为1.0 plt.errorbar(x1, y1, yerr=y_err_mid, fmt="o", ecolor="#FF0009", capsize=3, color="#FF0009", label="Errorbar", alpha=.1) # 默认alpha为1.0 def update(handle, orig): handle.update_from(orig) handle.set_alpha(1) plt.legend(handler_map={PathCollection : HandlerPathCollection(update_func = update), plt.Line2D : HandlerLine2D( update_func = update), plt.errorbar : HandlerErrorbar( update_func = update) # 加了这行但没生效,没法只把errorbar图例符号的alpha设为1 }) plt.show()
当前输出效果如图所示:
问题根源
plt.errorbar返回的是ErrorbarContainer对象,不是plt.errorbar这个函数本身,所以直接把plt.errorbar作为handler_map的键完全不生效。另外,ErrorbarContainer包含了标记、线条、误差线多个组件,得单独处理标记部分的透明度。
修复后的代码
import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import PathCollection from matplotlib.legend_handler import HandlerPathCollection, HandlerLine2D, HandlerErrorbar x1 = np.linspace(0,1,8) y1 = np.random.rand(8) # 计算预测区间 sum_of_squares_mid = np.sum((x1 - y1) ** 2) std_mid = np.sqrt(1 / (len(x1) - 2) * sum_of_squares_mid) y_err_mid = np.vstack([std_mid, std_mid]) * 1.96 # 保存绘图返回的对象,方便后续指定handler类型 line_plot, = plt.plot(x1, y1, 'bo', label='label', marker=r"$\clubsuit$", alpha=0.2) errorbar_container = plt.errorbar(x1, y1, yerr=y_err_mid, fmt="o", ecolor="#FF0009", capsize=3, color="#FF0009", label="Errorbar", alpha=.1) # 处理PathCollection(标记)的透明度更新 def update_mark(handle, orig): handle.update_from(orig) handle.set_alpha(1) # 处理ErrorbarContainer的图例更新,单独设置标记的透明度 def update_errorbar_legend(handle, orig): # 遍历图例元素的子组件,找到标记对应的PathCollection for child in handle.get_children(): if isinstance(child, PathCollection): child.set_alpha(1) # 如果不想改变误差线和线条的透明度,这里跳过即可 plt.legend(handler_map={ PathCollection: HandlerPathCollection(update_func=update_mark), type(line_plot): HandlerLine2D(update_func=update_mark), type(errorbar_container): HandlerErrorbar(update_func=update_errorbar_legend) }) plt.show()
核心修改点
- 保存
plt.plot和plt.errorbar的返回对象,用它们的实际类型作为handler_map的键,而不是用函数本身 - 针对
ErrorbarContainer的图例处理,遍历其子元素,找到标记对应的PathCollection并将透明度设为1 - 统一线条和普通标记的透明度更新逻辑
内容的提问来源于stack exchange,提问作者Mario
相关产品推荐
相关产品推荐

