图例指南

在Matplotlib中灵活生成图例。

本《图例指南》是对以下文件的扩展: legend() -在继续本指南之前,请确保您熟悉该文档的内容。

本指南使用了一些常用术语,为清晰起见,本文将对这些术语进行说明:

图例条目
图例由一个或多个图例条目组成。一个条目由一个键和一个标签组成。
图例键
每个图例标签左侧的彩色/带图案标记。
图例标签
描述由键表示的句柄的文本。
图例句柄
用于在图例中生成适当条目的原始对象。

控制图例项

调用 legend() 如果没有参数,则自动获取图例句柄及其关联的标签。此功能相当于:

handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)

这个 get_legend_handles_labels() 函数返回轴上存在的句柄/艺术家列表,这些句柄/艺术家可用于为生成的图例生成条目-但值得注意的是,并非所有艺术家都可以添加到图例中,此时必须创建“代理”(请参见 创建专门添加到传说中的艺术家(aka.代理艺术家 更多详情)。

标签为空字符串或标签以“”开头的艺术家将被忽略。

为了完全控制要添加到图例中的内容,通常将适当的句柄直接传递给 legend() ::

line_up, = plt.plot([1, 2, 3], label='Line 2')
line_down, = plt.plot([3, 2, 1], label='Line 1')
plt.legend(handles=[line_up, line_down])

在某些情况下,无法设置句柄的标签,因此可以将标签列表传递到 legend() ::

line_up, = plt.plot([1, 2, 3], label='Line 2')
line_down, = plt.plot([3, 2, 1], label='Line 1')
plt.legend([line_up, line_down], ['Line Up', 'Line Down'])

创建专门添加到传说中的艺术家(aka.代理艺术家

并非所有句柄都能自动转换为图例项,因此通常需要创建一个 can . 图例手柄不必存在于图形或轴上即可使用。

假设我们想要创建一个图例,其中包含一些数据的条目,这些数据由红色表示:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

red_patch = mpatches.Patch(color='red', label='The red data')
plt.legend(handles=[red_patch])

plt.show()
legend guide

有许多受支持的图例句柄。我们可以用一个标记来创建一条线,而不是创建一个色块:

import matplotlib.lines as mlines

blue_line = mlines.Line2D([], [], color='blue', marker='*',
                          markersize=15, label='Blue stars')
plt.legend(handles=[blue_line])

plt.show()
legend guide

图例位置

图例的位置可以由关键字参数指定 loc . 请参阅文档 legend() 了解更多详细信息。

这个 bbox_to_anchor 关键字为手动放置图例提供了很大程度的控制。例如,如果希望轴图例位于地物的右上角,而不是轴的角,只需指定角的位置和该位置的坐标系:

plt.legend(bbox_to_anchor=(1, 1),
           bbox_transform=plt.gcf().transFigure)

自定义图例放置的更多示例:

plt.subplot(211)
plt.plot([1, 2, 3], label="test1")
plt.plot([3, 2, 1], label="test2")

# Place a legend above this subplot, expanding itself to
# fully use the given bounding box.
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left',
           ncol=2, mode="expand", borderaxespad=0.)

plt.subplot(223)
plt.plot([1, 2, 3], label="test1")
plt.plot([3, 2, 1], label="test2")
# Place a legend to the right of this smaller subplot.
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)

plt.show()
legend guide

同一轴上的多个图例

有时可以更清楚地将图例项拆分为多个图例。虽然这样做的本能方法可能是 legend() 函数多次,您将发现轴上只存在一个图例。这样可以打电话 legend() 重复将图例更新为轴上的最新控制柄。要保留旧图例实例,必须手动将它们添加到轴:

line1, = plt.plot([1, 2, 3], label="Line 1", linestyle='--')
line2, = plt.plot([3, 2, 1], label="Line 2", linewidth=4)

# Create a legend for the first line.
first_legend = plt.legend(handles=[line1], loc='upper right')

# Add the legend manually to the current Axes.
ax = plt.gca().add_artist(first_legend)

# Create another legend for the second line.
plt.legend(handles=[line2], loc='lower right')

plt.show()
legend guide

图例处理器

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

  1. 更新 get_legend_handler_map() 值在 handler_map 关键字。
  2. 检查是否 handle 在新创建的 handler_map .
  3. 检查类型 handle 在新创建的 handler_map .
  4. 检查中是否有任何类型 handle 的MRO在新创建的 handler_map .

为了完整性,此逻辑主要在 get_legend_handler() .

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

使用自定义处理程序的最简单示例是实例化现有的 legend_handler.HandlerBase 子类。为了简单起见,让我们选择 legend_handler.HandlerLine2D 接受一个 点数 参数(numpoints也是 legend() 功能方便)。然后我们可以将实例到处理程序的映射作为关键字传递到图例。

from matplotlib.legend_handler import HandlerLine2D

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

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

出:

<matplotlib.legend.Legend object at 0x7fa9fc9c9240>

如您所见,“第1行”现在有4个标记点,“第2行”有2个标记点(默认)。尝试上述代码,只更改地图的键 line1type(line1) . 注意现在两个 Line2D 实例得到4个标记。

除了处理复杂绘图类型(如误差条、干图和柱状图)之外,默认值 handler_map 有特殊 tuple 处理程序 (legend_handler.HandlerTuple )它只需为给定元组中的每个项在彼此的顶部绘制句柄。下面的示例演示如何将两个图例键组合在一起:

from numpy.random import randn

z = randn(10)

red_dot, = plt.plot(z, "ro", markersize=15)
# Put a white cross over some of the data.
white_cross, = plt.plot(z[:5], "w+", markeredgewidth=3, markersize=15)

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

出:

<matplotlib.legend.Legend object at 0x7fa9e4470f60>

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

from matplotlib.legend_handler import HandlerLine2D, HandlerTuple

p1, = plt.plot([1, 2.5, 3], 'r-d')
p2, = plt.plot([3, 2, 1], 'k-o')

l = plt.legend([(p1, p2)], ['Two keys'], numpoints=1,
               handler_map={tuple: HandlerTuple(ndivide=None)})
legend guide

实现自定义图例处理程序

可以实现一个自定义处理程序,将任何句柄转换为图例键(句柄不一定需要是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


plt.legend([AnyObject()], ['My first handler'],
           handler_map={AnyObject: AnyObjectHandler()})
legend guide

出:

<matplotlib.legend.Legend object at 0x7fa9fc8294a8>

或者,我们是否希望在全球范围内接受 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)
plt.gca().add_patch(c)

plt.legend([c], ["An ellipse, not a rectangle"],
           handler_map={mpatches.Circle: HandlerEllipse()})
legend guide

出:

<matplotlib.legend.Legend object at 0x7fa9e4ab9160>

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

关键词:matplotlib代码示例,codex,python plot,pyplot Gallery generated by Sphinx-Gallery