Matplotlib 图例指南

本文围绕Matplotlib展开,介绍了图例相关知识,包括图例条目、键、标签和句柄等常用用语。详细阐述了控制图例条目、创建代理艺术家、设置图例位置、处理同一Axes下多个图例、使用图例Handlers以及实现自定义图例handler等内容,帮助读者灵活生成图例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

更多关于matplotlib的学习请关注博客文章


图例指南

 在Matplotlib中灵活地生成图例

 在阅读这一章节前请熟悉关于 legend()的讲解

一些常用用语:

  • 图例条目

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

  • 图例键

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

  • 图例标签

描述键所代表的文本。

  • 图例句柄

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

(也不知道这样子翻译的对不对,先放一下英文版,等明白了再回来改)

  • legend entry

    A legend is made up of one or more legend entries. An entry is made up of exactly one key and one label.

  • legend key

    The colored/patterned marker to the left of each legend label.

  • legend label

    The text which describes the handle represented by the key.

  • legend handle

    The original object which is used to generate an appropriate entry in the legend.


控制图例条目

调用无参的legend()会自动获取图例handles和它们的关联标签

这个功能等效于:

#等效于ax.legend()
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)

get_legend_handles_labels()函数返回存在于轴上的handles或artists,可用于生成结果图例的条目——(要注意的是,并非所有的Artist都可以添加到图例中,这种情况下“proxy(代理)”就需要创建)

带有空字符串作为标签或标签以“ _”开头的artists将被忽略。

要完全控制添加到图例中的内容,通常可以将适当的handles直接传递给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])

在某些情况下,无法设置handles的标签,因此可以将标签列表传递给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'])

创建专门用于添加图例的Artist(又名代理艺术家)

并不是所有的handles都能自动转换为图例条目,所以总是有必要创建一个artist。图例handles不必存在于图形或轴上才能使用。

import matplotlib.patches as mpatches

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

有许多受支持的图例handles。除了创建颜色patch之外,我们还可以创建带有标记的线:

import matplotlib.lines as mlines

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

图例位置

图例的位置可以通过关键字loc来指定。请在官方文档legend()查看更多细节

bbox_to_anchor关键字为手动图例的位置提供了很大程度的控制。

例如,如果你想让坐标轴图例位于图形的右上角而不是坐标轴的角落,只需指定角落的位置和该位置的坐标系统:

plt.plot([1,2,3],[3,2,1],label='Line')
#plt.gcf().transFigure获取当前figure
plt.legend(bbox_to_anchor=(1, 1),
           bbox_transform=plt.gcf().transFigure)

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

plt.subplot(211)
plt.plot([1,2,3],label="Line 1")
plt.plot([3,2,1],label="Line 2")
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="Line 1")
plt.plot([3,2,1],label="Line 2")
plt.legend(bbox_to_anchor=(1.05,1),loc='upper left',borderaxespad=0.)

plt.show()

同一个Axes下多个图例

手动将图例添加到当前Axes下:

line1, = plt.plot([1,2,3],label="Line 1",linestyle='--')
line2, = plt.plot([3,2,1],label="Line 2",linewidth=5)
#为第一条线创建图例
first_legend = plt.legend(handles=[line1],loc='upper right')
#将first_legend手动地添加到当前Axes
ax = plt.gca().add_artist(first_legend)
#为第二条线创建图例
plt.legend(handles=[line2],loc='lower right')

plt.show()

图例Handlers

为了创建图例条目,handles被作为参数提供给适当的HandlerBase子类。

使用自定义Handlers的最简单示例是实例化一个现有的legend_handler.HandlerBase的子类。

为了简单起见,我们选择legend_handler.HandlerLine2D,它接受numpoints参数(numpoints也是legend()函数上的一个关键字)。

然后,我们可以将实例到Handler的映射作为关键字传递给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=3)})

除了用于errorbar、stem plot和histograms等复杂图形类型的Handlers外,默认的handler_map还有一个特殊的元组handler(legend_handler.HandlerTuple),它简单地为给定元组中的每个项绘制一个又一个的handles。

下面的例子演示了将两个图例键组合在一起:

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"])

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

实现自定义的图例handler

可以实现自定义handler来将任何handle转换为图例键(handles不一定需要是matplotlib artists对象)。

handler必须实现一个legend_artist方法,该方法为图例返回一个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()})

或者,如果我们想要全局地接受AnyObject实例,而不需要一直手动设置handler_map关键字,我们可以用:

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

虽然这里的功能很明显,但请记住,已经实现了许多handlers,并且您想要实现的可能已经很容易地通过现有的类实现了。

例如,产生椭圆的图例键,而不是矩形的:

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



如果你发现文章中出现的错误或者有任何疑问欢迎在下方评论区评论


更多文章欢迎到个人博客查看点此跳转

<think>好的,我现在需要处理用户关于Matplotlib使用教程和示例代码的查询。首先,用户明确提到了几个引用内容,我需要先仔细查看这些引用,确保回答时正确引用相关信息。 首先,引用[1]提供了一个设置标记颜色的示例,使用`mfc='r'`来指定标记的填充颜色为红色。这可能对用户理解如何自定义图表元素有帮助。接下来,引用[2]展示了使用Seaborn绘制柱状图和散点图的示例,但用户主要关注的是Matplotlib,所以可能需要区分Seaborn和Matplotlib的关系,指出Seaborn是基于Matplotlib的库,可以简化某些操作,但基础仍是Matplotlib。 引用[3]涉及三维线框图的绘制,使用`plot_wireframe`方法,这属于Matplotlib的高级功能,适合展示三维数据。而引用[4]讨论了实时数据刷新的实现,虽然用户可能对动态图表感兴趣,但需要注意该示例可能存在程序退出的问题,需要谨慎推荐。 用户的需求是查找Matplotlib的使用指南和示例代码,因此需要组织一个结构清晰的回答,涵盖基础图表绘制、样式定制、三维图表和动态更新。同时,根据系统指令,必须使用正确的中文和LaTeX格式,独立公式用`$$...$$`,行内用`$...$`,并生成相关问题。 接下来,我需要确保回答中的每个示例代码都正确无误,并正确引用对应的引用标记。例如,在讲解标记颜色时引用[^1],在三维图表部分引用[^3]。同时,需要避免提及用户不可见的指令,如系统级要求,只需按照结构呈现内容。 另外,生成的相关问题需要与Matplotlib的使用相关,可能包括如何定制图表、处理动态数据、三维可视化等。这些问题应自然地从回答内容中延伸出来,帮助用户进一步探索。 最后,要检查LaTeX语法是否正确,例如数学表达式是否正确用`$`包围,独立公式是否单独成段。例如,如果有数学公式如傅里叶变换,应正确应用格式:$$X_k = \sum_{n=0}^{N-1} x_n e^{-i2\pi kn/N}$$。 总结步骤: 1. 分模块介绍Matplotlib的基础和高级功能。 2. 每个模块提供示例代码,正确引用给定的引用来源。 3. 确保代码正确性,必要时添加注释说明。 4. 生成相关问题,覆盖教程中提到的各个知识点。 5. 检查格式要求,包括中文字符、LaTeX的正确使用等。 现在开始整理回答内容,确保每个部分符合用户的要求,并自然引用提供的参考文献。</think>### Matplotlib 使用教程与示例代码 #### 一、基础图表绘制 1. **折线图与标记定制** 使用`plt.plot()`可快速绘制折线图,通过参数定制标记样式。例如设置标记颜色为红色: ```python import matplotlib.pyplot as plt import numpy as np ypoints = np.array([6, 2, 13, 10]) plt.plot(ypoints, marker='o', ms=20, mfc='r') # mfc设置标记填充颜色 plt.show() ``` 此处`mfc='r'`表示红色填充,`ms`控制标记大小。 2. **柱状图与标题添加** Seaborn(基于Matplotlib)可简化统计图表的绘制,但核心仍依赖Matplotlib: ```python import seaborn as sns data = sns.load_dataset('tips') sns.barplot(x='day', y='total_bill', data=data) plt.title('Total Bill per Day') # 添加标题[^2] plt.show() ``` #### 二、样式与辅助元素定制 - **坐标轴标签与图例** 使用`xlabel()`、`ylabel()`和`legend()`添加说明: ```python x = np.linspace(0, 2*np.pi, 100) y = np.sin(x) plt.plot(x, y, label='sin(x)') plt.xlabel('x轴') plt.ylabel('y轴') plt.legend() plt.show() ``` - **网格线与颜色映射** 添加`plt.grid(True)`开启网格,使用`cmap`参数设置颜色映射: ```python plt.scatter(x, y, c=y, cmap='viridis') plt.colorbar() # 显示颜色条 ``` #### 三、高级图表:三维可视化 通过`mpl_toolkits.mplot3d`绘制三维图表,例如线框图: ```python from mpl_toolkits.mplot3d import Axes3D x1 = np.arange(-5, 5, 0.25) y1 = np.arange(-5, 5, 0.25) X, Y = np.meshgrid(x1, y1) Z = np.sin(np.sqrt(X**2 + Y^2)) # 计算Z值 fig = plt.figure() ax = fig.add_subplot(111, projection="3d") ax.plot_wireframe(X, Y, Z, rstride=3, cstride=2) # 设置行列步长[^3] plt.show() ``` #### 四、动态数据刷新 实时数据更新需结合循环与`plt.pause()`,示例代码片段: ```python plt.ion() # 开启交互模式 for _ in range(10): y_new = np.random.rand() plt.scatter(_, y_new, c='blue') plt.pause(0.1) # 暂停0.1秒 plt.ioff() # 关闭交互模式[^4] ``` 注意:动态刷新可能导致资源未释放,需谨慎处理退出逻辑。 #### 五、数学表达式示例 在图表中添加公式时,使用LaTeX语法: ```python plt.title(r'傅里叶变换公式: $X_k = \sum_{n=0}^{N-1} x_n e^{-i2\pi kn/N}$') ``` 独立公式需换行并用`$$`包裹: $$X_k = \sum_{n=0}^{N-1} x_n e^{-i2\pi kn/N}$$
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值