Nemo
Nemo
使用 Matplotlib 绘制 2D 和 3D 图形
使用 Matplotlib 绘制 2D 和 3D 图形

介绍

Matplotlib 是支持 Python 语言的开源绘图库,因为其支持丰富的绘图类型、简单的绘图方式以及完善的接口文档,深受 Python 工程师、科研学者、数据工程师等各类人士的喜欢。

知识点

  • 图名称、坐标轴名称、图例
  • 线型、颜色、透明度
  • 画布网格、坐标轴范围
  • 其他 2D 图形
  • 3D 图形

Matplotlib 面向对象 API

导入模块:

from matplotlib import pyplot as plt

使用 NumPy 生成随机数据:

"""使用 NumPy 生成随机数据
"""
import numpy as np

x = np.linspace(0, 10, 20)
y = x * x + 2

1.绘图:

fig = plt.figure() # 新建图形对象

axes = fig.add_axes([0.5, 0.1, 0.8, 0.8]) 
# 控制画布的左, 下, 宽度, 高度 (从 0 到 1)

axes.plot(x, y, 'r')

输出:

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20002.jpg

重点:
上面的绘图代码中,你可能会对 figureaxes 产生疑问。Matplotlib 的 API 设计的非常符合常理,在这里,figure 相当于绘画用的画板,而 axes 则相当于铺在画板上的画布。我们将图像绘制在画布上,于是就有了 plotset_xlabel 等操作。

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20003.jpg

方法 1:plt.subplots绘制子图

fig, axes = plt.subplots(nrows=1, ncols=2)  # 子图为 1 行,2 列

for ax in axes:
    ax.plot(x, y, 'r')

输出:
https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20004.jpg

还能将一张图绘制在另一张图的内部

fig = plt.figure() # 新建画板

axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # 大画布
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) # 小画布

# 大画布
axes1.plot(x, y, 'r')

# 小画布
axes2.plot(y, x, 'g')

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20005.jpg

Tips:
上面的绘图代码中,你可能学会了使用 add_axes() 方法向我们设置的画板 figure 中添加画布 axes。在 Matplotlib 中,还有一种添加画布的方式,那就是plt.subplots()它和 axes 都等同于画布

方法 2:==使用 plt.subplots() 添加画布==

fig, axes = plt.subplots()

axes.plot(x, y, 'r')

输出:
https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20006.jpg

Matplotlib 绘图非常灵活,我们还可以使用 add_subplot 添加画布,使用 plt 完成绘图。

方法 3:使用 add_subplot() 添加画布

fig = plt.figure() # 新建图形对象

fig.add_subplot()

plt.plot(x, y, 'r')

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20007.jpg

对于上面提到的 3 种添加画布的方法,你可能觉得有些杂乱。一般情况下,只需要熟悉其中的一种即可,这里比较推荐使用 plt.subplots(),而下面的许多例子也将采用这种方式展开。

另外,既然我们拥有了画板和画布,我们应该也可以调整二者的尺寸,形状吧?当然!

调节画布尺寸和显示精度

fig, axes = plt.subplots(figsize=(16,9), dpi=50) # 通过 figsize 调节尺寸, dpi 调节显示精度

axes.plot(x, y, 'r')

1.2 图名称、坐标轴名称、图例

设置图标题

ax.set_title("title")

设置坐标轴名称

ax.set_xlabel("x")
ax.set_ylabel("y")

设置图例

ax.legend(["label1", "label2"])

举例如下:

绘制包含图标题、坐标轴标题以及图例的图形

fig, axes = plt.subplots()

axes.set_xlabel('x label')
axes.set_ylabel('y label')
axes.set_title('title')

axes.plot(x, x**2)
axes.plot(x, x**3)
axes.legend(["y = x**2", "y = x**3"], loc=2)

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20008.jpg

图例中的 loc 参数标记图例位置,1,2,3,4 依次代表:右上角、左上角、左下角,右下角;0 代表自适应。

==注意图例和曲线的对应顺序==

1.3 线型、颜色、透明度

设置线的颜色、透明度

fig, axes = plt.subplots()

axes.plot(x, x+1, color="red", alpha=0.5)
axes.plot(x, x+2, color="#1155dd")
axes.plot(x, x+3, color="#15cc55")

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20009.jpg

而对于线型而言,除了实线、虚线之外,还有很多丰富的线型可供选择。

设置线型

fig, ax = plt.subplots(figsize=(12,6))

# 线宽
ax.plot(x, x+1, color="blue", linewidth=0.25)
ax.plot(x, x+2, color="blue", linewidth=0.50)
ax.plot(x, x+3, color="blue", linewidth=1.00)
ax.plot(x, x+4, color="blue", linewidth=2.00)

# 虚线类型
ax.plot(x, x+5, color="red", lw=2, linestyle='-')
ax.plot(x, x+6, color="red", lw=2, ls='-.')
ax.plot(x, x+7, color="red", lw=2, ls=':')

# 虚线交错宽度
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10])

# 符号
ax.plot(x, x+ 9, color="green", lw=2, ls='--', marker='+')
ax.plot(x, x+10, color="green", lw=2, ls='--', marker='o')
ax.plot(x, x+11, color="green", lw=2, ls='--', marker='s')
ax.plot(x, x+12, color="green", lw=2, ls='--', marker='1')

# 符号大小和颜色
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+16, color="purple", lw=1, ls='-', marker='s', markersize=8, 
        markerfacecolor="yellow", markeredgewidth=2, markeredgecolor="blue")

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20010.jpg

1.4 画布网格、坐标轴范围

设置画布网格和坐标轴范围

fig, axes = plt.subplots(1, 2, figsize=(10,5))

# 显示网格
axes[0].plot(x, x**2, x, x**3, lw=2)
axes[0].grid(True)

# 设置坐标轴范围
axes[1].plot(x, x**2, x, x**3)
axes[1].set_ylim([0, 60])
axes[1].set_xlim([2, 5])

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20011.jpg

2.其他2D图形

2.1 绘制散点图(scatter)、梯步图(step)、条形图(bar)、面积图(fill_between)

n = np.array([0,1,2,3,4,5])

fig, axes = plt.subplots(1, 4, figsize=(16,5)) 
# 行列数可以简写

axes[0].scatter(x, x + 0.25*np.random.randn(len(x)))
axes[0].set_title("scatter")

axes[1].step(n, n**2, lw=2) #线宽可以简写
axes[1].set_title("step")

axes[2].bar(n, n**2, align="center", width=0.5, alpha=0.5) # width是bar的间距
axes[2].set_title("bar")

axes[3].fill_between(x, x**2, x**3, color="green", alpha=0.5)
axes[3].set_title("fill_between")

输出:

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20012.jpg

2.2 绘制雷达图

fig = plt.figure(figsize=(6,6))
ax = fig.add_axes([0.0, 0.0, .6, .6], polar=True)
t = np.linspace(0, 2 * np.pi, 100)
ax.plot(t, t, color='blue', lw=3)

输出:
https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20013.jpg

2.3 绘制直方图

n = np.random.randn(100000)
fig, axes = plt.subplots(1, 2, figsize=(12,4))

axes[0].hist(n)
axes[0].set_title("Default histogram")
axes[0].set_xlim((min(n), max(n)))

axes[1].hist(n, cumulative=True, bins=50)
axes[1].set_title("Cumulative detailed histogram")
axes[1].set_xlim((min(n), max(n)))

输出:
https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20014.jpg

2.4 绘制等高线图

# 生成示例数据
alpha = 0.7
phi_ext = 2 * np.pi * 0.5

def flux_qubit_potential(phi_m, phi_p):
    return 2 + alpha - 2 * np.cos(phi_p) * np.cos(phi_m) - alpha * np.cos(phi_ext - 2*phi_p)

phi_m = np.linspace(0, 2*np.pi, 100)
phi_p = np.linspace(0, 2*np.pi, 100)
X,Y = np.meshgrid(phi_p, phi_m)
Z = flux_qubit_potential(X, Y).T

绘图:

fig, ax = plt.subplots()

cnt = ax.contour(Z, cmap=plt.cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[0, 1, 0, 1])

输出:
https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20015.jpg

3. 3D图形

使用 Matplotlib 绘制 3D 图形的过程中,我们首先需要导入 Axes3D 类,并通过 projection='3d' 参数指定绘制 3D 图形。

3.1 绘制 3D 表面图

from mpl_toolkits.mplot3d.axes3d import Axes3D

fig = plt.figure(figsize=(14,6))

# 通过 projection='3d' 指定绘制 3D 图形
ax = fig.add_subplot(1, 2, 1, projection='3d')
ax.plot_surface(X, Y, Z, rstride=4, cstride=4, linewidth=0)

输出:
https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20016.jpg

Tips:
当我们在桌面环境中绘制 3D 图形时,是可以通过鼠标任意拖动角度的。

下面再绘制一个漂亮且复杂一些的 3D 图形。

3.2 绘制复杂一些的 3D 图

fig = plt.figure(figsize=(8,6))

ax = fig.add_subplot(1,1,1, projection='3d')

ax.plot_surface(X, Y, Z, rstride=4, cstride=4, alpha=0.25)
cset = ax.contour(X, Y, Z, zdir='z', offset=-np.pi, cmap=plt.cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='x', offset=-np.pi, cmap=plt.cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='y', offset=3*np.pi, cmap=plt.cm.coolwarm)

ax.set_xlim3d(-np.pi, 2*np.pi)
ax.set_ylim3d(0, 3*np.pi)
ax.set_zlim3d(-np.pi, 2*np.pi)

https://essay-1256185664.cos.ap-guangzhou.myqcloud.com/%E5%8D%9A%E6%96%87%E9%85%8D%E5%9B%BE/19-5-9_%E4%BD%BF%E7%94%A8%20Matplotlib%20%E7%BB%98%E5%88%B6%202D%20%E5%92%8C%203D%20%E5%9B%BE%E5%BD%A2/%E5%9B%BE%E5%83%8F%20017.jpg

Nemo版权所有丨如未注明,均为原创丨本网站采用BY-NC-SA协议进行授权,转载请注明转自:https://kanghaov.com/51.html
https://secure.gravatar.com/avatar/9fd8359b8faa6f7789f9623ba6041e4a?s=256&d=identicon&r=g

kanghaov

文章作者

推荐文章

发表评论

textsms
account_circle
email

Nemo

使用 Matplotlib 绘制 2D 和 3D 图形
介绍 Matplotlib 是支持 Python 语言的开源绘图库,因为其支持丰富的绘图类型、简单的绘图方式以及完善的接口文档,深受 Python 工程师、科研学者、数据工程师等各类人士的喜欢。 知识…
扫描二维码继续阅读
2019-05-09