Matplotlib的3D功能通过mpl_toolkits.mplot3d模块实现。
1. 基本设置
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np # 创建3D坐标轴 fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d')
2. 三维散点图
# 生成数据
np.random.seed(42)
n = 100
x = np.random.randn(n)
y = np.random.randn(n)
z = np.random.randn(n)
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 绘制散点图
scatter = ax.scatter(x, y, z, c=z, cmap='viridis', s=50, alpha=0.8)
# 添加标签和标题
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
ax.set_title('三维散点图')
# 添加颜色条
plt.colorbar(scatter, ax=ax, label='Z值')
plt.show()3. 三维线图
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 生成螺旋线数据
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
# 绘制线图
ax.plot(x, y, z, 'b-', linewidth=2, label='螺旋线')
ax.scatter(x[::10], y[::10], z[::10], c='red', s=50)
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
ax.set_title('三维线图 - 螺旋线')
ax.legend()
plt.show()4. 三维曲面图
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
# 生成网格数据
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
# 定义曲面函数 (Rastrigin函数)
Z = (X**2 - 10 * np.cos(2 * np.pi * X)) + \
(Y**2 - 10 * np.cos(2 * np.pi * Y)) + 20
# 绘制曲面
surf = ax.plot_surface(X, Y, Z, cmap='coolwarm',
alpha=0.8, antialiased=True)
# 添加等高线投影
ax.contour(X, Y, Z, 10, zdir='z', offset=Z.min(),
cmap='coolwarm', alpha=0.5)
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
ax.set_title('三维曲面图')
plt.colorbar(surf, ax=ax, shrink=0.5, aspect=10)
plt.show()5. 三维柱状图
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
# 生成数据
x = np.arange(5)
y = np.arange(5)
xpos, ypos = np.meshgrid(x, y)
xpos = xpos.flatten()
ypos = ypos.flatten()
zpos = np.zeros_like(xpos)
# 柱子的高度
dx = dy = 0.4 * np.ones_like(zpos)
dz = np.random.rand(25)
# 绘制柱状图
colors = plt.cm.viridis(dz / dz.max())
ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=colors,
shade=True, alpha=0.8)
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
ax.set_title('三维柱状图')
plt.show()6. 三维等高线图
fig = plt.figure(figsize=(14, 6))
# 创建两个子图
ax1 = fig.add_subplot(121, projection='3d')
ax2 = fig.add_subplot(122, projection='3d')
# 生成数据
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2)) * np.cos(2*np.pi*X) * np.cos(2*np.pi*Y)
# 子图1:3D等高线
ax1.plot_surface(X, Y, Z, cmap='viridis', alpha=0.6)
ax1.contour(X, Y, Z, 20, zdir='z', offset=Z.min(),
cmap='coolwarm', linewidths=1)
ax1.set_title('3D曲面+等高线投影')
# 子图2:3D线框
ax2.plot_wireframe(X, Y, Z, rstride=5, cstride=5,
color='blue', linewidth=0.5)
ax2.contour(X, Y, Z, 15, zdir='z', offset=Z.min(),
colors='red', linewidths=1)
ax2.set_title('3D线框+等高线投影')
for ax in [ax1, ax2]:
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
plt.tight_layout()
plt.show()7. 交互式视图控制
from matplotlib import animation
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 生成球形数据
u = np.linspace(0, 2 * np.pi, 50)
v = np.linspace(0, np.pi, 50)
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
# 绘制球体
ax.plot_surface(x, y, z, color='lightblue', alpha=0.6)
ax.set_box_aspect([1,1,1]) # 保持等比例
# 设置初始视角
ax.view_init(elev=20, azim=30)
def rotate(angle):
ax.view_init(elev=20, azim=angle)
# 创建动画
ani = animation.FuncAnimation(fig, rotate, frames=np.arange(0, 360, 2),
interval=50)
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')
ax.set_title('可旋转的3D球体')
# 保存动画
# ani.save('3d_rotation.gif', writer='pillow', fps=20)
plt.show()8. 实用技巧
# 多个子图的3D图形
fig = plt.figure(figsize=(15, 10))
# 创建4个子图
for i in range(4):
ax = fig.add_subplot(2, 2, i+1, projection='3d')
# 生成不同的函数
x = np.linspace(-3, 3, 50)
y = np.linspace(-3, 3, 50)
X, Y = np.meshgrid(x, y)
if i == 0:
Z = np.sin(np.sqrt(X**2 + Y**2))
title = '波纹曲面'
cmap = 'plasma'
elif i == 1:
Z = X**2 - Y**2
title = '马鞍面'
cmap = 'coolwarm'
elif i == 2:
Z = np.exp(-(X**2 + Y**2))
title = '高斯曲面'
cmap = 'viridis'
else:
Z = np.cos(X) * np.sin(Y)
title = '周期曲面'
cmap = 'RdYlBu'
# 绘制
surf = ax.plot_surface(X, Y, Z, cmap=cmap, alpha=0.8)
ax.set_title(title)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# 设置视角
ax.view_init(elev=30, azim=45*i)
plt.tight_layout()
plt.show()主要参数说明:
视角控制:
ax.view_init(elev=30, azim=45)– 设置仰角和方位角elev– 仰角(上下看的角度)azim– 方位角(左右旋转的角度)
坐标轴设置:
ax.set_xlim3d(left, right)ax.set_ylim3d(bottom, top)ax.set_zlim3d(zmin, zmax)ax.set_box_aspect([1,1,1])– 保持等比例
图形属性:
alpha– 透明度rstride,cstride– 曲面网格步长linewidth– 线宽antialiased– 抗锯齿
Matplotlib的3D功能适合基本的三维可视化,但对于复杂的三维场景或大数据集,建议考虑:
- Mayavi – 更强大的3D可视化库
- Plotly – 交互式3D可视化
- PyVista – 专业级3D可视化
