matplotlib柱状图图例加图片报BarContainer无_transform属性错误求助
问题原因
报错的根因是ImageHandler默认调用update_prop方法尝试将原图例句柄(ax.bar返回的BarContainer类型)的属性同步给自定义图片元素,但BarContainer是柱状图元素的容器对象,不具备普通绘图元素的_transform属性,因此触发属性不存在报错。
修复方案
直接修改自定义的ImageHandler类,删除不需要的属性同步逻辑即可,因为我们的图例完全使用自定义图片,不需要继承原有柱状图的任何样式属性。
修改后的ImageHandler代码
from matplotlib.transforms import Bbox, TransformedBbox from matplotlib.legend_handler import HandlerBase from matplotlib.image import BboxImage class ImageHandler(HandlerBase): def create_artists(self, legend, orig_handle, Xd_, Yd_, W_, H_, fontsize, trans): # 调整图片的边距 sx, sy = self.image_stretch # 创建存放图片的边界框 bb = Bbox.from_bounds(Xd_ - sx, Yd_ - sy, W_ + sx, H_ + sy ) tbb = TransformedBbox(bb, trans) image = BboxImage(tbb) image.set_data(self.image_data) # 删掉原本的属性同步语句即可解决报错 # self.update_prop(image, orig_handle, legend) return [image] def set_image(self, image_path, image_stretch=(0, 0)): self.image_data = plt.imread(image_path) self.image_stretch = image_stretch
图例调用调整
调用legend时可以将标签设为空字符串,避免多余文本显示,同时调整image_stretch参数适配图片尺寸:
emoji_dataset = os.path.join( os.environ['HOME'], 'Datasets', 'Emojis') h1 = ImageHandler() h2 = ImageHandler() # 调整stretch参数避免图片过大超出图例范围 h1.set_image(os.path.join(emoji_dataset, 'man.png'), image_stretch=(0, 2)) h2.set_image(os.path.join(emoji_dataset, 'woman.png'), image_stretch=(0, 2)) # 传入空字符串作为标签,仅保留图片显示 ax.legend( handles=[rects1, rects2], labels=["", ""], handler_map={rects1: h1, rects2: h2}, handlelength=2, labelspacing=0.0, borderpad=0.15, loc='best', handletextpad=0.2, borderaxespad=0.15 )
补充说明
如果需要保留原图例的部分样式,可以选择不修改ImageHandler,而是在调用legend时传入虚拟的普通Artist对象作为句柄(比如matplotlib.lines.Line2D([], [])),同样可以避开BarContainer的属性缺失问题。
内容的提问来源于stack exchange,提问作者farid
相关产品推荐
相关产品推荐

