matplotlib系列(4)-- 绘制三维图表

matplotlib绘制三维图表主要通过mplot3d模块实现,但由于三维图表实际上是在二维画布上展示,因此同样需要载入pyplot模块。

1、三维空间中的点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False

def plot_scatter_3d(title, x, y, z):
'''
绘制3D散点图
'''
fig = plt.figure(figsize=(16, 10), dpi= 80) # 创建一个画板
ax = Axes3D(fig)
ax.scatter(xs=x,
ys=y,
zs=z,
c='r', # 颜色
marker='o', # 点的标记
label='positive' # 标签
)

# 设置坐标轴显示以及旋转角度
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
ax.set_zlabel('z', fontsize=16)
ax.view_init(elev=10, azim=235)

plt.title(title, fontsize=22)
plt.grid(False) # 是否显示网格
ax.set_aspect('equal') # 坐标轴间比例一致
ax.legend(loc='upper left', fontsize=16)
# plt.savefig("./"+title+".png") # 保存图片
plt.show()

x = (40 - 15) * np.random.rand(100) + 15
y = (25 - 5) * np.random.rand(100) - 5
z = (15 - 4) * np.random.rand(100) + 4
plot_scatter_3d('测试图', x, y, z)

2、三维空间中的线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False

def plot_line_3d(title, x, y, z):
'''
绘制3D折线图
'''
fig = plt.figure(figsize=(16, 10), dpi= 80) # 创建一个画板
ax = Axes3D(fig)
ax.plot(xs=x,
ys=y,
zs=z,
c='r', # 颜色
label='parametric curve' # 标签
)

# 设置坐标轴显示以及旋转角度
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
ax.set_zlabel('z', fontsize=16)
ax.view_init(elev=10, azim=235)

plt.title(title, fontsize=22)
plt.grid(False) # 是否显示网格
ax.set_aspect('equal') # 坐标轴间比例一致
ax.legend(loc='upper left', fontsize=16)
# plt.savefig("./"+title+".png") # 保存图片
plt.show()

z = np.linspace(-2, 2, 100)
r = np.linspace(-2, 2, 100) ** 2 + 1
x = r * np.sin(np.linspace(-8 * np.pi, 8 * np.pi, 100)) # [-5,5]
y = r * np.cos(np.linspace(-8 * np.pi, 8 * np.pi, 100)) # [-5,5]
plot_line_3d('测试图', x, y, z)

3、三维空间中的面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False

def plot_surface_3d(title, x, y, z):
'''
绘制3D曲面图
'''
fig = plt.figure(figsize=(16, 10), dpi= 80) # 创建一个画板
ax = Axes3D(fig)
ax.plot_surface(X=x,
Y=y,
Z=z
)

# 设置坐标轴显示以及旋转角度
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
ax.set_zlabel('z', fontsize=16)
ax.view_init(elev=10, azim=235)

plt.title(title, fontsize=22)
plt.grid(False) # 是否显示网格
ax.set_aspect('equal') # 坐标轴间比例一致
# plt.savefig("./"+title+".png") # 保存图片
plt.show()

# 生成[-5,5]间隔0.25的数列,间隔越小,曲面越平滑
x = np.arange(-5, 5, 0.25)
y = np.arange(-5, 5, 0.25)
# 格点矩阵,原来的x行向量向下复制len(y)次,形成len(y)*len(x)的矩阵,即为新的x矩阵;
# 原来的y列向量向右复制len(x)次,形成len(y)*len(x)的矩阵,即为新的y矩阵;新的x矩阵和新的y矩阵shape相同
x, y = np.meshgrid(x,y)
r = np.sqrt(x ** 2 + y ** 2)
z = np.sin(r)
plot_surface_3d('测试图', x, y, z)

4、三维空间中的体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#-*- coding:utf-8 -*-
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

# 正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 正常显示负号
plt.rcParams['axes.unicode_minus']=False

def plot_body_3d(title, verts, faces):
'''
绘制3D实体图
'''
fig = plt.figure(figsize=(16, 10), dpi= 80) # 创建一个画板
ax = Axes3D(fig)

# 获得每个面的顶点
poly3d = [[verts[vert_id] for vert_id in face] for face in faces]
# 绘制顶点
x, y, z = zip(*verts)
ax.scatter(x, y, z)

# 绘制多边形面
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.3))
# 绘制多边形的边
ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.5, linestyles=':'))

# 设置坐标轴显示以及旋转角度
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
ax.set_zlabel('z', fontsize=16)
ax.view_init(elev=10, azim=235)

plt.title(title, fontsize=22)
plt.grid(False) # 是否显示网格
ax.set_aspect('equal') # 坐标轴间比例一致
# plt.savefig("./"+title+".png") # 保存图片
plt.show()

# 六面体顶点和面
verts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)]
faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [0, 3, 7, 4]]

# 四面体顶点和面
# verts = [(0, 0, 0), (1, 0, 0), (1, 1, 0), (1, 0, 1)]
# faces = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]

plot_body_3d('测试图', verts, faces)

0%