快速入门指南#

本教程介绍了一些基本的使用模式和最佳实践,以帮助您开始使用 Matplotlib.

import matplotlib.pyplot as plt
import numpy as np

一个简单的例子#

Matplotlib 将您的数据绘制在 Figure 上(例如,窗口,Jupyter 小部件等),每个图形可以包含一个或多个 Axes ,这是一个可以在 x-y 坐标(或极坐标图中的 theta-r,3D 图中的 x-y-z 等)中指定点的区域.创建包含 Axes 的 Figure 的最简单方法是使用 pyplot.subplots .然后,我们可以使用 Axes.plot 在 Axes 上绘制一些数据,并使用 show 显示图形:

fig, ax = plt.subplots()             # Create a figure containing a single Axes.
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])  # Plot some data on the Axes.
plt.show()                           # Show the figure.
quick start

根据您所工作的环境,可以省略 plt.show() .例如,Jupyter notebooks 就是这种情况,它会自动显示在代码单元格中创建的所有图形.

Figure 的组成部分#

以下是 Matplotlib Figure 的组成部分.

../../_images/anatomy.png

Figure#

整个图形.Figure 跟踪所有子 Axes ,一组"特殊"艺术家(标题,图形图例,颜色条等),甚至嵌套的子图形.

通常,您将通过以下函数之一创建一个新的 Figure:

fig = plt.figure()             # an empty figure with no Axes
fig, ax = plt.subplots()       # a figure with a single Axes
fig, axs = plt.subplots(2, 2)  # a figure with a 2x2 grid of Axes
# a figure with one Axes on the left, and two on the right:
fig, axs = plt.subplot_mosaic([['left', 'right_top'],
                               ['left', 'right_bottom']])

subplots()subplot_mosaic 是便捷函数,它们还在 Figure 内部创建 Axes 对象,但您也可以稍后手动添加 Axes.

有关 Figures 的更多信息,包括平移和缩放,请参阅 Figure简介 .

Axes#

Axes 是附加到 Figure 的 Artist,它包含一个用于绘制数据的区域,通常包括两个(或 3D 情况下的三个) Axis 对象(请注意 Axes 和 Axis 之间的区别),这些对象提供刻度和刻度标签,以便为 Axes 中的数据提供比例.每个 Axes 还有一个标题(通过 set_title() 设置),一个 x 轴标签(通过 set_xlabel() 设置)和一个 y 轴标签(通过 set_ylabel() 设置).

Axes 方法是配置绘图大部分内容的主要接口(添加数据,控制轴比例和限制,添加标签等).

Axis#

这些对象设置比例和限制,并生成刻度(轴上的标记)和刻度标签(标记刻度的字符串).刻度的位置由 Locator 对象确定,刻度标签字符串由 Formatter 格式化.正确的 LocatorFormatter 的组合可以非常精细地控制刻度位置和标签.

Artist#

基本上,Figure 上可见的所有内容都是 Artist(甚至是 Figure , AxesAxis 对象).这包括 Text 对象, Line2D 对象, collections 对象, Patch 对象等.渲染 Figure 时,所有 Artist 都会绘制到画布上.大多数 Artist 都绑定到一个 Axes;这样的 Artist 不能被多个 Axes 共享,也不能从一个 Axes 移动到另一个 Axes.

绘图函数的输入类型#

绘图函数期望将 numpy.arraynumpy.ma.masked_array 作为输入,或者可以将对象传递给 numpy.asarray . 类似于数组("类数组")的类,例如 pandas 数据对象和 numpy.matrix 可能无法按预期工作. 常见的惯例是在绘图之前将它们转换为 numpy.array 对象. 例如,要转换一个 numpy.matrix

b = np.matrix([[1, 2], [3, 4]])
b_asarray = np.asarray(b)

大多数方法还会解析一个字符串索引对象,如字典, structured numpy arraypandas.DataFrame . Matplotlib 允许您提供 data 关键字参数,并通过传递与 x 和 y 变量对应的字符串来生成绘图.

np.random.seed(19680801)  # seed the random number generator.
data = {'a': np.arange(50),
        'c': np.random.randint(0, 50, 50),
        'd': np.random.randn(50)}
data['b'] = data['a'] + 10 * np.random.randn(50)
data['d'] = np.abs(data['d']) * 100

fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained')
ax.scatter('a', 'b', c='c', s='d', data=data)
ax.set_xlabel('entry a')
ax.set_ylabel('entry b')
quick start

编码风格#

显式和隐式接口#

如上所述,使用 Matplotlib 主要有两种方式:

  • 显式地创建 Figures 和 Axes,并在它们上面调用方法("面向对象 (OO) 风格").

  • 依赖 pyplot 隐式地创建和管理 Figures 和 Axes,并使用 pyplot 函数进行绘图.

有关隐式和显式接口之间权衡的解释,请参见 Matplotlib 应用程序接口 (APIs) .

因此,可以使用 OO 风格

x = np.linspace(0, 2, 100)  # Sample data.

# Note that even in the OO-style, we use `.pyplot.figure` to create the Figure.
fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained')
ax.plot(x, x, label='linear')  # Plot some data on the Axes.
ax.plot(x, x**2, label='quadratic')  # Plot more data on the Axes...
ax.plot(x, x**3, label='cubic')  # ... and some more.
ax.set_xlabel('x label')  # Add an x-label to the Axes.
ax.set_ylabel('y label')  # Add a y-label to the Axes.
ax.set_title("Simple Plot")  # Add a title to the Axes.
ax.legend()  # Add a legend.
Simple Plot

或 pyplot 风格:

x = np.linspace(0, 2, 100)  # Sample data.

plt.figure(figsize=(5, 2.7), layout='constrained')
plt.plot(x, x, label='linear')  # Plot some data on the (implicit) Axes.
plt.plot(x, x**2, label='quadratic')  # etc.
plt.plot(x, x**3, label='cubic')
plt.xlabel('x label')
plt.ylabel('y label')
plt.title("Simple Plot")
plt.legend()
Simple Plot

(此外,还有第三种方法,适用于将 Matplotlib 嵌入到 GUI 应用程序中,它完全放弃了 pyplot,即使是对于图形创建也是如此.有关更多信息,请参阅图库中的相应部分 在图形用户界面中嵌入 Matplotlib .)

Matplotlib 的文档和示例同时使用 OO 和 pyplot 风格. 通常,我们建议使用 OO 风格,特别是对于复杂的绘图,以及旨在作为大型项目的一部分重复使用的函数和脚本. 但是,对于快速的交互式工作,pyplot 风格可能非常方便.

备注

您可能会发现使用 pylab 接口的旧示例,通过 from pylab import * . 强烈反对这种方法.

创建辅助函数#

如果您需要使用不同的数据集一遍又一遍地进行相同的绘图,或者想要轻松地包装 Matplotlib 方法,请使用下面推荐的签名函数.

def my_plotter(ax, data1, data2, param_dict):
    """
    A helper function to make a graph.
    """
    out = ax.plot(data1, data2, **param_dict)
    return out

然后您可以两次使用它来填充两个子图:

data1, data2, data3, data4 = np.random.randn(4, 100)  # make 4 random data sets
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(5, 2.7))
my_plotter(ax1, data1, data2, {'marker': 'x'})
my_plotter(ax2, data3, data4, {'marker': 'o'})
quick start

请注意,如果您想将这些作为 python 包安装,或者进行任何其他自定义,您可以使用网络上的众多模板之一; Matplotlib 在 mpl-cookiecutter 有一个.

样式化艺术家#

大多数绘图方法都有用于艺术家的样式选项,可以在调用绘图方法时访问,也可以从艺术家的"setter"访问. 在下面的绘图中,我们手动设置了 plot 创建的艺术家的颜色,线宽和线型,并且在使用 set_linestyle 之后设置了第二行的线型.

fig, ax = plt.subplots(figsize=(5, 2.7))
x = np.arange(len(data1))
ax.plot(x, np.cumsum(data1), color='blue', linewidth=3, linestyle='--')
l, = ax.plot(x, np.cumsum(data2), color='orange', linewidth=2)
l.set_linestyle(':')
quick start

颜色#

Matplotlib 有一个非常灵活的颜色数组,大多数艺术家都接受这些颜色; 有关规范列表,请参见 allowable color definitions . 一些艺术家会采用多种颜色. 即,对于 scatter 绘图,标记的边缘可以与内部颜色不同:

fig, ax = plt.subplots(figsize=(5, 2.7))
ax.scatter(data1, data2, s=50, facecolor='C0', edgecolor='k')
quick start

线宽,线型和标记大小#

线宽通常以印刷点为单位(1 pt = 1/72 英寸),可用于具有描边线的艺术家. 类似地,描边线可以具有线型. 请参阅 linestyles example .

标记大小取决于所使用的方法. plot 以点为单位指定标记大小,通常是标记的"直径"或宽度. scatter 指定标记大小,大约与标记的视觉区域成正比. 有一个标记样式数组可用作字符串代码(请参阅 markers ),或者用户可以定义自己的 MarkerStyle (请参阅 Marker 参考 ):

fig, ax = plt.subplots(figsize=(5, 2.7))
ax.plot(data1, 'o', label='data1')
ax.plot(data2, 'd', label='data2')
ax.plot(data3, 'v', label='data3')
ax.plot(data4, 's', label='data4')
ax.legend()
quick start

标记绘图#

轴标签和文本#

set_xlabel , set_ylabelset_title 用于在指定位置添加文本(有关更多讨论,请参见 Matplotlib 中的文本 ). 也可以使用 text 将文本直接添加到绘图中:

mu, sigma = 115, 15
x = mu + sigma * np.random.randn(10000)
fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained')
# the histogram of the data
n, bins, patches = ax.hist(x, 50, density=True, facecolor='C0', alpha=0.75)

ax.set_xlabel('Length [cm]')
ax.set_ylabel('Probability')
ax.set_title('Aardvark lengths\n (not really)')
ax.text(75, .025, r'$\mu=115,\ \sigma=15$')
ax.axis([55, 175, 0, 0.03])
ax.grid(True)
Aardvark lengths  (not really)

所有 text 函数都会返回一个 matplotlib.text.Text 实例. 就像上面的线条一样,您可以通过将关键字参数传递到文本函数来自定义属性:

t = ax.set_xlabel('my data', fontsize=14, color='red')

这些属性在 文本属性和布局 中有更详细的介绍.

在文本中使用数学表达式#

Matplotlib 接受任何文本表达式中的 TeX 方程表达式.例如,要在标题中写入表达式 \(\sigma_i=15\) ,您可以编写一个用美元符号括起来的 TeX 表达式:

ax.set_title(r'$\sigma_i=15$')

其中标题字符串前面的 r 表示该字符串是一个原始字符串,不应将反斜杠视为 python 转义符.Matplotlib 有一个内置的 TeX 表达式解析器和布局引擎,并附带了自己的数学字体--有关详细信息,请参阅 书写数学表达式 .您还可以直接使用 LaTeX 格式化您的文本,并将输出直接合并到您的显示图形或保存的 postscript 中--请参阅 使用 LaTeX 渲染文本 .

注释#

我们还可以在图上注释点,通常通过连接一个指向 xy 的箭头,到 xytext 处的一段文本:

fig, ax = plt.subplots(figsize=(5, 2.7))

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2 * np.pi * t)
line, = ax.plot(t, s, lw=2)

ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
            arrowprops=dict(facecolor='black', shrink=0.05))

ax.set_ylim(-2, 2)
quick start

在这个基本示例中,xy 和 xytext 都在数据坐标中.还有许多其他的坐标系可以选择--有关详细信息,请参阅 Basic annotation高级注释 .更多示例也可以在 注释绘图 中找到.

图例#

通常我们想用一个 Axes.legend 来识别线条或标记:

fig, ax = plt.subplots(figsize=(5, 2.7))
ax.plot(np.arange(len(data1)), data1, label='data1')
ax.plot(np.arange(len(data2)), data2, label='data2')
ax.plot(np.arange(len(data3)), data3, 'd', label='data3')
ax.legend()
quick start

Matplotlib 中的图例在布局,位置以及可以代表的 Artists 方面非常灵活.它们在 图例指南 中有详细的讨论.

轴刻度和刻度#

每个 Axes 都有两个(或三个) Axis 对象,分别代表 x 轴和 y 轴.这些对象控制轴的刻度,刻度定位器和刻度格式化器.可以附加额外的 Axes 来显示进一步的 Axis 对象.

刻度#

除了线性刻度外,Matplotlib 还提供非线性刻度,例如对数刻度.由于对数刻度使用得非常频繁,因此还有像 loglog , semilogxsemilogy 这样的直接方法.有多种刻度(有关其他示例,请参阅 标度 ).在这里,我们手动设置刻度:

fig, axs = plt.subplots(1, 2, figsize=(5, 2.7), layout='constrained')
xdata = np.arange(len(data1))  # make an ordinal for this
data = 10**data1
axs[0].plot(xdata, data)

axs[1].set_yscale('log')
axs[1].plot(xdata, data)
quick start

刻度设置了从数据值到沿着轴的间距的映射.这发生在两个方向上,并组合成一个变换,这是 Matplotlib 从数据坐标映射到 Axes,Figure 或屏幕坐标的方式.请参阅 转换教程 .

刻度定位器和格式化器#

每个 Axis 都有一个刻度定位器和格式化器,用于选择沿着 Axis 对象放置刻度线的位置.一个简单的接口是 set_xticks :

fig, axs = plt.subplots(2, 1, layout='constrained')
axs[0].plot(xdata, data1)
axs[0].set_title('Automatic ticks')

axs[1].plot(xdata, data1)
axs[1].set_xticks(np.arange(0, 100, 30), ['zero', '30', 'sixty', '90'])
axs[1].set_yticks([-1.5, 0, 1.5])  # note that we don't need to specify labels
axs[1].set_title('Manual ticks')
Automatic ticks, Manual ticks

不同的刻度可以有不同的定位器和格式化器;例如,上面的对数刻度使用 LogLocatorLogFormatter .有关其他格式化器和定位器以及编写您自己的格式化器和定位器的信息,请参阅 刻度定位器刻度格式器 .

绘制日期和字符串#

Matplotlib 可以处理绘制日期数组和字符串数组,以及浮点数.这些会得到适当的特殊定位器和格式化器.对于日期:

from matplotlib.dates import ConciseDateFormatter

fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained')
dates = np.arange(np.datetime64('2021-11-15'), np.datetime64('2021-12-25'),
                  np.timedelta64(1, 'h'))
data = np.cumsum(np.random.randn(len(dates)))
ax.plot(dates, data)
ax.xaxis.set_major_formatter(ConciseDateFormatter(ax.xaxis.get_major_locator()))
quick start

有关更多信息,请参见日期示例(例如 日期刻度标签 )

对于字符串,我们得到分类绘图(参见 绘制分类变量 ).

fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained')
categories = ['turnips', 'rutabaga', 'cucumber', 'pumpkins']

ax.bar(categories, np.random.rand(len(categories)))
quick start

关于分类绘图的一个注意事项是,某些解析文本文件的方法返回一个字符串列表,即使这些字符串都表示数字或日期.如果您传递 1000 个字符串,Matplotlib 会认为您指的是 1000 个类别,并会在您的绘图中添加 1000 个刻度!

额外的 Axis 对象#

在一个图表中绘制不同量级的数据可能需要额外的 y 轴.可以通过使用 twinx 添加一个具有不可见的 x 轴和位于右侧的 y 轴来创建这样的 Axis(类似于 twiny ).有关另一个示例,请参阅 具有不同比例的绘图 .

类似地,您可以添加一个 secondary_xaxissecondary_yaxis ,它具有与主 Axis 不同的刻度,以不同的刻度或单位表示数据.有关更多示例,请参阅 次坐标轴 .

fig, (ax1, ax3) = plt.subplots(1, 2, figsize=(7, 2.7), layout='constrained')
l1, = ax1.plot(t, s)
ax2 = ax1.twinx()
l2, = ax2.plot(t, range(len(t)), 'C1')
ax2.legend([l1, l2], ['Sine (left)', 'Straight (right)'])

ax3.plot(t, s)
ax3.set_xlabel('Angle [rad]')
ax4 = ax3.secondary_xaxis('top', (np.rad2deg, np.deg2rad))
ax4.set_xlabel('Angle [°]')
quick start

颜色映射数据#

通常,我们希望在绘图中使用颜色映射中的颜色来表示第三个维度.Matplotlib 有许多执行此操作的绘图类型:

from matplotlib.colors import LogNorm

X, Y = np.meshgrid(np.linspace(-3, 3, 128), np.linspace(-3, 3, 128))
Z = (1 - X/2 + X**5 + Y**3) * np.exp(-X**2 - Y**2)

fig, axs = plt.subplots(2, 2, layout='constrained')
pc = axs[0, 0].pcolormesh(X, Y, Z, vmin=-1, vmax=1, cmap='RdBu_r')
fig.colorbar(pc, ax=axs[0, 0])
axs[0, 0].set_title('pcolormesh()')

co = axs[0, 1].contourf(X, Y, Z, levels=np.linspace(-1.25, 1.25, 11))
fig.colorbar(co, ax=axs[0, 1])
axs[0, 1].set_title('contourf()')

pc = axs[1, 0].imshow(Z**2 * 100, cmap='plasma', norm=LogNorm(vmin=0.01, vmax=100))
fig.colorbar(pc, ax=axs[1, 0], extend='both')
axs[1, 0].set_title('imshow() with LogNorm()')

pc = axs[1, 1].scatter(data1, data2, c=data3, cmap='RdBu_r')
fig.colorbar(pc, ax=axs[1, 1], extend='both')
axs[1, 1].set_title('scatter()')
pcolormesh(), contourf(), imshow() with LogNorm(), scatter()

Colormaps#

这些都是从 ScalarMappable 对象派生的 Artist 的示例.它们都可以设置 vmin 和 vmax 之间的线性映射到 cmap 指定的颜色映射中.Matplotlib 有很多颜色映射可供选择( 在 Matplotlib 中选择颜色映射 ),你可以制作自己的颜色映射( 在 Matplotlib 中创建颜色映射 )或下载 third-party packages .

Normalizations#

有时我们希望数据到颜色映射的非线性映射,如上面的 LogNorm 示例中所示.我们通过向 ScalarMappable 提供 norm 参数而不是 vmin 和 vmax 来实现这一点.更多归一化显示在 颜色映射归一化 .

颜色条#

添加 colorbar 提供了一个将颜色与底层数据相关联的键.Colorbars 是图形级别的 Artist,它附加到 ScalarMappable(它们从中获取关于 norm 和 colormap 的信息),并且通常会从父 Axes 中占用空间.Colorbars 的位置可能很复杂:有关详细信息,请参阅 放置颜色条 .你还可以使用 extend 关键字更改 colorbars 的外观,以在末尾添加箭头,并使用 shrink 和 aspect 来控制大小.最后,colorbar 将具有适合于 norm 的默认定位器和格式化程序.这些可以像其他 Axis 对象一样进行更改.

Working with multiple Figures and Axes#

你可以通过多次调用 fig = plt.figure()fig2, ax = plt.subplots() 来打开多个 Figures.通过保留对象引用,你可以将 Artist 添加到任一 Figure.

可以通过多种方式添加多个 Axes,但最基本的是上面使用的 plt.subplots() .可以使用 subplot_mosaic 实现更复杂的布局,其中 Axes 对象跨越列或行.

fig, axd = plt.subplot_mosaic([['upleft', 'right'],
                               ['lowleft', 'right']], layout='constrained')
axd['upleft'].set_title('upleft')
axd['lowleft'].set_title('lowleft')
axd['right'].set_title('right')
upleft, right, lowleft

Matplotlib 具有非常复杂的工具来排列 Axes:请参阅 在 Figure 中排列多个 Axes复杂和语义图形合成(subplot_mosaic) .

更多阅读#

有关更多绘图类型,请参见 Plot typesAPI reference ,特别是 Axes API .

Total running time of the script: (0 minutes 6.453 seconds)

Gallery generated by Sphinx-Gallery