Scipy.interpolate griddata三次样条返回NaN而非有效值的解决方法
解决scipy griddata三次样条插值返回NaN的问题
嘿,我来帮你排查这个问题~你遇到的NaN返回值,核心原因是三次样条(cubic)插值要求查询点必须落在原始数据点构成的凸包内部,如果点在凸包外面,就会直接返回NaN。
咱们先验证一下你的测试点(3128,265)是不是在凸包外:
import pandas as pd import numpy as np from scipy.interpolate import griddata from scipy.spatial import Delaunay # 原始数据 y = [164,166,168,172,173,181,185,189, 189,191,196,197,198,201,214,218, 223,224,227,230,231,232,237,253, 257,257,258,262,266] z = [0.68,0.95,0.44,0.68,0.93,0.69,0.94, 1.55,0.94,1.53,1.85,0.52,1.53,1.83, 0.98,1.53,0.77,1.82,1.56,2.43,1.01, 1.82,0.15,2.41,1.84,0.39,0.64,1.56, 2.39] x = [100,250,400,550,700,850,1000,1150,1300, 1450,1600,1750,1900,2050,2200,2350,2500, 2650,2800,2950,3100,3250,3400,3550,3700, 3850,4000,4150,4300] # 生成Delaunay三角剖分,用于判断点是否在凸包内 points = np.array(list(zip(x, y))) tri = Delaunay(points) # 检查测试点 query_point = np.array([3128, 265]) print("测试点是否在凸包内:", tri.find_simplex(query_point) >= 0) # 输出False,说明在凸包外
知道原因后,有几种解决方案可选:
方案1:换用支持外推的插值方法
如果你能接受外推的结果,可以把插值方法换成linear或者nearest,这两种方法会对凸包外的点进行计算:
# 线性外推 print(griddata((x,y),z,(3128,265), method='linear')) # 返回约1.23左右的数值 # 最近邻插值 print(griddata((x,y),z,(3128,265), method='nearest')) # 返回1.01(对应最近的点(3100,231)的z值)
方案2:混合插值(凸包内用cubic,外补充其他方法)
如果必须保留三次样条的精度,同时不想有NaN,可以对凸包内的点用cubic插值,凸包外的点用其他方法填充:
# 生成网格 xi = np.linspace(100,4300) yi = np.linspace(164,266) xi_grid, yi_grid = np.meshgrid(xi, yi) # 将网格点转为一维数组 grid_points = np.array([xi_grid.flatten(), yi_grid.flatten()]).T # 判断每个网格点是否在凸包内 inside = tri.find_simplex(grid_points) >= 0 # 初始化插值结果数组 zi = np.empty_like(xi_grid) # 凸包内用cubic插值,外用nearest填充 zi.flat[inside] = griddata((x, y), z, grid_points[inside], method='cubic') zi.flat[~inside] = griddata((x, y), z, grid_points[~inside], method='nearest') # 现在zi里就没有NaN了 print(zi)
方案3:补充数据点(最彻底但成本高)
如果对精度要求极高,最好的办法是在凸包外的区域(比如你测试的x≈3000-4300,y≈250-266区间)补充更多采样数据点,让凸包覆盖到你需要查询的区域,这样就能用cubic插值得到有效结果。
内容的提问来源于stack exchange,提问作者cosmic noise
相关产品推荐
相关产品推荐

