You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用三次插值将含NaN的二维网格数据插值到非结构化坐标?

问题根源分析
  1. RegularGridInterpolator cubic报错原因:三次插值依赖样条拟合(make_interp_spline),样条算法要求输入数据完全无NaN;而线性插值是基于局部邻点的计算,遇到邻点含NaN时直接返回NaN,因此两者对NaN的兼容性完全不同。
  2. interp2d使用错误:interp2d设计目标是生成网格插值结果,若要得到非结构化点的插值,需将目标坐标按成对方式传入,但该函数效率较低,不适合大量非结构化点场景。
  3. interpn参数错误:interpn第一个参数需传入规则网格的维度坐标(如(lat0, lon0)),而非扁平化的非NaN点坐标,你传入的(latM, lonM)是一维点集,导致维度匹配失败。
可行解决方案

方案1:直接用griddata对非结构化点做三次插值

跳过规则网格插值,直接用非NaN原始点对目标坐标做三次插值,最贴合你的需求:

import numpy as np
from scipy.interpolate import griddata

# 复用数据定义
lat0, lon0 = np.linspace(-60, -40, 20), np.linspace(-50, 0.0, 50)
lonG, latG = np.meshgrid(lon0, lat0)
data_nan = np.sin(latG*lonG)
data_nan[1:8, 5:12] = np.nan
data_nan[2:6, 12:20] = np.nan

# 提取有效点坐标与对应值
mask = ~np.isnan(data_nan)
source_points = np.column_stack((latG[mask], lonG[mask]))
source_values = data_nan[mask]

# 目标非结构化坐标
lat = np.random.uniform(low=-60, high=-40, size=2000)
lon = np.random.uniform(low=-50, high=0.0, size=2000)
target_points = np.column_stack((lat, lon))

# 三次插值,靠近NaN区域的点自动返回NaN
interped_cub = griddata(source_points, source_values, target_points, method='cubic', fill_value=np.nan)

方案2:先填充NaN再用RegularGridInterpolator三次插值

先对带NaN的规则网格数据补全,再使用三次插值,适合需要保留规则网格结构的场景:

import numpy as np
from scipy.interpolate import RegularGridInterpolator, griddata

# 复用数据定义
lat0, lon0 = np.linspace(-60, -40, 20), np.linspace(-50, 0.0, 50)
lonG, latG = np.meshgrid(lon0, lat0)
data_nan = np.sin(latG*lonG)
data_nan[1:8, 5:12] = np.nan
data_nan[2:6, 12:20] = np.nan

# 提取非NaN点并填充网格
mask = ~np.isnan(data_nan)
points = np.column_stack((latG[mask], lonG[mask]))
values = data_nan[mask]
filled_data = griddata(points, values, (latG, lonG), method='linear', fill_value=np.nan)

# 用填充后的数据做三次插值
fc = RegularGridInterpolator((lat0, lon0), filled_data, method='cubic', bounds_error=True)
lat = np.random.uniform(low=-60, high=-40, size=2000)
lon = np.random.uniform(low=-50, high=0.0, size=2000)
interped_cub = fc((lat, lon))

方案3:结合线性插值掩码做三次插值

利用线性插值返回的NaN掩码,只对有效区域的点做三次插值,避免报错:

import numpy as np
from scipy.interpolate import RegularGridInterpolator

# 复用数据定义
lat0, lon0 = np.linspace(-60, -40, 20), np.linspace(-50, 0.0, 50)
lonG, latG = np.meshgrid(lon0, lat0)
data_nan = np.sin(latG*lonG)
data_nan[1:8, 5:12] = np.nan
data_nan[2:6, 12:20] = np.nan

# 先做线性插值,得到有效点掩码
fl = RegularGridInterpolator((lat0, lon0), data_nan, method='linear', bounds_error=True)
lat = np.random.uniform(low=-60, high=-40, size=2000)
lon = np.random.uniform(low=-50, high=0.0, size=2000)
interped_lin = fl((lat, lon))
valid_mask = ~np.isnan(interped_lin)

# 仅对有效点执行三次插值
fc = RegularGridInterpolator((lat0, lon0), data_nan, method='cubic', bounds_error=True)
interped_cub = np.full_like(interped_lin, np.nan)
interped_cub[valid_mask] = fc((lat[valid_mask], lon[valid_mask]))
说明
  • 方案1最直接,无需预处理规则网格,直接针对目标点插值,结果完全符合你的期望:有效区域返回三次插值结果,靠近NaN区域返回NaN。
  • 方案2适合需要同时保留规则网格数据的场景,填充后的网格可用于其他后续处理。
  • 方案3利用线性插值的掩码过滤报错点,避免NaN影响,但需要两次插值计算。

内容的提问来源于stack exchange,提问作者ofk123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:13:12