图例指南#

图例处理程序#

为了创建图例条目,将句柄作为参数提供给适当的HandlerBase子类。处理程序子类的选择由以下规则决定:

使用关键字get_legend_handler_map()

中的值进行更新。handler_map

检查是否handle在新创建的handler_map.

检查类型handle是否在新创建的handler_map.

检查 's mro 中的任何类型handle是否在新创建的handler_map.

为了完整起见,此逻辑主要在

get_legend_handler().

所有这些灵活性意味着我们有必要的钩子来为我们自己的图例键类型实现自定义处理程序。

使用自定义处理程序的最简单示例是实例化现有legend_handler.HandlerBase子类之一。为了简单起见,让我们选择legend_handler.HandlerLine2D

哪个接受numpoints参数(为方便起见,numpoints 也是legend()函数上的关键字)。然后我们可以将实例到 Handler 的映射作为关键字传递给图例。

from matplotlib.legend_handler import HandlerLine2D

fig, ax = plt.subplots()

line1, = ax.plot([3, 2, 1], marker='o', label='Line 1')

line2, = ax.plot([1, 2, 3], marker='o', label='Line 2')

ax.legend(handler_map={line1: HandlerLine2D(numpoints=4)})

如您所见,“Line 1”现在有 4 个标记点,而“Line 2”有 2 个(默认)。试试上面的代码,只需将地图的键从 更改line1为

type(line1)。请注意现在两个Line2D实例如何获得 4 个标记。

除了用于复杂绘图类型(如误差线、茎图和直方图)的处理程序外,默认设置还有handler_map一个特殊的tuple处理程序 ( legend_handler.HandlerTuple以下示例演示了将两个图例键相互叠加:

from numpy.random import randn

z = randn(10)

fig, ax = plt.subplots()

red_dot, = ax.plot(z, "ro", markersize=15)

# Put a white cross over some of the data.

white_cross, = ax.plot(z[:5], "w+", markeredgewidth=3, markersize=15)

ax.legend([red_dot, (red_dot, white_cross)], ["Attr A", "Attr A+B"])

该类legend_handler.HandlerTuple还可用于将多个图例键分配给同一条目:

from matplotlib.legend_handler import HandlerLine2D, HandlerTuple

fig, ax = plt.subplots()

p1, = ax.plot([1, 2.5, 3], 'r-d')

p2, = ax.plot([3, 2, 1], 'k-o')

l = ax.legend([(p1, p2)], ['Two keys'], numpoints=1,

handler_map={tuple: HandlerTuple(ndivide=None)})

实现自定义图例处理程序#

可以实现自定义处理程序以将任何句柄转换为图例键(句柄不一定需要是 matplotlib 艺术家)。处理程序必须实现一个legend_artist方法,该方法返回单个艺术家供图例使用。所需的签名legend_artist记录在

legend_artist。

import matplotlib.patches as mpatches

class AnyObject:

pass

class AnyObjectHandler:

def legend_artist(self, legend, orig_handle, fontsize, handlebox):

x0, y0 = handlebox.xdescent, handlebox.ydescent

width, height = handlebox.width, handlebox.height

patch = mpatches.Rectangle([x0, y0], width, height, facecolor='red',

edgecolor='black', hatch='xx', lw=3,

transform=handlebox.get_transform())

handlebox.add_artist(patch)

return patch

fig, ax = plt.subplots()

ax.legend([AnyObject()], ['My first handler'],

handler_map={AnyObject: AnyObjectHandler()})

或者,如果我们想要全局接受AnyObject实例而不需要一直手动设置handler_map关键字,我们可以注册新的处理程序:

from matplotlib.legend import Legend

Legend.update_default_handler_map({AnyObject: AnyObjectHandler()})

虽然这里的力量很明显,但请记住已经实现了许多处理程序,并且您想要实现的目标可能已经很容易通过现有的类实现。例如,要生成椭圆图例键,而不是矩形键:

from matplotlib.legend_handler import HandlerPatch

class HandlerEllipse(HandlerPatch):

def create_artists(self, legend, orig_handle,

xdescent, ydescent, width, height, fontsize, trans):

center = 0.5 * width - 0.5 * xdescent, 0.5 * height - 0.5 * ydescent

p = mpatches.Ellipse(xy=center, width=width + xdescent,

height=height + ydescent)

self.update_prop(p, orig_handle, legend)

p.set_transform(trans)

return [p]

c = mpatches.Circle((0.5, 0.5), 0.25, facecolor="green",

edgecolor="red", linewidth=3)

fig, ax = plt.subplots()

ax.add_patch(c)

ax.legend([c], ["An ellipse, not a rectangle"],

handler_map={mpatches.Circle: HandlerEllipse()})

脚本总运行时间:(0分3.053秒)

Download Python source code: legend_guide.py

Download Jupyter notebook: legend_guide.ipynb

由 Sphinx-Gallery 生成的画廊