Python三维绘图全教程:plot3d/mesh/surf/contour函数实战(附完整代码)

139 阅读8分钟

在数据可视化、科学计算和工程分析中,三维绘图是展示空间数据、函数关系的重要手段。MATLAB中常用plot3()mesh()surf()contour()实现三维绘图,而Python的matplotlib库通过mplot3d模块完美复刻了这些功能(对应plot3D()plot_wireframe()plot_surface()contour3D()等函数)。

一、准备工作:安装依赖与基础环境搭建

1.1 安装必备库

Python三维绘图依赖matplotlib(绘图核心)和numpy(数值计算与数据生成),执行以下命令安装:

pip install matplotlib numpy

1.2 导入模块与创建3D绘图环境

matplotlibmplot3d模块是实现3D绘图的核心,需先导入并创建3D坐标轴对象:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d  # 必须导入,启用3D绘图功能

# 创建画布与3D坐标轴
fig = plt.figure(figsize=(8, 6))  # 设置画布大小
ax = plt.axes(projection='3d')    # 指定投影为3D
plt.show()  # 显示绘图窗口

关键说明projection='3d'是创建3D绘图环境的核心参数,缺少则默认生成2D坐标轴。

二、3D线图(对应MATLAB plot3()):ax.plot3D()

plot3D()是MATLABplot3()的Python等价函数,用于绘制三维空间中的折线/曲线,适合展示一维数据的空间轨迹(如运动路径、螺旋线)。

2.1 基本语法

ax.plot3D(xdata, ydata, zdata, color, linewidth, label, ...)
  • xdata/ydata/zdata:三维坐标数据(需为等长数组);
  • color:线条颜色(如'red''#FF5733');
  • linewidth:线条宽度;
  • label:图例标签。

2.2 实战案例:绘制三维螺旋线

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

# 生成数据:螺旋线参数方程
theta = np.linspace(0, 10 * np.pi, 1000)  # 角度范围
x = np.sin(theta) * np.cos(theta)         # x坐标
y = np.sin(theta) * np.sin(theta)         # y坐标
z = np.linspace(0, 5, 1000)               # z坐标

# 创建3D绘图环境
fig = plt.figure(figsize=(8, 6))
ax = plt.axes(projection='3d')

# 绘制3D线图
ax.plot3D(x, y, z, color='blue', linewidth=2, label='3D螺旋线')

# 设置坐标轴标签与图例
ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
ax.set_zlabel('Z轴', fontsize=12)
ax.legend(loc='upper right')
ax.set_title('三维螺旋线(plot3D实现)', fontsize=14)

plt.show()

结果解读:代码通过参数方程生成螺旋线的三维坐标,plot3D()将其连接为连续曲线,可清晰看到曲线在XY平面呈螺旋状,沿Z轴线性上升。

2.3 拓展:绘制三维随机折线

# 生成随机三维数据
np.random.seed(42)  # 固定随机种子
x = np.cumsum(np.random.randn(100))
y = np.cumsum(np.random.randn(100))
z = np.cumsum(np.random.randn(100))

# 绘图
fig = plt.figure(figsize=(8, 6))
ax = plt.axes(projection='3d')
ax.plot3D(x, y, z, color='green', marker='o', markersize=3, label='随机折线')

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.legend()
ax.set_title('三维随机折线')
plt.show()

技巧:添加marker参数可显示数据点,便于观察离散数据的空间分布。

三、3D网格图(对应MATLAB mesh()):ax.plot_wireframe()

plot_wireframe()对应MATLAB的mesh(),用于绘制三维网格面,仅显示曲面的网格线条,适合展示函数的空间轮廓,不填充颜色。

3.1 核心步骤:生成网格数据

绘制二维函数z=f(x,y)z = f(x, y)的网格图,需先通过np.meshgrid()生成X、Y平面的网格坐标:

# 生成x、y轴的一维数据
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
# 生成网格坐标矩阵
X, Y = np.meshgrid(x, y)

说明np.meshgrid()将一维的x、y转换为二维矩阵,使每个(X[i,j],Y[i,j])(X[i,j], Y[i,j])对应平面上的一个点。

3.2 基本语法

ax.plot_wireframe(X, Y, Z, rstride, cstride, color, linewidth, ...)
  • rstride/cstride:行/列步长(数值越大,网格越稀疏);
  • Z:与X、Y对应的z轴数据矩阵。

3.3 实战案例:绘制正弦曲面网格图

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

# 1. 生成网格数据
x = np.linspace(-np.pi, np.pi, 30)
y = np.linspace(-np.pi, np.pi, 30)
X, Y = np.meshgrid(x, y)
# 2. 定义三维函数:z = sin(X) + cos(Y)
Z = np.sin(X) + np.cos(Y)

# 3. 创建3D绘图环境
fig = plt.figure(figsize=(10, 8))
ax = plt.axes(projection='3d')

# 4. 绘制网格图
ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2, color='purple', linewidth=1)

# 5. 设置标签与标题
ax.set_xlabel('X (rad)', fontsize=12)
ax.set_ylabel('Y (rad)', fontsize=12)
ax.set_zlabel('Z', fontsize=12)
ax.set_title('三维正弦曲面网格图(mesh/plot_wireframe实现)', fontsize=14)

plt.show()

参数解读rstride=2, cstride=2表示每隔2个点绘制一条网格线,若设为1则网格密集,渲染速度变慢;color统一设置网格线条颜色。

四、3D曲面图(对应MATLAB surf()):ax.plot_surface()

plot_surface()对应MATLAB的surf(),用于绘制填充颜色的三维曲面,通过颜色映射(colormap)可直观展示Z值的变化,是最常用的三维曲面可视化方法。

4.1 基本语法

ax.plot_surface(X, Y, Z, cmap, alpha, edgecolor, ...)
  • cmap:颜色映射方案(如'viridis''plasma''coolwarm');
  • alpha:透明度(0-1,1为不透明);
  • edgecolor:曲面边缘线条颜色(设为'none'则隐藏边缘)。

4.2 实战案例1:绘制抛物面曲面图

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

# 生成网格数据
x = np.linspace(-4, 4, 50)
y = np.linspace(-4, 4, 50)
X, Y = np.meshgrid(x, y)
# 抛物面函数:z = x² + y²
Z = X**2 + Y**2

# 创建绘图环境
fig = plt.figure(figsize=(10, 8))
ax = plt.axes(projection='3d')

# 绘制曲面图
surf = ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8, edgecolor='black')

# 添加颜色条(展示Z值与颜色的对应关系)
fig.colorbar(surf, ax=ax, shrink=0.6, aspect=10, label='Z值')

# 设置标签与标题
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('三维抛物面曲面图(surf/plot_surface实现)', fontsize=14)

plt.show()

结果解读:颜色从蓝到黄渐变,对应Z值从0(中心)到32(边缘)递增,颜色条清晰展示了数值与颜色的映射关系;edgecolor='black'让曲面的网格边缘更明显。

4.3 实战案例2:彩色正弦曲面(隐藏边缘)

# 复用前文的X、Y、Z数据(Z = sin(X) + cos(Y))
fig = plt.figure(figsize=(10, 8))
ax = plt.axes(projection='3d')

# 隐藏边缘的曲面图
surf = ax.plot_surface(X, Y, Z, cmap='coolwarm', alpha=0.9, edgecolor='none')

fig.colorbar(surf, ax=ax, shrink=0.6, label='Z值')
ax.set_xlabel('X (rad)')
ax.set_ylabel('Y (rad)')
ax.set_zlabel('Z')
ax.set_title('彩色正弦曲面(无边缘)', fontsize=14)

plt.show()

技巧edgecolor='none'可让曲面更平滑,适合展示连续的颜色渐变效果。

五、等高线图(对应MATLAB contour()):contour()/contour3D()

等高线图通过二维平面上的闭合曲线展示三维函数的Z值分布,分为2D等高线ax.contour())和3D等高线ax.contour3D()),对应MATLAB的contour()contour3()

5.1 2D等高线图:ax.contour()

5.1.1 基本语法

ax.contour(X, Y, Z, levels, colors, linewidths, label, ...)
  • levels:等高线层级数(或指定具体数值);
  • colors:等高线颜色;
  • linewidths:线条宽度。

5.1.2 实战案例:抛物面2D等高线

# 复用抛物面的X、Y、Z数据
fig, ax = plt.subplots(figsize=(8, 6))

# 绘制2D等高线
contour = ax.contour(X, Y, Z, levels=15, cmap='viridis', linewidths=1.5)

# 添加等高线数值标签
ax.clabel(contour, inline=True, fontsize=8, fmt='%.1f')

# 设置标签与标题
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('抛物面2D等高线图', fontsize=14)
plt.grid(True, alpha=0.3)
plt.show()

关键参数ax.clabel()用于添加等高线的数值标签,inline=True表示标签嵌入线条内部。

5.2 3D等高线图:ax.contour3D()

contour3D()将等高线绘制在三维空间的指定Z平面,保留三维空间的立体感。

5.2.1 基本语法

ax.contour3D(X, Y, Z, levels, cmap, linewidths, ...)

5.2.2 实战案例:正弦曲面3D等高线

# 复用正弦曲面的X、Y、Z数据
fig = plt.figure(figsize=(10, 8))
ax = plt.axes(projection='3d')

# 绘制3D等高线(20个层级)
ax.contour3D(X, Y, Z, levels=20, cmap='coolwarm', linewidths=1)

# 设置视角与标签
ax.view_init(elev=30, azim=60)  # 调整视角(仰角30°,方位角60°)
ax.set_xlabel('X (rad)')
ax.set_ylabel('Y (rad)')
ax.set_zlabel('Z')
ax.set_title('正弦曲面3D等高线图', fontsize=14)

plt.show()

视角调整ax.view_init(elev, azim)可手动设置绘图视角,elev为仰角(与XY平面的夹角),azim为方位角(绕Z轴的旋转角度)。

5.3 混合绘图:曲面图+3D等高线

# 抛物面数据的曲面+3D等高线混合图
fig = plt.figure(figsize=(10, 8))
ax = plt.axes(projection='3d')

# 绘制曲面(半透明)
ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.5, edgecolor='none')
# 绘制3D等高线
ax.contour3D(X, Y, Z, levels=10, cmap='viridis', linewidths=2)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('抛物面:曲面图+3D等高线', fontsize=14)
plt.show()

实战价值:混合绘图既展示了曲面的整体形态,又通过等高线清晰标注了Z值的分布,适合专业报告与论文可视化。

六、三维绘图常见技巧与问题解决

6.1 调整视角

除了ax.view_init(),还可在绘图窗口中鼠标交互调整

  • 左键拖动:旋转视角(调整azim/elev);
  • 滚轮:缩放画面;
  • 右键拖动:平移画面。

6.2 设置坐标轴范围

通过ax.set_xlim()/ax.set_ylim()/ax.set_zlim()固定坐标轴范围,避免自动缩放导致的比例失调:

ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
ax.set_zlim(-2, 2)

6.3 保存高清图片

使用plt.savefig()保存图片,设置dpi参数提高分辨率:

plt.savefig('3d_surface.png', dpi=300, bbox_inches='tight')
  • dpi=300:适合印刷/论文的高清分辨率;
  • bbox_inches='tight':裁剪空白边缘。

6.4 解决“网格/曲面渲染模糊”问题

  • 增大np.linspace()的采样点数(如从30改为50),让数据更密集;
  • 保存图片时提高dpi
  • 减少rstride/cstride的步长(设为1)。

6.5 自定义颜色映射

matplotlib内置了数十种颜色映射方案,也可自定义:

from matplotlib.colors import LinearSegmentedColormap

# 自定义从红到绿的颜色映射
colors = [(1, 0, 0), (0, 1, 0)]  # 红→绿
cmap = LinearSegmentedColormap.from_list('custom', colors, N=100)
ax.plot_surface(X, Y, Z, cmap=cmap)