
本文详解如何将具有不规则x坐标(每行x长度相同但数值不同)的二维散点型数据,通过Pandas重排与插值预处理,转换为适用于plt.contourf或pcolormesh的规则网格,实现高质量等高线/热力图可视化。
本文详解如何将具有不规则x坐标(每行x长度相同但数值不同)的二维散点型数据,通过pandas重排与插值预处理,转换为适用于`plt.contourf`或`pcolormesh`的规则网格,实现高质量等高线/热力图可视化。
在科学计算与物理建模中,常遇到“非结构化二维数据”:y方向离散(如10个不同参数 r_primes),而每个y对应一组独立采样的x值(如50个能量本征值 eigenenergies),z则为对应位置的物理量(如 dc_intensities)。此时直接调用 np.meshgrid(x, y) 会失败——因为 x 是 (10, 50) 的不规则二维数组,而非一维向量;传统 contourf 要求输入为形状一致的规则网格(X, Y, Z 均为 (M, N))。
核心思路是:将原始“逐行定义”的散点数据,统一映射到一个共享的、排序后的规则坐标系中。以下是推荐的三步稳健流程:
✅ 步骤1:数据展平与结构化
将原始 (N, M) 形状的 x, y, z 展平为一维,并构造带坐标的长格式 DataFrame:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 假设已加载数据(如 pickle)
with open('data.pkl', 'rb') as f:
data_loaded = pickle.load(f)
x, y, z = data_loaded['eigenenergies'], data_loaded['r_primes'], data_loaded['dc_intensities']
# 确保维度一致:假设每行 x 长度均为 dim
dim = len(x[0]) # 例如 50
X = np.array(x) # shape: (10, 50)
Y = np.array(y) # shape: (10,)
Z = np.array(z) # shape: (10, 50)
# 展平并构建长格式表:每行代表一个 (x_i, y_j, z_ij) 三元组
df = pd.DataFrame({
'x': X.flatten(), # 所有 x 坐标(500 个)
'y': np.repeat(Y, dim), # 对应 y 坐标(重复 50 次/行 → 共 500 个)
'z': Z.flatten() # 对应 z 值
})✅ 步骤2:网格重建(pivot + meshgrid)
利用 pivot_table 按唯一 x/y 值自动对齐数据,生成规则二维矩阵:
# 透视表:以 x 为行索引、y 为列索引,填充 z 值 # 注意:此处 index='x' 表示 x 是横轴(通常为水平方向),columns='y' 为纵轴 pivot_df = df.pivot_table(index='x', columns='y', values='z', aggfunc='mean') # 提取排序后的唯一坐标(确保单调性,避免绘图错位) X_unique = pivot_df.index.to_numpy() # shape: (M,) —— x 坐标(升序) Y_unique = pivot_df.columns.to_numpy() # shape: (N,) —— y 坐标(升序) # 构造匹配的 meshgrid(注意顺序:X 对应列,Y 对应行) X_grid, Y_grid = np.meshgrid(X_unique, Y_unique) # X_grid.shape = Y_grid.shape = (N, M) Z_grid = pivot_df.values.T # .T 确保 Z_grid[i,j] 对应 (X_grid[i,j], Y_grid[i,j]) # 清理缺失值(pivot 可能引入 NaN) Z_grid = np.nan_to_num(Z_grid, nan=0.0) # 或使用插值:scipy.interpolate.griddata
✅ 步骤3:绘制与优化
使用 contourf 或 pcolormesh 绘图,并设置关键参数:
plt.figure(figsize=(8, 6))
contour = plt.contourf(
X_grid, Y_grid, Z_grid,
levels=50, # 控制等高线密度(过少则阶梯化,过多则渲染慢)
cmap='viridis', # 推荐 perceptually uniform colormap
extend='both' # 自动处理超出 vmin/vmax 的值
)
plt.colorbar(contour, label=r'Intensity', fraction=0.025, pad=0.04)
plt.xlabel(r'$\Delta E \; [|J|]$', fontsize=14)
plt.ylabel(r'$r^\prime \; [\AA]$', fontsize=14)
plt.title('DC Intensity Contour', fontsize=16)
plt.tight_layout()
plt.show()⚠️ 注意事项与进阶建议
- 坐标方向验证:pivot_table(index='x', columns='y') 默认 x 为行(垂直轴)、y 为列(水平轴),但 contourf(X, Y, Z) 要求 X 和 Y 为 列主序 网格。因此务必用 .T 转置 Z 并检查 X_grid.shape == Y_grid.shape == Z_grid.shape。
-
缺失值处理:若原始数据在某些 (x,y) 组合无观测值,pivot_table 会填 NaN。除 nan_to_num 外,更优方案是使用 scipy.interpolate.griddata 进行双线性插值:
from scipy.interpolate import griddata xi, yi = np.linspace(X_unique.min(), X_unique.max(), 200), \ np.linspace(Y_unique.min(), Y_unique.max(), 100) Xi, Yi = np.meshgrid(xi, yi) Zi = griddata((df['x'], df['y']), df['z'], (Xi, Yi), method='cubic') - 性能提示:当 x 各行采样点差异较大时,pivot_table 可能产生稀疏网格。可先对 x 进行统一重采样(如 np.linspace + scipy.interpolate.interp1d),再执行上述流程,提升精度与连续性。
该方法兼顾鲁棒性与可解释性,无需手动构造复杂插值逻辑,是处理实验测量或模拟输出中典型不规则二维数据的标准化实践。

















