1.4. Matplotlib:绘图¶
作者:Nicolas Rougier, Mike Müller, Gaël Varoquaux
1.4.1. 简介¶
提示
Matplotlib 可能是 Python 中最常用的二维图形库。它提供了一种快速的方式来可视化 Python 中的数据,以及以多种格式生成出版物质量的图形。我们将以交互模式探索 Matplotlib,涵盖最常见的情况。
1.4.1.1. IPython、Jupyter 和 Matplotlib 模式¶
对于交互式 Matplotlib 会话,请打开 Matplotlib 模式
- IPython 控制台:
使用 IPython 控制台时,使用
In [1]: %matplotlib
- Jupyter 笔记本:
在笔记本中,在笔记本的开头插入以下 魔法命令
%matplotlib inline
1.4.1.2. pyplot¶
提示
pyplot 为面向对象的 Matplotlib 绘图库提供了一个过程式接口。它的设计与 Matlab™ 非常相似。因此,pyplot 中大多数绘图命令都有类似参数的 Matlab™ 等效命令。重要命令将在交互式示例中解释。
import matplotlib.pyplot as plt
1.4.2. 简单绘图¶
提示
在本节中,我们希望在同一张图上绘制余弦和正弦函数。从默认设置开始,我们将逐步丰富图形,使其更美观。
第一步是获取正弦和余弦函数的数据
import numpy as np
X = np.linspace(-np.pi, np.pi, 256)
C, S = np.cos(X), np.sin(X)
X
现在是一个 NumPy 数组,包含 256 个值,范围从 到 (包含在内)。C
是余弦(256 个值),S
是正弦(256 个值)。
要运行此示例,您可以在 IPython 交互式会话中输入它们
$ ipython --matplotlib
这将带您进入 IPython 提示符
IPython 0.13 -- An enhanced Interactive Python.
? -> Introduction to IPython's features.
%magic -> Information about IPython's 'magic' % functions.
help -> Python's own help system.
object? -> Details about 'object'. ?object also works, ?? prints more.
提示
您也可以下载每个示例并使用常规 Python 运行它,但您将失去交互式数据操作功能
$ python plot_exercise_1.py
您可以通过点击相应的图形获取每个步骤的源代码。
1.4.2.1. 使用默认设置绘图¶
提示
Matplotlib 附带了一组默认设置,允许自定义各种属性。您可以控制 Matplotlib 中几乎所有属性的默认值:图形大小和 DPI、线条宽度、颜色和样式、轴、坐标轴和网格属性、文本和字体属性等等。
import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-np.pi, np.pi, 256)
C, S = np.cos(X), np.sin(X)
plt.plot(X, C)
plt.plot(X, S)
plt.show()
1.4.2.2. 实例化默认值¶
在下面的脚本中,我们实例化(并注释)了影响绘图外观的所有图形设置。
import numpy as np
import matplotlib.pyplot as plt
# Create a figure of size 8x6 inches, 80 dots per inch
plt.figure(figsize=(8, 6), dpi=80)
# Create a new subplot from a grid of 1x1
plt.subplot(1, 1, 1)
X = np.linspace(-np.pi, np.pi, 256)
C, S = np.cos(X), np.sin(X)
# Plot cosine with a blue continuous line of width 1 (pixels)
plt.plot(X, C, color="blue", linewidth=1.0, linestyle="-")
# Plot sine with a green continuous line of width 1 (pixels)
plt.plot(X, S, color="green", linewidth=1.0, linestyle="-")
# Set x limits
plt.xlim(-4.0, 4.0)
# Set x ticks
plt.xticks(np.linspace(-4, 4, 9))
# Set y limits
plt.ylim(-1.0, 1.0)
# Set y ticks
plt.yticks(np.linspace(-1, 1, 5))
# Save figure using 72 dots per inch
# plt.savefig("exercise_2.png", dpi=72)
# Show result on screen
plt.show()
1.4.2.3. 更改颜色和线条宽度¶
提示
第一步,我们希望余弦为蓝色,正弦为红色,两者的线条稍微粗一些。我们还将稍微调整图形大小,使其更宽。
...
plt.figure(figsize=(10, 6), dpi=80)
plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")
...
1.4.2.4. 设置限制¶
提示
图形的当前限制有点过于严格,我们希望留出一些空间,以便清楚地看到所有数据点。
...
plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.ylim(C.min() * 1.1, C.max() * 1.1)
...
1.4.2.5. 设置刻度¶
提示
当前的刻度并不理想,因为它们没有显示正弦和余弦的有趣值(,:math:pm pi/2)。我们将更改它们,以便它们只显示这些值。
...
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, +1])
...
1.4.2.6. 设置刻度标签¶
提示
刻度现在已正确放置,但它们的标签不够明确。我们可以猜测 3.142 是 ,但最好将其明确显示出来。当我们设置刻度值时,我们也可以在第二个参数列表中提供相应的标签。请注意,我们将使用 LaTeX 来允许对标签进行漂亮的渲染。
...
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
[r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
plt.yticks([-1, 0, +1],
[r'$-1$', r'$0$', r'$+1$'])
...
1.4.2.7. 移动脊柱¶
提示
脊柱是连接坐标轴刻度标记并标注数据区域边界的线。它们可以放置在任意位置,到目前为止,它们一直位于坐标轴的边界。我们将改变这一点,因为我们希望它们位于中间。由于有四个(顶部/底部/左侧/右侧),我们将通过将它们的 color 设置为 none 来丢弃顶部和右侧,并将底部和左侧移至数据空间坐标系中的坐标 0。
...
ax = plt.gca() # gca stands for 'get current axis'
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
...
1.4.2.8. 添加图例¶
提示
让我们在左上角添加一个图例。这只需要在 plot 命令中添加关键字参数 label(将在图例框中使用)。
...
plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-", label="sine")
plt.legend(loc='upper left')
...
1.4.2.9. 注释一些点¶
提示
让我们使用 annotate 命令注释一些有趣的点。我们选择了 值,我们希望注释正弦和余弦。我们首先在曲线上绘制一个标记以及一条直的点线。然后,我们使用 annotate 命令显示带有箭头的文本。
...
t = 2 * np.pi / 3
plt.plot([t, t], [0, np.cos(t)], color='blue', linewidth=2.5, linestyle="--")
plt.scatter([t, ], [np.cos(t), ], 50, color='blue')
plt.annotate(r'$cos(\frac{2\pi}{3})=-\frac{1}{2}$',
xy=(t, np.cos(t)), xycoords='data',
xytext=(-90, -50), textcoords='offset points', fontsize=16,
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
plt.plot([t, t],[0, np.sin(t)], color='red', linewidth=2.5, linestyle="--")
plt.scatter([t, ],[np.sin(t), ], 50, color='red')
plt.annotate(r'$sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$',
xy=(t, np.sin(t)), xycoords='data',
xytext=(+10, +30), textcoords='offset points', fontsize=16,
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
...
1.4.2.10. 魔鬼藏在细节中¶
提示
刻度标签现在由于蓝色和红色的线条而几乎不可见。我们可以使它们更大,我们也可以调整它们的属性,以便它们在半透明的白色背景上渲染。这将允许我们同时看到数据和标签。
...
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(16)
label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))
...
1.4.3. 图形、子图、轴和刻度¶
Matplotlib 中的 “图形” 指的是用户界面中的整个窗口。在这个图形中可以存在 “子图”。
提示
到目前为止,我们一直在使用隐式图形和轴创建。这对于快速绘制非常方便。我们可以使用 figure、subplot 和 axes 明确地对显示进行更多控制。虽然 subplot 将绘图排列在规则网格中,但 axes 允许在图形中自由放置。根据您的意图,两者都可能有用。我们已经使用过图形和子图,而没有显式地调用它们。当我们调用 plot 时,matplotlib 会调用 gca()
来获取当前轴,而 gca 又会调用 gcf()
来获取当前图形。如果没有,它会调用 figure()
来创建一个,严格来说,是创建一个 subplot(111)
。让我们看看细节。
1.4.3.1. 图形¶
提示
图形是 GUI 中的窗口,标题为“图形 #”。图形从 1 开始编号,与 Python 从 0 开始的正常方式相反。这显然是 MATLAB 风格。有几个参数决定了图形的外观
参数 |
默认值 |
描述 |
---|---|---|
|
|
图形编号 |
|
|
图形大小,以英寸为单位(宽度、高度) |
|
|
每英寸点数的分辨率 |
|
|
绘图背景颜色 |
|
|
绘图背景周围边缘的颜色 |
|
|
是否绘制图形框架 |
提示
默认值可以在资源文件中指定,并且大多数情况下都会使用。只有图形的编号会经常改变。
与其他对象一样,您也可以设置图形属性 setp 或使用 set_something 方法。
当您使用 GUI 时,您可以通过单击右上角的 x 来关闭图形。但是,您可以通过调用 close 以编程方式关闭图形。根据参数,它会关闭(1)当前图形(无参数)、(2)特定图形(图形编号或图形实例作为参数)或(3)所有图形("all"
作为参数)。
plt.close(1) # Closes figure 1
1.4.3.2. 子图¶
提示
使用 subplot,您可以在规则网格中排列绘图。您需要指定行数和列数以及绘图的编号。请注意,gridspec 命令是一个更强大的替代方案。
1.4.3.3. 轴¶
轴与子图非常相似,但允许将绘图放置在图形中的任何位置。因此,如果我们想要将一个小绘图放在一个大绘图中,我们就会使用轴。
1.4.3.4. 刻度¶
格式良好的刻度是出版级图形的重要组成部分。Matplotlib 提供了一个完全可配置的刻度系统。有刻度定位器来指定刻度应该出现在哪里,以及刻度格式化器来给刻度提供您想要的外观。主刻度和次刻度可以独立于彼此定位和格式化。默认情况下,次刻度不会显示,也就是说,它们只有一个空列表,因为它是 NullLocator
(见下文)。
刻度定位器¶
刻度定位器控制刻度的位置。它们设置如下
ax = plt.gca()
ax.xaxis.set_major_locator(eval(locator))
有几种定位器可以满足不同类型的需求
所有这些定位器都源自基类 matplotlib.ticker.Locator
。您可以从它派生自己的定位器。处理日期作为刻度可能特别棘手。因此,matplotlib 在 matplotlib.dates 中提供了特殊的定位器。
1.4.4. 其他类型的绘图:示例和练习¶
1.4.4.1. 常规绘图¶
从下面的代码开始,尝试重现图形,注意填充区域
提示
您需要使用 fill_between()
命令。
n = 256
X = np.linspace(-np.pi, np.pi, n)
Y = np.sin(2 * X)
plt.plot(X, Y + 1, color='blue', alpha=1.00)
plt.plot(X, Y - 1, color='blue', alpha=1.00)
单击图形以查看解决方案。
1.4.4.2. 散点图¶
从下面的代码开始,尝试重现图形,注意标记大小、颜色和透明度。
提示
颜色由 (X,Y) 的角度给出。
n = 1024
rng = np.random.default_rng()
X = rng.normal(0,1,n)
Y = rng.normal(0,1,n)
plt.scatter(X,Y)
单击图形以查看解决方案。
1.4.4.3. 条形图¶
从下面的代码开始,尝试重现图形,通过添加红色条形的标签。
提示
您需要注意文本对齐。
n = 12
X = np.arange(n)
rng = np.random.default_rng()
Y1 = (1 - X / float(n)) * rng.uniform(0.5, 1.0, n)
Y2 = (1 - X / float(n)) * rng.uniform(0.5, 1.0, n)
plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')
for x, y in zip(X, Y1):
plt.text(x + 0.4, y + 0.05, '%.2f' % y, ha='center', va='bottom')
plt.ylim(-1.25, +1.25)
单击图形以查看解决方案。
1.4.4.4. 等高线图¶
从下面的代码开始,尝试重现图形,注意颜色图(见下文的 颜色图)。
提示
您需要使用 clabel()
命令。
def f(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 -y ** 2)
n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X, Y = np.meshgrid(x, y)
plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap='jet')
C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)
单击图形以查看解决方案。
1.4.4.5. Imshow¶
从下面的代码开始,尝试重现图形,注意颜色图、图像插值和原点。
提示
您需要注意 imshow 命令中图像的 origin
,并使用 colorbar()
def f(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
n = 10
x = np.linspace(-3, 3, 4 * n)
y = np.linspace(-3, 3, 3 * n)
X, Y = np.meshgrid(x, y)
plt.imshow(f(X, Y))
单击图形以查看解决方案。
1.4.4.6. 饼图¶
从下面的代码开始,尝试重现图形,注意颜色和切片大小。
提示
您需要修改 Z。
rng = np.random.default_rng()
Z = rng.uniform(0, 1, 20)
plt.pie(Z)
单击图形以查看解决方案。
1.4.4.7. 矢量图¶
从下面的代码开始,尝试重现图形,注意颜色和方向。
提示
您需要绘制两次箭头。
n = 8
X, Y = np.mgrid[0:n, 0:n]
plt.quiver(X, Y)
单击图形以查看解决方案。
1.4.4.8. 网格¶
从下面的代码开始,尝试重现图形,注意线型。
axes = plt.gca()
axes.set_xlim(0, 4)
axes.set_ylim(0, 3)
axes.set_xticklabels([])
axes.set_yticklabels([])
单击图形以查看解决方案。
1.4.4.9. 多图¶
从下面的代码开始,尝试重现图形。
提示
您可以使用多个具有不同分区方式的子图。
plt.subplot(2, 2, 1)
plt.subplot(2, 2, 3)
plt.subplot(2, 2, 4)
单击图形以查看解决方案。
1.4.4.10. 极坐标轴¶
提示
您只需要修改 axes
行
从下面的代码开始,尝试重现图形。
plt.axes([0, 0, 1, 1])
N = 20
theta = np.arange(0., 2 * np.pi, 2 * np.pi / N)
rng = np.random.default_rng()
radii = 10 * rng.random(N)
width = np.pi / 4 * rng.random(N)
bars = plt.bar(theta, radii, width=width, bottom=0.0)
for r, bar in zip(radii, bars):
bar.set_facecolor(plt.cm.jet(r / 10.))
bar.set_alpha(0.5)
单击图形以查看解决方案。
1.4.4.11. 3D 图形¶
从下面的代码开始,尝试重现图形。
提示
您需要使用 contourf()
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)
X = np.arange(-4, 4, 0.25)
Y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='hot')
单击图形以查看解决方案。
1.4.4.12. 文本¶
尝试从头开始做同样的事情!
提示
看看 matplotlib logo。
单击图形以查看解决方案。
1.4.5. 超越本教程¶
Matplotlib 得益于广泛的文档以及庞大的用户和开发者社区。以下是几个感兴趣的链接
1.4.5.1. 教程¶
1.4.5.2. Matplotlib 文档¶
1.4.5.3. 代码文档¶
代码有很好的文档记录,您可以从 Python 会话中快速访问特定的命令
>>> import matplotlib.pyplot as plt
>>> help(plt.plot)
Help on function plot in module matplotlib.pyplot:
plot(*args: ...) -> 'list[Line2D]'
Plot y versus x as lines and/or markers.
Call signatures::
plot([x], y, [fmt], *, data=None, **kwargs)
plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
...
1.4.5.4. 图库¶
matplotlib 图库 在您搜索如何渲染给定图形时也非常有用。每个示例都附带源代码。
1.4.5.5. 邮件列表¶
1.4.6. 快速参考¶
以下是一组表格,显示了主要属性和样式。
1.4.6.1. 线属性¶
属性 |
描述 |
外观 |
---|---|---|
alpha (或 a) |
0-1 范围内的 alpha 透明度 |
|
antialiased |
True 或 False - 使用抗锯齿渲染 |
|
color (或 c) |
matplotlib 颜色参数 |
|
linestyle (或 ls) |
参见 线属性 |
|
linewidth (或 lw) |
浮点数,线宽,以磅为单位 |
|
solid_capstyle |
实线端点样式 |
|
solid_joinstyle |
实线连接样式 |
|
dash_capstyle |
虚线端点样式 |
|
dash_joinstyle |
虚线连接样式 |
|
标记 |
参见 标记 |
|
标记边框宽度 (mew) |
标记符号周围的线宽 |
|
标记边框颜色 (mec) |
使用标记时的边框颜色 |
|
标记填充颜色 (mfc) |
使用标记时的填充颜色 |
|
标记大小 (ms) |
标记的大小,以点为单位 |
1.4.6.2. 线型¶
1.4.6.3. 标记¶
1.4.6.4. 颜色图¶
所有颜色图都可以通过附加 _r
来反转。例如,gray_r
是 gray
的反转。
如果您想了解更多关于颜色图的信息,请查看 matplotlib 中关于颜色图的文档。
1.4.7. 完整代码示例¶
1.4.7.1. Matplotlib 代码示例¶
这里示例仅与本章中提到的要点相关。matplotlib 文档附带了一个更全面的 画廊。