
本文介绍如何通过 for 循环重构重复性高的 `scatter3d` 多子图代码,统一设置坐标轴、颜色映射与视角参数,显著提升可读性与可维护性。
在使用 Matplotlib 绘制多视角 3D 散点图时,若为每个子图单独编写几乎相同的绘图逻辑(仅视角 view_init(elev, azim) 不同),不仅代码冗长,还容易因漏改某处参数导致不一致。最佳实践是将共性逻辑提取为循环体,差异化部分(如视角角度)以元组列表或函数生成方式传入。
以下是一个优化后的专业写法,支持任意数量的子图,并清晰分离「数据绘制」「视角配置」和「坐标系设置」三类操作:
import matplotlib.pyplot as plt
def plot_example(data_df):
"""
绘制四视角 3D 散点图:俯视(0°,90°)、侧视(45°,0°)、斜视1(35°,45°)、斜视2(20°,40°)
Parameters:
-----------
data_df : pandas.DataFrame
必须包含 'x', 'y', 'z' 列
"""
fig = plt.figure(figsize=(15, 15))
# 预定义各子图视角:(elev, azim)
view_angles = [(0, 90), (45, 0), (35, 45), (20, 40)]
for i, (elev, azim) in enumerate(view_angles, start=1):
ax = fig.add_subplot(2, 2, i, projection='3d')
# 统一绘图
scatter = ax.scatter3D(
data_df.x, data_df.y, data_df.z,
c=data_df.z, cmap='Blues', s=20, alpha=0.8
)
# 设置视角
ax.view_init(elev=elev, azim=azim)
# 统一标签与样式
ax.set_xlabel('x', color='red', fontsize=10)
ax.set_ylabel('y', color='red', fontsize=10)
ax.set_zlabel('z', color='red', fontsize=10)
# 统一坐标范围(关键:必须对每个 ax 单独调用)
ax.set_xlim(0, 14)
ax.set_ylim(-6, 6)
ax.set_zlim(0, 8.5)
# 可选:添加共享 colorbar(增强可读性)
cbar = fig.colorbar(scatter, ax=fig.axes, shrink=0.5, aspect=20, pad=0.1)
cbar.set_label('z value', color='red', fontsize=12)
plt.tight_layout()
plt.show()✅ 关键优化点说明:
- 避免 plt.axis() 误用:该函数仅适用于 2D 坐标系(接受 [xmin,xmax,ymin,ymax]),3D 场景中必须对每个 Axes3D 实例分别调用 set_xlim()/set_ylim()/set_zlim();
- 视角解耦:将 (elev, azim) 显式定义为元组列表,语义清晰、便于调试与扩展;
- 增强鲁棒性:添加 s(点大小)和 alpha(透明度)提升视觉层次;tight_layout() 自动优化子图间距;
- 可扩展设计:如需增加第五个视角,只需在 view_angles 中追加元组,无需新增代码块。
⚠️ 注意事项:
- 确保传入的 data_df 已正确加载且无缺失值(NaN 会导致 scatter3D 报错);
- 若数据量极大(>10⁵ 点),建议启用 antialiased=False 或降采样以提升渲染性能;
- projection='3d' 仅支持 add_subplot() 创建,不兼容 plt.subplots() 的简写形式(需显式指定 subplot_kw={'projection': '3d'})。
通过结构化循环与参数化配置,原始 60+ 行重复代码可压缩至 30 行以内,同时大幅提升逻辑一致性与后期维护效率。










