Python 用线性插值器外推

Python 用线性插值器外推,python,numpy,scipy,interpolation,extrapolation,Python,Numpy,Scipy,Interpolation,Extrapolation,我有一个三维数据集,我想用线性插值和外推。插值可以很容易地完成。该模块只能为参数范围之外的值填充常量/nan,但我不明白为什么它不提供启用外推的选项 查看代码,我看到模块是用cython编写的。由于没有cython方面的经验,很难使用代码来实现外推。我可以用纯python代码编写它,但也许这里的其他人有更好的主意?我的特殊情况涉及一个恒定的xy网格,但z值不断变化(-100000),因此插值必须快速,因为每次z值变化时都会运行插值 根据要求,给出一个基本示例,假设我有一个类似网格的 xyPair

我有一个三维数据集,我想用线性插值和外推。插值可以很容易地完成。该模块只能为参数范围之外的值填充常量/nan,但我不明白为什么它不提供启用外推的选项

查看代码,我看到模块是用cython编写的。由于没有cython方面的经验,很难使用代码来实现外推。我可以用纯python代码编写它,但也许这里的其他人有更好的主意?我的特殊情况涉及一个恒定的xy网格,但z值不断变化(-100000),因此插值必须快速,因为每次z值变化时都会运行插值

根据要求,给出一个基本示例,假设我有一个类似网格的

xyPairs = [[-1.0, 0.0], [-1.0, 4.0],
           [-0.5, 0.0], [-0.5, 4.0],
           [-0.3, 0.0], [-0.3, 4.0],
           [+0.0, 0.0], [+0.0, 4.0],
           [+0.2, 0.0], [+0.2, 4.0]]

假设我想计算
x=-1.5,-0.8,+0.5
y=-0.2,+0.2,+0.5
的值。目前,我正在为每个y值沿x轴执行1d插值/外推,然后为每个x值沿y轴执行1d插值/外推。外推是由中的第二个函数完成的。

我提出了一个方法,代码很糟糕,但我希望它能帮助您。其思想是,如果预先知道必须进行外推的边界,可以使用线性外推值在数组边缘添加额外的列/行,然后在新数组上进行插值。下面是一个示例,其中一些数据将被外推到x=+-50和y=+-40:

将numpy导入为np
x、 y=np.meshgrid(np.linspace(0,6,7),np.linspace(0,8,9))#创建x,y网格
z=x**2*y#和z值
#创建具有两个以上列/行的更大版本
xlarge=np.zero((x.shape[0]+2,x.shape[1]+2))
ylarge=np.zero((x.shape[0]+2,x.shape[1]+2))
zlarge=np.zero((x.shape[0]+2,x.shape[1]+2))
xlarge[1:-1,1:-1]=x#在中心复制数据
y大[1:-1,1:-1]=y
zlarge[1:-1,1:-1]=z
#填充额外的列/行
xmin,xmax=-50,50
ymin,ymax=-40,40
xlarge[:,0]=xmin;xlarge[:,-1]=xmax#填充第一列/最后一列
xlarge[0,:]=xlarge[1,:];xlarge[-1,:]=xlarge[-2,:]#复制第一行/最后一行
ylarge[0,:]=ymin;ylarge[-1,:]=ymax
ylarge[:,0]=ylarge[:,1];ylarge[:,-1]=ylarge[:,-2]
#对于速度增益:存储第一列/最后一列/行的系数
第一列系数=(xlarge[:,0]-xlarge[:,1])/(xlarge[:,1]-xlarge[:,2])
最后一列系数=(xlarge[:,-1]-xlarge[:,-2])/(xlarge[:,-2]-xlarge[:,-3])
第一行系数=(ylarge[0,:]-ylarge[1,:])/(ylarge[1,:]-ylarge[2,:])
最后一行系数=(ylarge[-1,:]-ylarge[-2,:])/(ylarge[-2,:]-ylarge[-3,:])
#外推z;仅当zlarge[1:-1,1:-1]更新时,才需要重复此操作
zlarge[:,0]=zlarge[:,1]+第一列因子*(zlarge[:,1]-zlarge[:,2])外推第一列
zlarge[:,-1]=zlarge[:,-2]+最后一列系数*(zlarge[:,-2]-zlarge[:,-3])外推最后一列
zlarge[0,:]=zlarge[1,:]+第一行系数*(zlarge[1,:]-zlarge[2,:])#外推第一行
zlarge[-1,:]=zlarge[-2,:]+最后一行系数*(zlarge[-2,:]-zlarge[-3,:])#外推最后一行

然后可以在(xlarge、ylarge、zlarge)上插值。因为所有的操作都是numpy切片操作,我希望它对您来说足够快。更新z数据时,将其复制到
zlarge[1:-1,1:-1]
中,然后重新执行最后4行。

使用最近插值和线性插值的组合。 LinearNDInterpolator如果插值失败,则返回np.nan 否则返回数组大小(1) 最接近的Interpolator返回一个浮点值

import scipy.interpolate
import numpy
class LinearNDInterpolatorExt(object):
  def __init__(self, points,values):
    self.funcinterp=scipy.interpolate.LinearNDInterpolator(points,values)
    self.funcnearest=scipy.interpolate.NearestNDInterpolator(points,values)
  def __call__(self,*args):
    t=self.funcinterp(*args)
    if not numpy.isnan(t):
      return t.item(0)
    else:
      return self.funcnearest(*args)

我稍微修改了@Keith Williams的答案,这对我来说很有效(注意它不是线性外推-它只使用最近邻):


哦,一个月前问过,现在就编辑了-你能发布一些代码吗,比如你的数据集是什么样子的,你现在使用的是什么,结果是什么,以及你希望它是什么样子的,这是丑陋的,但它确实很快。不推广到N维插值和外推我喜欢这个想法,但你的
\uuuuuuuuuuuuuuuuuu
方法是一种全有或全无的解决方案。我猜OP希望尽可能地进行插值,用最近的值填充生成的边NaN。不过,这是一个很好的起点。
import numpy as np
from scipy.interpolate import LinearNDInterpolator as linterp
from scipy.interpolate import NearestNDInterpolator as nearest

class LinearNDInterpolatorExt(object):
    def __init__(self, points, values):
        self.funcinterp = linterp(points, values)
        self.funcnearest = nearest(points, values)
    
    def __call__(self, *args):
        z = self.funcinterp(*args)
        chk = np.isnan(z)
        if chk.any():
            return np.where(chk, self.funcnearest(*args), z)
        else:
            return z