Matplotlib 3D图入门教程

Matplotlib 3D图入门教程

Matplotlib 绘制 3D 图的核心是 mpl_toolkits.mplot3d 工具包,它在 2D 绘图基础上增加了“z轴”维度,原理和 2D 绘图一致——都是通过 Figure(画布)和 Axes(绘图区域)控制,只是 3D 图的 Axes 是专门的 Axes3D 对象。

本教程从“单个子图→多个子图”逐步推进,只讲实用功能,避开复杂公式,同时解决常见坑,让新手也能快速上手。

一、基础准备(必做步骤)

1. 安装依赖

Matplotlib 本身自带 3D 功能,无需额外安装,只需确保已安装 Matplotlib 和 NumPy(生成测试数据用):

pip install matplotlib numpy

2. 导入核心库

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D  # 关键:导入3D绘图工具包

3. 核心原理(一句话搞懂)

  • 2D 图的 Axes 是平面区域,3D 图的 Axes3D 是立体空间区域,支持 x/y/z 三个轴;
  • 绘制 3D 图的关键:先创建 Figure,再在上面添加 Axes3D 子图,最后调用 ax.plot3D()/ax.scatter3D() 等 3D 专用方法绘图。

二、第一步:绘制单个3D子图(3种常用类型)

先从最基础的“单个3D图”入手,掌握 3 种高频场景:线图、散点图、曲面图。

1. 3D线图(plot3D)

适合展示“三维数据的变化趋势”(如时间-温度-湿度关系)。

示例代码:

# 1. 创建画布(和2D图一样)
fig = plt.figure(figsize=(8, 6), dpi=100)

# 2. 添加3D子图(关键:projection='3d')
ax = fig.add_subplot(111, projection='3d')  # 111=1行1列第1个子图

# 3. 生成测试数据(x/y/z三个维度)
t = np.linspace(0, 10*np.pi, 1000)  # 生成1000个均匀分布的点
x = np.sin(t)  # x轴数据
y = np.cos(t)  # y轴数据
z = t          # z轴数据(螺旋上升的高度)

# 4. 绘制3D线图(专用方法:plot3D)
ax.plot3D(
    x, y, z,          # x/y/z数据
    color='#FF6B6B',  # 线颜色
    linewidth=2,      # 线宽
    label='3D螺旋线'  # 图例标签
)

# 5. 美化设置(和2D图类似,多了z轴标签)
ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
ax.set_zlabel('Z轴', fontsize=12)  # 3D图专属:z轴标签
ax.set_title('单个3D线图示例', fontsize=14, pad=20)
ax.legend(fontsize=10)

# 6. 显示图片
plt.tight_layout()
plt.show()

效果:

一个沿 z 轴螺旋上升的 3D 线条,可拖动鼠标旋转视角查看立体效果。

2. 3D散点图(scatter3D)

适合展示“三维数据的分布”(如身高-体重-年龄关系)。

示例代码:

fig = plt.figure(figsize=(8, 6), dpi=100)
ax = fig.add_subplot(111, projection='3d')

# 生成3D随机数据(1000个点)
np.random.seed(42)  # 固定随机种子,结果一致
x = np.random.normal(0, 1, 1000)  # x轴:正态分布数据
y = np.random.normal(0, 1, 1000)  # y轴:正态分布数据
z = np.random.normal(0, 1, 1000)  # z轴:正态分布数据

# 绘制3D散点图(专用方法:scatter3D)
scatter = ax.scatter3D(
    x, y, z,
    s=30,          # 点的大小
    c=z,           # 按z轴数据着色(颜色渐变)
    cmap='viridis',# 配色方案(内置,无需手动调颜色)
    alpha=0.6,     # 透明度(避免点重叠遮挡)
    label='3D散点'
)

# 美化设置
ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
ax.set_zlabel('Z轴', fontsize=12)
ax.set_title('单个3D散点图示例(按z轴着色)', fontsize=14, pad=20)
ax.legend(fontsize=10)

# 添加颜色条(解释颜色对应的z值)
fig.colorbar(scatter, ax=ax, shrink=0.8, label='Z轴数值')

plt.tight_layout()
plt.show()

关键技巧:

  • c=z 表示“按 z 轴数值给点着色”,配合 cmap 可实现渐变效果,直观体现三维分布;
  • alpha=0.6 是 3D 散点图必备参数,避免点重叠导致看不清。

3. 3D曲面图(plot_surface)

适合展示“连续的三维曲面”(如地形高度、函数曲面 z = sin(x) + cos(y))。

示例代码:

fig = plt.figure(figsize=(8, 6), dpi=100)
ax = fig.add_subplot(111, projection='3d')

# 生成网格数据(关键:用np.meshgrid创建x/y平面网格)
x = np.linspace(-5, 5, 100)  # x轴范围:-5~5,100个点
y = np.linspace(-5, 5, 100)  # y轴范围:-5~5,100个点
X, Y = np.meshgrid(x, y)     # 生成100x100的网格(每个点对应一个(x,y)坐标)

# 定义z轴函数(曲面方程)
Z = np.sin(X) + np.cos(Y)  # 每个(x,y)对应的z值

# 绘制3D曲面图(专用方法:plot_surface)
surface = ax.plot_surface(
    X, Y, Z,
    cmap='coolwarm',  # 配色方案(冷暖渐变)
    edgecolor='none', # 隐藏网格线(让曲面更光滑)
    alpha=0.8         # 透明度
)

# 美化设置
ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
ax.set_zlabel('Z轴', fontsize=12)
ax.set_title('单个3D曲面图示例(z = sin(x) + cos(y))', fontsize=14, pad=20)

# 添加颜色条
fig.colorbar(surface, ax=ax, shrink=0.8, label='Z轴数值')

plt.tight_layout()
plt.show()

关键注意:

  • 曲面图必须用 np.meshgrid() 生成 x/y 网格(不能直接用一维数组),否则会报错;
  • edgecolor='none' 可隐藏网格线,让曲面更美观(默认显示网格线,适合看细节)。

三、第二步:绘制多个3D子图(排列布局)

和 2D 多子图逻辑完全一致,用 fig.add_subplot(nrows, ncols, index, projection='3d') 批量创建 Axes3D 对象即可。

示例代码:2行2列共4个3D子图

fig = plt.figure(figsize=(12, 10), dpi=100)  # 扩大画布,避免子图拥挤

# 生成通用测试数据
t = np.linspace(0, 10*np.pi, 1000)
x_line = np.sin(t)
y_line = np.cos(t)
z_line = t

x_scatter = np.random.normal(0, 1, 500)
y_scatter = np.random.normal(0, 1, 500)
z_scatter = np.random.normal(0, 1, 500)

x_surf = np.linspace(-5, 5, 50)
y_surf = np.linspace(-5, 5, 50)
X_surf, Y_surf = np.meshgrid(x_surf, y_surf)
Z_surf1 = np.sin(X_surf) * np.cos(Y_surf)
Z_surf2 = X_surf**2 + Y_surf**2  # 抛物面

# 子图1:3D线图(1行1列第1个)
ax1 = fig.add_subplot(2, 2, 1, projection='3d')
ax1.plot3D(x_line, y_line, z_line, color='red', linewidth=2)
ax1.set_title('子图1:3D线图', fontsize=12)
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_zlabel('Z')

# 子图2:3D散点图(1行2列第2个)
ax2 = fig.add_subplot(2, 2, 2, projection='3d')
ax2.scatter3D(x_scatter, y_scatter, z_scatter, s=20, c='blue', alpha=0.5)
ax2.set_title('子图2:3D散点图', fontsize=12)
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_zlabel('Z')

# 子图3:正弦余弦曲面(2行1列第3个)
ax3 = fig.add_subplot(2, 2, 3, projection='3d')
ax3.plot_surface(X_surf, Y_surf, Z_surf1, cmap='viridis', edgecolor='none')
ax3.set_title('子图3:sin(x)cos(y)曲面', fontsize=12)
ax3.set_xlabel('X')
ax3.set_ylabel('Y')
ax3.set_zlabel('Z')

# 子图4:抛物面(2行2列第4个)
ax4 = fig.add_subplot(2, 2, 4, projection='3d')
ax4.plot_surface(X_surf, Y_surf, Z_surf2, cmap='plasma', edgecolor='none')
ax4.set_title('子图4:x²+y²抛物面', fontsize=12)
ax4.set_xlabel('X')
ax4.set_ylabel('Y')
ax4.set_zlabel('Z')

# 调整子图间距(避免标签重叠)
plt.tight_layout()
plt.show()

布局技巧:

  • 多3D子图要扩大画布(figsize=(12,10)),否则会拥挤;
  • 每个子图的 Axes3D 对象独立,可分别设置标题、标签、样式,互不影响。

四、3D图常见问题与解决方案(避坑指南)

1. 报错:'module' object has no attribute 'Axes3D'

  • 原因:导入方式错误(旧版本 Matplotlib 导入路径不同);
  • 解决方案:用标准导入方式:
    from mpl_toolkits.mplot3d import Axes3D  # 正确
    # 避免用:import mpl_toolkits.mplot3d as Axes3D(错误)
    

2. 3D图显示为“平面”,没有立体效果

  • 原因1:忘记指定 projection='3d'(创建的是2D子图);
    • 解决:ax = fig.add_subplot(111, projection='3d')(必须加 projection='3d');
  • 原因2:数据维度不对(如曲面图用了一维数组);
    • 解决:曲面图必须用 np.meshgrid() 生成二维网格(X/Y 是 2D 数组)。

3. 子图标签/标题重叠

  • 原因:画布太小,子图间距不足;
  • 解决:① 扩大画布 figsize;② 用 plt.tight_layout() 自动调整间距;③ 缩小标签字体(fontsize=10)。

4. 3D散点图点太多,重叠看不清

  • 解决方案:① 减小点的大小(s=20);② 降低透明度(alpha=0.5);③ 抽样减少数据量(如 x = x[:500])。

5. 保存3D图时,部分区域被截断

  • 原因:plt.savefig() 默认裁剪空白,3D图的z轴可能被裁;
  • 解决方案:保存时加 bbox_inches='tight'
    fig.savefig('3d_fig.png', dpi=150, bbox_inches='tight')
    

五、核心总结(快速回顾)

  1. 3D绘图核心步骤:创建画布 → 添加 projection='3d' 的子图 → 生成3D数据 → 调用3D专用方法(plot3D/scatter3D/plot_surface);
  2. 数据要求:线图/散点图用一维数组(x/y/z),曲面图用二维网格(np.meshgrid 生成);
  3. 多子图逻辑:和2D一致,用 add_subplot(nrows, ncols, index, projection='3d') 批量创建;
  4. 关键技巧:散点图加 alpha 避免重叠,曲面图用 cmap 渐变着色,保存时加 bbox_inches='tight'
posted @ 2025-11-29 09:14  wangya216  阅读(0)  评论(0)    收藏  举报