备注
前往结尾 下载完整示例代码。
快速入门指南#
本教程涵盖了一些基本的使用模式和最佳实践,以帮助您开始使用 Matplotlib。
import matplotlib.pyplot as plt
import numpy as np
一个简单的例子#
Matplotlib 在 Figure
上绘制您的数据(例如,窗口、Jupyter 小部件等),每个 Figure
可以包含一个或多个 Axes
,这是一个可以以 x-y 坐标(或在极坐标图中为 theta-r,在 3D 图中为 x-y-z 等)指定点的区域。创建带有 Axes 的 Figure 的最简单方法是使用 pyplot.subplots
。然后,我们可以使用 Axes.plot
在 Axes 上绘制一些数据,并使用 show
来显示 Figure:
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.

根据您工作的环境,plt.show()
可以省略。例如,在使用 Jupyter 笔记本时,所有在代码单元中创建的图形会自动显示。
图形的部分#
以下是 Matplotlib 图形的组成部分。

Figure
#
整个图形。图形跟踪所有子 Axes
,一组'特殊'的艺术家(标题、图形图例、颜色条等),甚至嵌套的子图形。
通常,您会通过以下函数之一创建一个新的图形:
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。
更多关于图形的介绍,包括平移和缩放,请参见 图表介绍。
Axes
#
Axes 是一个附加到 Figure 上的 Artist,它包含一个用于绘制数据的区域,并且通常包括两个(或在 3D 情况下为三个):class:Axis
对象(注意 Axes 和 Axis 的区别),这些对象提供刻度和刻度标签,为 Axes 中的数据提供尺度。每个 Axes
还有一个标题(通过 set_title()
设置)、一个 x 轴标签(通过 set_xlabel()
设置)和一个 y 轴标签(通过 set_ylabel()
设置)。
Axes
方法是配置图表大部分内容(添加数据、控制轴的比例和限制、添加标签等)的主要接口。
Axis
#
这些对象设置比例和限制,并生成刻度(轴上的标记)和刻度标签(标记的标签字符串)。刻度的位置由 Locator
对象决定,刻度标签字符串由 Formatter
格式化。正确组合 Locator
和 Formatter
可以非常精细地控制刻度位置和标签。
Artist
#
基本上,图表上所有可见的内容都是一个 Artist(甚至是 Figure
、Axes
和 Axis
对象)。这包括 Text
对象、Line2D
对象、collections
对象、Patch
对象等。当图表被渲染时,所有的 Artists 都会被绘制到 画布 上。大多数 Artists 都与一个 Axes 绑定;这样的 Artist 不能被多个 Axes 共享,也不能从一个 Axes 移动到另一个 Axes。
绘图函数的输入类型#
绘图函数期望输入为 numpy.array
或 numpy.ma.masked_array
,或者是可以传递给 numpy.asarray
的对象。类似于数组('array-like')的类,如 pandas
数据对象和 numpy.matrix
,可能无法按预期工作。常见的做法是在绘图前将这些对象转换为 numpy.array
对象。例如,转换一个 numpy.matrix
b = np.matrix([[1, 2], [3, 4]])
b_asarray = np.asarray(b)
大多数方法还可以解析像 dict 这样的字符串可索引对象、结构化的 numpy 数组 或 pandas.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')

编码风格#
显式接口与隐式接口#
如上所述,使用 Matplotlib 基本上有两种方式:
显式创建图形和轴,并在其上调用方法(即“面向对象 (OO) 风格”)。
依赖于 pyplot 来隐式创建和管理 Figures 和 Axes,并使用 pyplot 函数进行绘图。
关于隐式接口和显式接口之间的权衡解释,请参见 Matplotlib 应用程序接口 (APIs)。
因此,可以使用面向对象的风格
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.

或使用 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()

(此外,还有第三种方法,适用于在GUI应用程序中嵌入Matplotlib的情况,这种方法完全放弃使用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'})

请注意,如果你想将这些作为Python包安装,或者进行任何其他自定义,你可以使用网上众多的模板之一;Matplotlib在 mpl-cookiecutter 提供了一个模板。
艺术家风格#
大多数绘图方法都有样式选项用于艺术家,这些选项可以在调用绘图方法时访问,或者通过艺术家的“设置器”访问。在下面的图中,我们手动设置了由 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(':')

颜色#
Matplotlib 接受大多数艺术家的颜色数组非常灵活;请参阅 允许的颜色定义 以获取规范列表。一些艺术家会接受多种颜色。例如,对于 scatter
绘图,标记的边缘颜色可以与内部颜色不同:
fig, ax = plt.subplots(figsize=(5, 2.7))
ax.scatter(data1, data2, s=50, facecolor='C0', edgecolor='k')

线宽、线型和标记大小#
线条宽度通常以印刷点(1 pt = 1/72 英寸)为单位,适用于有描边线条的艺术家。同样,描边线条可以有线条样式。请参阅 线条样式示例。
标记大小取决于所使用的方法。plot
以点为单位指定 markersize,通常是标记的“直径”或宽度。scatter
将 markersize 指定为大约与标记的视觉面积成正比。有一系列的 markerstyles 可用作字符串代码(参见 markers
),或者用户可以定义自己的 MarkerStyle`(参见 :doc:
/gallery/lines_bars_and_markers/marker_reference`):
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()

标注图表#
坐标轴标签和文本#
set_xlabel
, set_ylabel
, 和 set_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)

所有 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)

在这个基本示例中,xy 和 xytext 都在数据坐标中。还有许多其他坐标系可供选择——详情请参阅 注释教程 和 绘图指南注释。更多示例也可以在 标注图表 中找到。
图例#
通常我们希望用 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()

Matplotlib 中的图例在布局、位置以及它们可以表示的艺术家方面非常灵活。它们在 图例指南 中有详细讨论。
轴刻度和刻度线#
每个 Axes 有两个(或三个) Axis
对象,分别代表 x 轴和 y 轴。这些对象控制 Axes 的 比例 、刻度 定位器 和刻度 格式化器 。可以附加额外的 Axes 以显示更多的 Axis 对象。
刻度#
除了线性刻度外,Matplotlib 还提供了非线性刻度,例如对数刻度。由于对数刻度使用非常广泛,因此也有直接的方法,如 loglog
、semilogx
和 semilogy
。有多种刻度可供选择(参见 刻度 以获取其他示例)。这里我们手动设置刻度:
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)

比例设置数据值到轴上间距的映射。这在两个方向上都发生,并结合成一个*变换*,这是 Matplotlib 从数据坐标映射到轴、图形或屏幕坐标的方式。参见 变换教程。
刻度定位器和格式化器#
每个轴都有一个刻度 定位器 和 格式化器 ,它们决定了在轴对象的哪些位置放置刻度。一个简单的接口是 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')

不同的刻度可以有不同的定位器和格式化器;例如,上面的对数刻度使用 LogLocator
和 LogFormatter
。请参阅 刻度定位器 和 Tick formatters 以获取其他格式化器和定位器以及编写自己的信息。
绘制日期和字符串#
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()))

更多信息请参见日期示例(例如:日期刻度标签)
对于字符串,我们得到分类绘图(参见:绘制分类变量)。
fig, ax = plt.subplots(figsize=(5, 2.7), layout='constrained')
categories = ['turnips', 'rutabaga', 'cucumber', 'pumpkins']
ax.bar(categories, np.random.rand(len(categories)))

关于分类绘图的一个注意事项是,某些解析文本文件的方法会返回一个字符串列表,即使这些字符串都表示数字或日期。如果你传递了1000个字符串,Matplotlib会认为你指的是1000个类别,并会在你的图表中添加1000个刻度!
附加轴对象#
在一张图表中绘制不同量级的数据可能需要一个额外的y轴。这样的轴可以通过使用 twinx
来创建一个新的Axes,该Axes具有不可见的x轴和一个位于右侧的y轴(类似地,对于 twiny
也是如此)。请参见 不同尺度的图表 以获取另一个示例。
同样地,你可以添加一个 secondary_xaxis
或 secondary_yaxis
,它们的刻度与主轴不同,以不同刻度或单位表示数据。更多示例请参见 次要轴。
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 [°]')

颜色映射数据#
通常我们希望在绘图中通过颜色图中的颜色来表示第三维度。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()')

颜色映射#
这些都是从 ScalarMappable
对象派生的艺术家示例。它们都可以在 vmin 和 vmax 之间设置一个线性映射到由 cmap 指定的颜色映射。Matplotlib 有许多颜色映射可供选择(在 Matplotlib 中选择颜色表),你可以创建自己的(在 Matplotlib 中创建 Colormap)或下载为 第三方包。
标准化#
有时我们希望数据到颜色映射的非线性映射,如上面的 LogNorm
示例。我们通过向 ScalarMappable 提供 norm 参数而不是 vmin 和 vmax 来实现这一点。更多归一化方法请参见 颜色映射归一化。
颜色条#
添加 colorbar
会提供一个键,用于将颜色与基础数据关联起来。Colorbar 是图级别的艺术家,它们附着在一个 ScalarMappable 上(从中获取关于 norm 和 colormap 的信息),并且通常会从父 Axes 中窃取空间。Colorbar 的放置可能很复杂:详情请参见 放置颜色条。你还可以使用 extend 关键字在末端添加箭头,以及使用 shrink 和 aspect 来控制大小,从而改变 colorbar 的外观。最后,colorbar 将具有适合 norm 的默认定位器和格式化器。这些可以像其他 Axis 对象一样进行更改。
使用多个图和轴#
你可以通过多次调用 fig = plt.figure()
或 fig2, ax = plt.subplots()
来打开多个图形。通过保持对象引用,你可以在任意图形中添加艺术家。
可以通过多种方式添加多个轴,但最基本的是如上所述使用 plt.subplots()
。可以使用 subplot_mosaic
实现更复杂的布局,其中轴对象跨越列或行。
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')

Matplotlib 有相当复杂的工具来安排 Axes:请参见 在图形中排列多个轴 和 复杂且语义化的图形组合 (subplot_mosaic)。
更多阅读#
更多图表类型请参见 图表类型 和 API 参考,特别是 Axes API。
脚本总运行时间: (0 分钟 2.512 秒)