如何让Matplotlib Pyplot图例中的Hatches填充图案显示美观
解决Matplotlib图例中Hatch图案偏移问题
问题原因
Matplotlib的hatch填充图案基于全局坐标空间绘制,而非图例中Patch的局部边界框,导致小尺寸Patch的hatch无法居中,出现对齐偏移。
解决方案
方法一:自定义居中Hatch的Patch类
重写Patch的get_hatch_transform方法,让hatch图案相对于Patch自身边界框居中:
import matplotlib.patches as mpatches from matplotlib.transforms import TransformedBbox, Bbox import matplotlib.pyplot as plt # 自定义居中hatch的Patch类 class CenteredHatchPatch(mpatches.Patch): def __init__(self, hatch, **kwargs): super().__init__(**kwargs) self.hatch = hatch def get_hatch_transform(self): # 获取Patch的局部边界框 bbox = TransformedBbox(Bbox.from_bounds(0, 0, self.get_width(), self.get_height()), self.get_transform()) # 调整变换矩阵,让hatch以Patch中心为原点 hatch_trans = self.get_transform().inverted() hatch_trans = hatch_trans.translate(bbox.width/2, bbox.height/2) hatch_trans = hatch_trans.scale(1/bbox.width, 1/bbox.height) return hatch_trans # 替换原图例元素中的Patch为自定义类 legend_elements=[ CenteredHatchPatch(hatch="\\\\", facecolor='none', label='not unitary', edgecolor="#8D8896", lw=1), CenteredHatchPatch(hatch="//", facecolor='none', label='not bfb', edgecolor="#752692", lw=1), CenteredHatchPatch(hatch="---", facecolor='none', label='STU obs.', edgecolor="#124C8A", lw=1), CenteredHatchPatch(hatch="xx", facecolor='none', label='Vacuum stab.', edgecolor="#B9314F", lw=1), CenteredHatchPatch(hatch="||", facecolor='none', label='HB excl.', edgecolor="#F57200", lw=1), CenteredHatchPatch(hatch="++", facecolor='none', label='HS excl.', edgecolor="tab:green", lw=1), CenteredHatchPatch(hatch="//", facecolor='none', label='$h_{95}$ excl.', edgecolor="#4EA5D9", lw=1), mpatches.Patch(facecolor="darkgreen", label='stable') ] fig, ax = plt.subplots() ax.legend(handles=legend_elements, ncols=2, loc="lower center", bbox_to_anchor=(0.5, 1.05)) plt.show()
方法二:调整图例Patch尺寸
通过增大图例中Patch的显示尺寸,弱化hatch偏移的视觉效果,操作简单:
# 在legend调用中添加handlelength和handleheight参数 ax.legend(handles=legend_elements, ncols=2, loc="lower center", bbox_to_anchor=(0.5, 1.05), handlelength=2, handleheight=1.5)
方法三:用Line2D模拟Hatch图案
对于简单图案,直接用Line2D的marker或线条模拟,完全控制图案位置:
from matplotlib.lines import Line2D # 重新定义图例元素,用Line2D替代部分Patch legend_elements=[ mpatches.Patch(facecolor='none', hatch="\\\\", label='not unitary', edgecolor="#8D8896", lw=1), # 用"+" marker模拟"++" hatch Line2D([], [], color='tab:green', lw=1, marker='+', linestyle='', markersize=8, label='HS excl.'), # 用水平线模拟"---" hatch Line2D([], [], color="#124C8A", lw=1, linestyle='-', label='STU obs.'), # 用叉号marker模拟"xx" hatch Line2D([], [], color="#B9314F", lw=1, marker='x', linestyle='', markersize=8, label='Vacuum stab.'), # 其他元素按需替换 mpatches.Patch(facecolor="darkgreen", label='stable') ]
方法对比
- 自定义Patch:彻底解决居中问题,适配所有hatch类型,代码稍复杂。
- 调整尺寸:快速改善视觉效果,无需修改元素定义,但无法完全消除偏移。
- Line2D模拟:灵活性高,适合简单图案,需逐个调整元素样式。
内容的提问来源于stack exchange,提问作者TheMaker845
相关产品推荐
相关产品推荐

