3.6.md 16.2 KB
Newer Older
W
3.6  
wizardforcel 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
# 3.6 图例指南

> 原文:[Legend guide](http://matplotlib.org/users/legend_guide.html)

> 译者:[飞龙](https://github.com/)

> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)

此图例指南是`legend()`中可用文档的扩展 - 请在继续阅读本指南之前确保你熟悉该文档(见篇尾)的内容。

本指南使用一些常见术语,为了清楚起见,这些术语在此处进行说明:

图例条目

图例由一个或多个图例条目组成。 一个条目由一个键和一个标签组成。

图例键

每个图例标签左侧的彩色/图案标记。

图例标签

描述由键表示的句柄的文本。

图例句柄

用于在图例中生成适当条目的原始对象。

## 控制图例条目

不带参数调用`legend()`会自动获取图例句柄及其相关标签。 此函数等同于:

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

`get_legend_handles_labels()`函数返回轴域上存在的句柄/artist 的列表,这些句柄/artist 可以用于为结果图例生成条目 - 但值得注意的是,并非所有 artist 都可以添加到图例中, 这种情况下会创建『代理』(请参阅[特地为添加到图例创建 artist(也称为代理 artist)](http://matplotlib.org/users/legend_guide.html#proxy-legend-handles),来了解更多详细信息)。

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

```py
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()`

```py
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'])
```

## 特地为添加到图例创建 artist(也称为代理 artist)

并非所有的句柄都可以自动转换为图例条目,因此通常需要创建一个可转换的 artist。 图例句柄不必存在于被用到的图像或轴域上。

假设我们想创建一个图例,其中有一些数据表示为红色:

```py
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()
```

![](http://matplotlib.org/_images/legend_guide-1.png)

除了创建一个色块之外,有许多受支持的图例句柄,我们可以创建一个带有标记的线条:

```py
import matplotlib.lines as mlines
import matplotlib.pyplot as plt

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

plt.show()
```

## 图例位置

图例的位置可以通过关键字参数`loc`指定。 详细信息请参阅`legend()`的文档。

`bbox_to_anchor`关键字可让用户手动控制图例布局。 例如,如果你希望轴域图例位于图像的右上角而不是轴域的边角,则只需指定角的位置以及该位置的坐标系:

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

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

```py
import matplotlib.pyplot as plt


plt.subplot(211)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# 将图例放到这个子图上方,
# 扩展自身来完全利用提供的边界框。
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
           ncol=2, mode="expand", borderaxespad=0.)

plt.subplot(223)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# 将图例放到这个小型子图的右侧
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

plt.show()
```

![](http://matplotlib.org/_images/simple_legend01.png)

## 相同轴域内的多个图例

有时,在多个图例之间分割图例条目会更加清晰。 虽然直觉上的做法可能是多次调用`legend()`函数,但你会发现轴域上只存在一个图例。 这样做是为了可以重复调用`legend()`,将图例更新为轴域上的最新句柄,因此要保留旧的图例实例,我们必须将它们手动添加到轴域中:

```py
import matplotlib.pyplot as plt

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

# 为第一个线条创建图例
first_legend = plt.legend(handles=[line1], loc=1)

# 手动将图例添加到当前轴域
ax = plt.gca().add_artist(first_legend)

# 为第二个线条创建另一个图例
plt.legend(handles=[line2], loc=4)

plt.show()
```

![](http://matplotlib.org/_images/simple_legend02.png)

## 图例处理器

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

+ 使用`handler_map`关键字中的值更新`get_legend_handler_map()`
+ 检查句柄是否在新创建的`handler_map`中。
+ 检查句柄的类型是否在新创建的`handler_map`中。
+ 检查句柄的`mro`中的任何类型是否在新创建的`handler_map`中。

处于完整性,这个逻辑大多在`get_legend_handler()`中实现。

所有这些灵活性意味着我们可以使用一些必要的钩子,为我们自己的图例键类型实现自定义处理器。

使用自定义处理器的最简单的例子是,实例化一个现有的`HandlerBase`子类。 为了简单起见,让我们选择`matplotlib.legend_handler.HandlerLine2D`,它接受`numpoints`参数(出于便利,注意`numpoints``legend()`函数上的一个关键字)。 然后我们可以将实例的字典作为关键字`handler_map`传给`legend`

```py
import matplotlib.pyplot as plt
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)})
```

![](http://matplotlib.org/_images/legend_guide-3.png)

如你所见,`Line 1`现在有 4 个标记点,`Line 2`有两个(默认值)。 尝试上面的代码,只需将字典的键从`line1`更改为type(line)`。 注意现在两个`Line2D`实例都拥有了 4 个标记。

除了用于复杂的绘图类型的处理器,如误差条,茎叶图和直方图,默认的`handler_map`有一个特殊的元组处理器(`HandlerTuple`),它简单地在顶部一一绘制给定元组中每个项目的句柄。 以下示例演示如何将两个图例的键相互叠加:

```py
import matplotlib.pyplot as plt
from numpy.random import randn

z = randn(10)

red_dot, = plt.plot(z, "ro", markersize=15)
# 将白色十字放置在一些数据上
white_cross, = plt.plot(z[:5], "w+", markeredgewidth=3, markersize=15)

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

![](http://matplotlib.org/_images/legend_guide-4.png)

### 实现自定义图例处理器


可以实现自定义处理器,将任何句柄转换为图例的键(句柄不必要是`matplotlib`artist)。 处理器必须实现`legend_artist`方法,该方法为要使用的图例返回单个 artist。 有关`legend_artist`的详细信息,请参阅[`legend_artist()`](http://matplotlib.org/api/legend_api.html#matplotlib.legend_handler.HandlerBase.legend_artist)。

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

class AnyObject(object):
    pass

class AnyObjectHandler(object):
    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()})
```

![](http://matplotlib.org/_images/legend_guide-5.png)

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

```py
from matplotlib.legend import Legend
Legend.update_default_handler_map({AnyObject: AnyObjectHandler()})
```

虽然这里的功能十分清楚,请记住,有很多已实现的处理器,你想实现的目标可能易于使用现有的类实现。 例如,要生成椭圆的图例键,而不是矩形键:

```py
from matplotlib.legend_handler import HandlerPatch
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches


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()})
```

![](http://matplotlib.org/_images/legend_guide-6.png)

## 使用图例的现有示例

这里是一个不太详尽的示例列表,涉及以各种方式使用的图例:

+ [`lines_bars_and_markers` 示例代码: `scatter_with_legend.py`](http://matplotlib.org/examples/lines_bars_and_markers/scatter_with_legend.html#lines-bars-and-markers-scatter-with-legend)
+ [API 示例代码: `legend_demo.py`](http://matplotlib.org/examples/api/legend_demo.html#api-legend-demo)
+ [`pylab_examples` 示例代码: `contourf_hatching.py`](http://matplotlib.org/examples/pylab_examples/contourf_hatching.html#pylab-examples-contourf-hatching)
+ [`pylab_examples` 示例代码: `figlegend_demo.py`](http://matplotlib.org/examples/pylab_examples/figlegend_demo.html#pylab-examples-figlegend-demo)
+ [`pylab_examples` 示例代码: `finance_work2.py`](http://matplotlib.org/examples/pylab_examples/finance_work2.html#pylab-examples-finance-work2)
+ [`pylab_examples` 示例代码: `scatter_symbol.py`](http://matplotlib.org/examples/pylab_examples/scatter_symbol.html#pylab-examples-scatter-symbol)
W
3.6 doc  
wizardforcel 已提交
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

## `matplotlib.pyplot.legend(*args, **kwargs)` 文档

在轴域上放置一个图例。

为了为轴域上已经存在的线条(例如通过绘图)制作图例,只需使用字符串的可迭代对象(每个图例条目对应一个字符串)调用此函数。 例如:

```py
ax.plot([1, 2, 3])
ax.legend(['A simple line'])
```

但是,为了使『标签』和图例元素实例保持一致,最好在 artist 创建时指定标签,或者通过调用 artist 的`set_label()`方法:

```py
line, = ax.plot([1, 2, 3], label='Inline label')
# 通过调用该方法覆写标签
line.set_label('Label via method')
ax.legend()
```

通过定义以下划线开头的标签,可以从图例元素自动选择中排除特定线条。 这对于所有 artist 都是默认的,因此不带任何参数调用`legend()`,并且没有手动设置标签会导致没有绘制图例。

为了完全控制哪些 artist 拥有图例条目,可以传递拥有图例的 artist 的可迭代对象,然后是相应图例标签的可迭代对象:

```py
legend((line1, line2, line3), ('label1', 'label2', 'label3'))
```

### 参数

`loc`:整数、字符串或者浮点偶对,默认为`'upper right'`。

图例的位置。 可能的代码是:

|位置字符串 | 位置代码 |
| --- | --- |
| `'best'` | `0` |
| `'upper right'` | `1` |
| `'upper left'` | `2` |
| `'lower left'` | `3` |
| `'lower right'` | `4` |
| `'right'` | `5` |
| `'center left'` | `6` |
| `'center right'` | `7` |
| `'lower center'` | `8` |
| `'upper center'` | `9` |
| `'center'` | `10` |

W
fix  
wizardforcel 已提交
316
或者,可以是一个二元组,提供图例的距离左下角的`x, y`坐标(在这种情况下,`bbox_to_anchor`将被忽略)。
W
3.6 doc  
wizardforcel 已提交
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

`bbox_to_anchor `:`matplotlib.transforms.BboxBase`示例或者浮点元组。

在`bbox_transform`坐标(默认轴域坐标)中为图例指定任意位置。

例如,要将图例的右上角放在轴域中心,可以使用以下关键字:

```py
loc='upper right', bbox_to_anchor=(0.5, 0.5)
```

`ncol`:整数。

图例的列数,默认为 1。

`prop`:`None`、`matplotlib.font_manager.FontProperties`或者字典。

图例的字体属性,如果为`None`(默认),会使用当前的` matplotlib.rcParams`。

`fontsize`:整数、浮点或者`{‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’}`。

控制图例的字体大小。 如果值为数字,则大小将为绝对字体大小(以磅为单位)。 字符串值相对于当前默认字体大小。 此参数仅在未指定`prop`的情况下使用。

`numpoints`:`None`或者整数。

为线条/`matplotlib.lines.Line2D`创建图例条目时,图例中的标记点数。 默认值为`None`,它将从`legend.numpoints` `rcParam`中获取值。

`scatterpoints`:`None`或者整数。

为散点图/`matplotlib.collections.PathCollection`创建图例条目时,图例中的标记点数。 默认值为`None`,它将从`legend.scatterpoints` `rcParam`中获取值。

`scatteryoffsets`:浮点的可迭代对象。

W
fix  
wizardforcel 已提交
350
为散点图图例条目创建的标记的垂直偏移量(相对于字体大小)。 0.0 是在图例文本的底部,1.0 是在顶部。 为了将所有标记绘制在相同的高度,请设置为`[0.5]`。 默认值为`[0.375,0.5,0.3125]`。
W
3.6 doc  
wizardforcel 已提交
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414

`markerscale`:`None`、整数或者浮点。

图例标记对于原始绘制的标记的相对大小。 默认值为`None`,它将从`legend.markerscale` `rcParam`中获取值。

`markerfirst`: `[ True | False ]`

如果为`True`,则图例标记位于图例标签的左侧,如果为`False`,图例标记位于图例标签的右侧。

`frameon`:`None`或布尔值

控制是否应在图例周围绘制框架。 默认值为`None`,它将从`legend.frameon` `rcParam`中获取值。

`fancybox`:`None`或布尔值

控制是否应在构成图例背景的`FancyBboxPatch`周围启用圆边。 默认值为`None`,它将从`legend.fancybox` `rcParam`中获取值。

`shadow`:`None`或布尔值

控制是否在图例后面画一个阴影。 默认值为`None`,它将从`legend.shadow` `rcParam`中获取值。

`framealpha`:`None`或浮点

控制图例框架的 Alpha 透明度。 默认值为`None`,它将从`legend.framealpha` `rcParam`中获取值。

`mode`:`{"expand", None}`

如果`mode`设置为`"expand"`,图例将水平扩展来填充轴域区域(如果定义图例的大小,则为`bbox_to_anchor`)。

`bbox_transform`:`None`或者` matplotlib.transforms.Transform`

边界框的变换(`bbox_to_anchor`)。 对于`None`值(默认),将使用`Axes`的`transAxes`变换。

`title`:字符串或者`None`

图例的标题,默认没有标题(`None`)。

`borderpad`:浮点或`None`

图例边框的内边距。 以字体大小为单位度量。 默认值为`None`,它将从`legend.borderpad` `rcParam`中获取值。

`labelspacing`:浮点或`None`

图例条目之间的垂直间距。 以字体大小为单位度量。 默认值为`None`,它将从`legend.labelspacing` `rcParam`中获取值。

`handlelength`:浮点或`None`

图例句柄的长度。 以字体大小为单位度量。 默认值为`None`,它将从`legend.handlelength` `rcParam`取值。

`handletextpad`:浮点或`None`

图例句柄和文本之间的间距。 以字体大小为单位度量。 默认值为`None`,它将从`legend.handletextpad` `rcParam`中获取值。

`borderaxespad`:浮点或`None`

轴和图例边框之间的间距。 以字体大小为单位度量。 默认值为`None`,它将从`legend.borderaxespad` `rcParam`中获取值。

`columnspacing`:浮点或`None`

列间距。以字体大小为单位度量。 默认值为`None`,它将从`legend.columnspacing` `rcParam`中获取值。

`handler_map`:字典或`None`

自定义字典,用于将实例或类型映射到图例处理器。 这个`handler_map`会更新在`matplotlib.legend.Legend.get_legend_handler_map()`中获得的默认处理器字典。