为保证所有程序可直接运行,先运行以下代码生成模拟的三维实验数据(不规则分布的XYZ散点,带噪声的非线性响应曲面)。
import numpy as npimport pandas as pdnp.random.seed(2024)# 生成不规则分布的XYZ数据点(模拟实验测量)n_points = 250x = np.random.uniform(-3, 3, n_points)y = np.random.uniform(-3, 3, n_points)# 构造一个具有双峰、一个凹陷的复杂响应曲面z = ( 8 * np.exp(-((x-1.5)**2 + (y-1)**2)/2) + # 右上前峰6 * np.exp(-((x+1.8)**2 + (y+1.2)**2)/1.5) - # 左下后峰4 * np.exp(-((x)**2 + (y)**2)/3) + # 中心凹陷1.5 * np.sin(2.5*x) * np.cos(2.0*y) + # 波动项0.4 * x + 0.3 * y ) # 线性趋势# 添加测量噪声(模拟实验误差)z += np.random.normal(0, 0.5, n_points)df_xyz = pd.DataFrame({'X': x, 'Y': y, 'Z': z})df_xyz.to_csv('三维散点数据.csv', index=False, encoding='utf-8-sig')print("数据生成完成:三维散点数据.csv(含X, Y, Z三列,共250个数据点)")本任务从基础的三维散点图入手,逐步进阶到颜色映射、大小映射、多视角设置、投影线及三维文字标注。
读取数据,使用scatter在三维坐标系中绘制散点。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3D# 学术样式设置defset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x = df['X'].valuesy = df['Y'].valuesz = df['Z'].valuesfig = plt.figure(figsize=(5.5, 4.5))ax = fig.add_subplot(111, projection='3d')sc = ax.scatter(x, y, z, s=15, c='#4472C4', alpha=0.7, edgecolors='black', linewidths=0.3)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维散点图(基础)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维散点图_基础.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维散点图_基础.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

使用projection='3d'创建三维坐标轴,scatter绘制散点。
默认视角为elev=30, azim=-60,可从不同角度观察数据分布。
散点颜色单一,大小固定,适用于初步探索数据整体结构。
将Z值(响应变量)映射为散点颜色,直观展示响应值的空间变化。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Ddefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesfig = plt.figure(figsize=(5.5, 4.5))ax = fig.add_subplot(111, projection='3d')sc = ax.scatter(x, y, z, s=20, c=z, cmap='viridis', alpha=0.8, edgecolors='black', linewidths=0.3)cbar = fig.colorbar(sc, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维散点图(Z值颜色映射)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维散点图_颜色映射.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维散点图_颜色映射.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

通过c=z将散点颜色与Z值关联,cmap='viridis'使用色盲友好渐变色。
颜色条显示Z值范围,高响应区(黄色)和低响应区(深紫)一目了然。
结合Z轴高度和颜色双重编码,增强数据可读性。
假设每个数据点带有测量置信度或权重,将散点大小与第四维变量关联。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Ddefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].values# 模拟第四维:测量精度/权重(中心区域精度高,边缘低)weights = np.exp(-(x**2 + y**2)/8) + 0.3 * np.random.rand(len(x))# 映射到散点大小(15~80)sizes = 15 + 65 * (weights - weights.min()) / (weights.max() - weights.min())fig = plt.figure(figsize=(5.5, 4.5))ax = fig.add_subplot(111, projection='3d')sc = ax.scatter(x, y, z, s=sizes, c=z, cmap='plasma', alpha=0.7, edgecolors='black', linewidths=0.3)cbar = fig.colorbar(sc, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维散点图(大小表示测量权重)', fontsize=10)# 添加大小图例(手动)import matplotlib.patches as mpatcheslegend_sizes = [0.2, 0.5, 0.9]legend_labels = ['低权重', '中权重', '高权重']handles = [mpatches.Patch(color='gray', alpha=0.6, label=f'{label}') for label in legend_labels]# 实际大小图例需要自定义,此处省略细节plt.tight_layout()plt.show()fig.savefig('三维散点图_大小映射.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维散点图_大小映射.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

散点大小反映第四维信息(如置信度、样本量),颜色仍表示Z值。
视觉上中心区域点较大,表示测量更可靠。
实际应用中可添加大小图例说明,此处限于篇幅未完整实现。
将同一数据以四个不同视角绘制在子图中,全面展示三维结构。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Ddefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesview_angles = [(30, -60), (0, -90), (90, -90), (30, 0)]titles = ['默认视角', '俯视 (X-Y)', '正视 (X-Z)', '侧视 (Y-Z)']fig = plt.figure(figsize=(8.0, 7.0))for i, (elev, azim) in enumerate(view_angles): ax = fig.add_subplot(2, 2, i+1, projection='3d') sc = ax.scatter(x, y, z, s=12, c=z, cmap='viridis', alpha=0.7, edgecolors='black', linewidths=0.2) ax.view_init(elev=elev, azim=azim) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_title(titles[i], fontsize=10)# 共享颜色条cbar_ax = fig.add_axes([0.92, 0.15, 0.02, 0.7])norm = plt.Normalize(z.min(), z.max())sm = plt.cm.ScalarMappable(cmap='viridis', norm=norm)sm.set_array([])fig.colorbar(sm, cax=cbar_ax, label='响应值 Z')plt.tight_layout(rect=[0, 0, 0.91, 1])plt.show()fig.savefig('三维散点图_多视角.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维散点图_多视角.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

四个子图从不同角度观察数据,俯视图揭示X-Y平面分布,正视图和侧视图展示Z与X、Y的关系。
共享颜色条保证色彩映射一致,便于跨子图比较。
适用于论文中需要多角度展示三维数据的情况。
在三维散点图中添加从每个点到XY、XZ、YZ平面的垂线,帮助读者准确定位空间坐标。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Ddefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')# 抽取少量点以避免过度拥挤df_sample = df.sample(n=30, random_state=42)x, y, z = df_sample['X'].values, df_sample['Y'].values, df_sample['Z'].valuesfig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')# 散点sc = ax.scatter(x, y, z, s=30, c=z, cmap='plasma', alpha=0.9, edgecolors='black', linewidths=0.5)# 绘制到XY平面的垂线(z_min为平面)z_min = ax.get_zlim()[0]for xi, yi, zi in zip(x, y, z): ax.plot([xi, xi], [yi, yi], [z_min, zi], color='gray', linestyle=':', linewidth=0.5, alpha=0.5)# 在XY平面画小圆点 ax.scatter(xi, yi, z_min, s=10, c='gray', alpha=0.5, edgecolors='none')# 绘制到XZ平面的垂线(y_min)y_min = ax.get_ylim()[0]for xi, yi, zi in zip(x, y, z): ax.plot([xi, xi], [y_min, yi], [zi, zi], color='gray', linestyle=':', linewidth=0.5, alpha=0.3)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维散点图(带投影垂线)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维散点图_投影垂线.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维散点图_投影垂线.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

灰色虚线连接散点与XY平面上的投影点,清晰展示每个点的X、Y坐标。
仅对部分点绘制垂线,避免视觉混乱。
此方法常用于展示高维数据降维后的空间分布。
本任务从基础的plot_surface曲面绘制入手,逐步进阶到插值方法对比、透明度调整、颜色映射自定义及网格线叠加。
将散点数据插值到规则网格,绘制光滑曲面。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].values# 定义规则网格xi = np.linspace(x.min(), x.max(), 50)yi = np.linspace(y.min(), y.max(), 50)Xi, Yi = np.meshgrid(xi, yi)# 线性插值Zi = griddata((x, y), z, (Xi, Yi), method='linear')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='viridis', linewidth=0, antialiased=True)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维响应曲面(线性插值)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维曲面_基础插值.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_基础插值.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

griddata将不规则散点插值到规则网格,plot_surface绘制连续曲面。
线性插值速度快,但在数据稀疏区域可能产生折痕。
颜色映射反映Z值,曲面光滑程度取决于网格分辨率。
对比线性插值与三次样条插值的效果差异。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 60)yi = np.linspace(y.min(), y.max(), 60)Xi, Yi = np.meshgrid(xi, yi)# 线性插值Zi_linear = griddata((x, y), z, (Xi, Yi), method='linear')# 三次样条插值Zi_cubic = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(10.0, 4.5))# 线性插值ax1 = fig.add_subplot(121, projection='3d')surf1 = ax1.plot_surface(Xi, Yi, Zi_linear, cmap='viridis', linewidth=0, antialiased=True)ax1.set_title('线性插值', fontsize=10)ax1.set_xlabel('X'); ax1.set_ylabel('Y'); ax1.set_zlabel('Z')# 三次样条插值ax2 = fig.add_subplot(122, projection='3d')surf2 = ax2.plot_surface(Xi, Yi, Zi_cubic, cmap='viridis', linewidth=0, antialiased=True)ax2.set_title('三次样条插值', fontsize=10)ax2.set_xlabel('X'); ax2.set_ylabel('Y'); ax2.set_zlabel('Z')# 共享颜色条cbar_ax = fig.add_axes([0.92, 0.15, 0.015, 0.7])norm = plt.Normalize(z.min(), z.max())sm = plt.cm.ScalarMappable(cmap='viridis', norm=norm)sm.set_array([])fig.colorbar(sm, cax=cbar_ax, label='响应值 Z')plt.tight_layout(rect=[0, 0, 0.91, 1])plt.show()fig.savefig('三维曲面_插值方法对比.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_插值方法对比.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

三次样条插值曲面更光滑,峰谷过渡自然,尤其在数据点之间生成连续导数。
线性插值在局部可能出现棱角,但计算更快。
实际应用中,若数据噪声较大,可先平滑再插值,或使用径向基函数插值。
将原始散点叠加在透明曲面上,展示拟合质量。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 60)yi = np.linspace(y.min(), y.max(), 60)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')# 半透明曲面surf = ax.plot_surface(Xi, Yi, Zi, cmap='viridis', alpha=0.6, linewidth=0, antialiased=True)# 叠加散点ax.scatter(x, y, z, s=15, c='red', edgecolors='black', linewidths=0.3, label='实验数据')cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('曲面拟合(透明曲面 + 原始散点)', fontsize=10)ax.legend(loc='upper left', fontsize=8)plt.tight_layout()plt.show()fig.savefig('三维曲面_透明叠加散点.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_透明叠加散点.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

曲面透明度alpha=0.6使背后的散点和坐标轴线隐约可见,增强立体感。
红色散点标记原始测量位置,偏离曲面的点表示拟合残差。
适用于展示插值或拟合结果的可靠性。
使用自定义颜色映射,并启用shade参数模拟光照。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddataimport matplotlib.colors as mcolorsdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 60)yi = np.linspace(y.min(), y.max(), 60)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')# 自定义离散色阶(11个等级)boundaries = np.linspace(z.min(), z.max(), 12)norm = mcolors.BoundaryNorm(boundaries, ncolors=256)fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='terrain', norm=norm, linewidth=0, antialiased=True, shade=True, alpha=0.9)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1, ticks=boundaries[::2])cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维曲面(离散色阶 + 光照)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维曲面_离散色阶光照.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_离散色阶光照.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

BoundaryNorm将连续值映射到离散颜色区间,使颜色条呈现阶梯状,便于分档识别。
shade=True启用默认光照,曲面明暗随角度变化,立体感增强。
地形色盘terrain适合展示具有峰谷特征的地貌式数据。
在光滑曲面上叠加黑色网格线,同时保留颜色填充,兼顾美观与结构清晰。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 1200set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 40)yi = np.linspace(y.min(), y.max(), 40)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')# 彩色曲面(无边缘线)surf = ax.plot_surface(Xi, Yi, Zi, cmap='coolwarm', linewidth=0, antialiased=True, alpha=0.9)# 叠加黑色网格线(线框图)ax.plot_wireframe(Xi, Yi, Zi, color='black', linewidth=0.3, alpha=0.5)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维曲面 + 网格线', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维曲面_叠加网格线.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_叠加网格线.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

plot_wireframe绘制黑色细线,勾勒出曲面的网格结构,便于观察曲面曲率变化。
填充颜色和网格线结合,既美观又保留了定量读取网格交点的能力。
适用于有限元后处理或需要展示网格划分的场景。
本任务将二维等高线投影到三维曲面底部平面,并逐步进阶到填充等高线、自定义投影高度、多平面投影及三维等高线绘制。
使用contour的zdir和offset参数将等高线投影到底部平面。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesmask = np.isfinite(x) & np.isfinite(y) & np.isfinite(z)x, y, z = x[mask], y[mask], z[mask]xi = np.linspace(x.min(), x.max(), 50)yi = np.linspace(y.min(), y.max(), 50)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')# 曲面surf = ax.plot_surface(Xi, Yi, Zi, cmap='viridis', alpha=0.8, linewidth=0)# 底部等高线投影z_min = np.nanmin(Zi) - 2# 偏移到曲面下方z_max = np.nanmax(Zi)ax.contour(Xi, Yi, Zi, zdir='z', offset=z_min, cmap='viridis', linewidths=0.8)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_zlim(z_min, z_max)ax.set_title('三维曲面 + 底部等高线投影', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维曲面_等高线投影_基础.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_等高线投影_基础.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:
zdir='z'指定投影方向为Z轴,offset定义投影平面高度。使用contourf绘制填充等高线投影,使底部平面呈现二维热力图效果。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 50)yi = np.linspace(y.min(), y.max(), 50)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='viridis', alpha=0.8, linewidth=0)z_min = np.nanmin(Zi) - 2# 偏移到曲面下方z_max = np.nanmax(Zi)# 填充等高线ax.contourf(Xi, Yi, Zi, zdir='z', offset=z_min, cmap='viridis', alpha=0.7, levels=15)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_zlim(z_min, z_max)ax.set_title('三维曲面 + 底部填充等高线', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维曲面_填充等高线投影.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_填充等高线投影.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:
除了底部XY平面,还在侧面(XZ和YZ平面)投影等高线,全面展示数据在各个维度的变化。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 40)yi = np.linspace(y.min(), y.max(), 40)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(7.0, 6.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='plasma', alpha=0.7, linewidth=0)# 底部XY平面投影z_min = np.nanmin(Zi) - 2# 偏移到曲面下方z_max = np.nanmax(Zi)ax.contour(Xi, Yi, Zi, zdir='z', offset=z_min, cmap='plasma', linewidths=0.6)# 侧面XZ平面投影(y为最小值)y_min = np.nanmin(Yi) - 0.5y_max = np.nanmax(Yi)ax.contour(Xi, Yi, Zi, zdir='y', offset=y_min, cmap='plasma', linewidths=0.6)# 侧面YZ平面投影(x为最小值)x_min = np.nanmin(Xi) - 0.5x_max = np.nanmax(Xi)ax.contour(Xi, Yi, Zi, zdir='x', offset=x_min, cmap='plasma', linewidths=0.6)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_xlim(x_min, x_max)ax.set_ylim(y_min, y_max)ax.set_zlim(z_min, z_max)ax.set_title('三维曲面 + 三平面等高线投影', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维曲面_三平面投影.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_三平面投影.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:
使用contour直接在三维曲面上绘制等高线(需将等高线投影到曲面表面,而非平面)。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 50)yi = np.linspace(y.min(), y.max(), 50)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='coolwarm', alpha=0.6, linewidth=0)# 在曲面上绘制等高线(提升z值微小偏移避免渲染冲突)levels = np.linspace(Zi.min(), Zi.max(), 8)ax.contour(Xi, Yi, Zi, levels=levels, colors='black', linewidths=0.8)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('三维曲面 + 曲面等高线', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维曲面_曲面等高线.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_曲面等高线.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

将三维视图与独立的二维等高线图组合在同一个Figure中,使用GridSpec布局。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatafrom matplotlib.gridspec import GridSpecdefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 50)yi = np.linspace(y.min(), y.max(), 50)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(8.0, 4.5))gs = GridSpec(1, 2, width_ratios=[1.5, 1], wspace=0.05)# 左侧:三维曲面ax1 = fig.add_subplot(gs[0], projection='3d')surf = ax1.plot_surface(Xi, Yi, Zi, cmap='viridis', linewidth=0, antialiased=True)z_min = np.nanmin(Zi)-2z_max = np.nanmax(Zi)ax1.contourf(Xi, Yi, Zi, zdir='z', offset=z_min, cmap='viridis', alpha=0.5, levels=15)ax1.set_xlabel('X')ax1.set_ylabel('Y')ax1.set_zlabel('Z')ax1.set_zlim(z_min, z_max)ax1.set_title('三维响应曲面', fontsize=10)# 右侧:二维填充等高线ax2 = fig.add_subplot(gs[1])cf = ax2.contourf(Xi, Yi, Zi, levels=20, cmap='viridis')ax2.contour(Xi, Yi, Zi, levels=8, colors='black', linewidths=0.4)ax2.set_xlabel('X')ax2.set_ylabel('Y')ax2.set_aspect('equal')ax2.set_title('二维等高线图', fontsize=10)# 共享颜色条cbar_ax = fig.add_axes([0.92, 0.15, 0.015, 0.7])fig.colorbar(cf, cax=cbar_ax, label='响应值 Z')plt.tight_layout(rect=[0, 0, 0.91, 1])plt.show()fig.savefig('三维曲面_组合二维等高线.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维曲面_组合二维等高线.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:
本任务聚焦三维坐标轴的美化与物理比例校正,包括等比例缩放、刻度格式化、标签旋转、背景样式及多子图统一比例。
使用set_box_aspect使X、Y、Z三个轴的单位长度在屏幕上相等。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 40)yi = np.linspace(y.min(), y.max(), 40)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='viridis', linewidth=0, alpha=0.9)# 设置等比例(X:Y:Z = 1:1:1)ax.set_box_aspect([1, 1, 1])cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X (mm)')ax.set_ylabel('Y (mm)')ax.set_zlabel('Z (μm)')ax.set_title('三维曲面(等比例坐标轴)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维坐标轴_等比例.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维坐标轴_等比例.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

set_box_aspect([1,1,1])强制三个轴在屏幕上的物理长度相等,避免因数据范围不同导致的扭曲。[1,1,2])。当X、Y、Z数据范围差异较大时,可设置比例使视觉效果平衡,同时标注物理单位。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].values# 模拟物理尺寸:X范围6,Y范围6,Z范围~15,希望视觉上Z轴压缩一点xi = np.linspace(x.min(), x.max(), 40)yi = np.linspace(y.min(), y.max(), 40)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='viridis', linewidth=0, alpha=0.9)# 计算各轴数据范围x_range = x.max() - x.min()y_range = y.max() - y.min()z_range = z.max() - z.min()# 设置比例:让Z轴视觉上略短(如Z轴范围为X的2倍,但视觉比例设为1:1:0.8)ax.set_box_aspect([1, 1, 0.8 * z_range / x_range])cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)ax.set_xlabel('X (mm)')ax.set_ylabel('Y (mm)')ax.set_zlabel('Z (μm)')ax.set_title('三维曲面(自定义视觉比例)', fontsize=10)plt.tight_layout()plt.show()fig.savefig('三维坐标轴_自定义比例.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维坐标轴_自定义比例.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

box_aspect,可灵活控制各轴在屏幕上的长度比例。使用tick_params和set_xticklabels优化刻度显示,如添加单位、旋转长标签。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 40)yi = np.linspace(y.min(), y.max(), 40)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='coolwarm', linewidth=0, alpha=0.9)# 自定义刻度:保留2位小数,并添加单位符号ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda val, pos: f'{val:.1f} m'))ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda val, pos: f'{val:.1f} m'))ax.zaxis.set_major_formatter(plt.FuncFormatter(lambda val, pos: f'{val:.1f} Pa'))# 调整刻度标签字体大小和颜色ax.tick_params(axis='both', labelsize=8, colors='#333333')# 旋转X轴标签(3D中需谨慎,可能重叠)for label in ax.get_xticklabels(): label.set_rotation(20)ax.set_xlabel('X (m)', fontsize=9, labelpad=8)ax.set_ylabel('Y (m)', fontsize=9, labelpad=8)ax.set_zlabel('压力 (Pa)', fontsize=9, labelpad=8)ax.set_title('自定义刻度与标签样式', fontsize=10)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.12)cbar.ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda val, pos: f'{val:.1f}'))cbar.set_label('压力 (Pa)', fontsize=9)plt.tight_layout()plt.show()fig.savefig('三维坐标轴_刻度格式化.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维坐标轴_刻度格式化.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

FuncFormatter自定义刻度标签格式,可添加单位、控制小数位数。去除三维坐标轴的背景面板和网格线,仅保留坐标轴线和标签,获得极简视觉效果。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 40)yi = np.linspace(y.min(), y.max(), 40)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')fig = plt.figure(figsize=(6.0, 5.0))ax = fig.add_subplot(111, projection='3d')surf = ax.plot_surface(Xi, Yi, Zi, cmap='plasma', linewidth=0, alpha=0.9)# 移除背景面板(设为白色或透明)ax.xaxis.pane.fill = Falseax.yaxis.pane.fill = Falseax.zaxis.pane.fill = False# 移除网格线ax.grid(False)# 可保留坐标轴线ax.xaxis.line.set_color('black')ax.yaxis.line.set_color('black')ax.zaxis.line.set_color('black')ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')ax.set_title('极简风格三维曲面', fontsize=10)cbar = fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, pad=0.1)cbar.set_label('响应值 Z', fontsize=9)plt.tight_layout()plt.show()fig.savefig('三维坐标轴_极简风格.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维坐标轴_极简风格.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:

pane.fill = False使三个坐标平面透明,仅显示坐标轴线。grid(False)移除网格线,画面更加干净。在多个三维子图中,设置相同的视角、坐标轴比例和范围,确保可比较性。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.interpolate import griddatadefset_academic_style(): plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['font.size'] = 9 plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.linewidth'] = 1.0 plt.rcParams['xtick.major.width'] = 1.0 plt.rcParams['ytick.major.width'] = 1.0 plt.rcParams['xtick.major.size'] = 3.5 plt.rcParams['ytick.major.size'] = 3.5 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' plt.rcParams['legend.frameon'] = False plt.rcParams['pdf.fonttype'] = 42 plt.rcParams['savefig.dpi'] = 300set_academic_style()df = pd.read_csv('三维散点数据.csv')x, y, z = df['X'].values, df['Y'].values, df['Z'].valuesxi = np.linspace(x.min(), x.max(), 35)yi = np.linspace(y.min(), y.max(), 35)Xi, Yi = np.meshgrid(xi, yi)Zi = griddata((x, y), z, (Xi, Yi), method='cubic')# 模拟不同平滑程度的曲面(改变插值方法或平滑参数)Zi2 = griddata((x, y), z, (Xi, Yi), method='linear')Zi3 = griddata((x, y), z, (Xi, Yi), method='nearest')data_list = [(Zi, 'cubic'), (Zi2, 'linear'), (Zi3, 'nearest')]fig = plt.figure(figsize=(12.0, 4.0))for i, (Z_data, method) in enumerate(data_list): ax = fig.add_subplot(1, 3, i+1, projection='3d') surf = ax.plot_surface(Xi, Yi, Z_data, cmap='viridis', linewidth=0, alpha=0.9) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_title(f'插值方法: {method}', fontsize=10)# 统一视角 ax.view_init(elev=25, azim=-60)# 统一坐标轴范围 ax.set_xlim(x.min(), x.max()) ax.set_ylim(y.min(), y.max()) ax.set_zlim(z.min()-1, z.max()+1)# 统一比例 ax.set_box_aspect([1, 1, 0.8])# 共享颜色条cbar_ax = fig.add_axes([0.92, 0.15, 0.015, 0.7])norm = plt.Normalize(z.min(), z.max())sm = plt.cm.ScalarMappable(cmap='viridis', norm=norm)sm.set_array([])fig.colorbar(sm, cax=cbar_ax, label='响应值 Z')plt.tight_layout(rect=[0, 0, 0.91, 1])plt.show()fig.savefig('三维坐标轴_多子图统一.pdf', bbox_inches='tight', pad_inches=0.05)fig.savefig('三维坐标轴_多子图统一.png', bbox_inches='tight', pad_inches=0.05)执行结果分析:
