`regulargridinterpolator` 不支持含 nan 的输入数据,需改用 `griddata` 对有效点进行非结构化三次插值,并自动处理边界与空缺区域。
在科学计算与地球系统建模中,常需将规则经纬度网格(如 1°×1°)上的物理量(如温度、降水)插值到任意散点坐标(如观测站点或轨迹点)。当原始数据含大量 NaN(例如海洋区域无观测、云遮挡导致遥感缺失),scipy.interpolate.RegularGridInterpolator 的 'cubic' 方法会直接报错 ValueError: Array must not contain infs or nans.——这是因为其底层调用 make_interp_spline 要求输入值数组完全非空且有限,无法容忍任何缺失值。
而 'linear' 方法能成功运行,是因为线性插值仅依赖局部邻近点的加权平均,RegularGridInterpolator 内部会对 NaN 区域做隐式跳过与边界截断;但三次样条插值需构建全局光滑样条函数,必须基于完整、连续的规则网格,故不兼容稀疏/含缺数据。
✅ 正确解法:转向非结构化插值器 scipy.interpolate.griddata
griddata 专为“散点 → 散点”或“散点 → 规则网格”设计,天然支持从任意子集坐标-值对(即剔除 NaN 后的有效点)出发,执行 'nearest'、'linear' 或 'cubic' 插值。它不要求输入点构成规则网格,也不要求覆盖整个定义域,因此完美适配您的场景。
import numpy as np
from scipy.interpolate import griddata
# 1. 构造原始规则网格与含 NaN 数据(同问题复现逻辑)
lat0 = np.linspace(-60, -40, 20)
lon0 = np.linspace(-50, 0.0, 50)
lonG, latG = np.meshgrid(lon0, lat0)
data = np.sin(latG * lonG)
data_nan = data.copy()
data_nan[1:8, 5:12] = np.nan
data_nan[2:6, 12:20] = np.nan
# 2. 提取所有非 NaN 点的坐标与值(展平 + 过滤)
mask = ~np.isnan(data_nan)
lat_valid = latG[mask] # 1D array of valid latitudes
lon_valid = lonG[mask] # 1D array of valid longitudes
data_valid = data_nan[mask] # 1D array of corresponding values
# 3. 准备待插值的“非结构化”目标坐标(例如 2000 个随机点)
lat_q = np.random.uniform(-60, -40, 2000)
lon_q = np.random.uniform(-50, 0.0, 2000)
xi = np.column_stack((lat_q, lon_q)) # shape (2000, 2)
# 4. 执行三次样条插值(关键!)
interped_cubic = griddata(
points=(lat_valid, lon_valid), # 注意:顺序需与 xi 一致(此处为 (lat, lon))
values=data_valid,
xi=xi,
method='cubic',
fill_value=np.nan # 显式指定域外/不可插区域返回 NaN
)
# 5. 验证结果(自动包含 NaN 处理)
print(f"插值完成,共 {np.isnan(interpe
d_cubic).sum()} 个 NaN 输出")RegularGridInterpolator(..., method='cubic') 本质是规则网格专用的张量积样条,拒绝 NaN;而 griddata(..., method='cubic') 是基于 Delaunay 三角剖分的散点样条,天生适配稀疏数据。只需三步:① 展平并过滤 NaN 点;② 组织 (x, y, z) 三元组;③ 调用 griddata —— 即可获得与线性插值一致的容错行为(有效区三次光滑,无效区自动置 NaN),且代码简洁、语义清晰。