问题描述
我有一个3D数据集,我想对其进行线性插值和插值.使用 scipy.interpolate.LinearNDInterpolator
一个>.该模块只能为参数范围之外的值填写常数/nan,但是我不明白为什么它不提供打开外推的选项.
I've got a 3D dataset that I want to interpolate AND extrapolate linearly. The interpolation can be done easily with scipy.interpolate.LinearNDInterpolator
. The module can only fill in a constant/nan for values outside the parameter range, but I don't see why it would not offer an option to turn on extrapolation.
看代码,我看到该模块是用cython编写的.没有cython经验,很难尝试使用代码来实现外推.我可以用纯python代码编写它,但是这里的其他人也许有更好的主意?我的特殊情况涉及一个恒定的xy网格,但是z值不断变化(-100,000),因此插值必须很快,因为每次z值更改时都会运行插值.
Looking at the code, I see that the module is written in cython. With no experience in cython, it is hard to play around with the code to implement extrapolation. I can write it in pure python code, but maybe someone else here has a better idea? My particular case involves a constant xy-grid, but the z-values keep changing a lot (-100,000) and therefore the interpolation must be fast as the interpolation will be runned for each time the z-values change.
根据要求给出一个基本示例,可以说我有一个像这样的网格
To give a basic example, as requested, lets say that I have a grid like
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轴执行一维插值/外推,然后对每个x值沿y轴执行一维插值/外推.外推由 ryggyr's answer
中的第二个函数完成.
and lets say I want to calculate values at x = -1.5, -0.8, +0.5
and y = -0.2, +0.2, +0.5
. Currently, I am performing 1d interpolation/extrapolation along the x-axis for each y-value and then along the y-axis for each x-value. The extrapolation is done by the second function in ryggyr's answer
.
推荐答案
我提出了一种方法,代码虽然很糟糕,但希望对您有所帮助.这个想法是,如果您事先知道必须外推的范围,则可以在数组的边缘添加带有线性外推值的额外列/行,然后在新数组上进行内插.这是一个示例,其中一些数据将被外推到x = +-50和y = +-40:
I propose a method, the code is awful but I hope it will help you. The idea is, if you know by advance the bounds in which you will have to extrapolate, you can add extra columns/rows at the edge of your arrays with linearly extrapolated values, and then interpolate on the new array. Here is an example with some data that will be extrapolated until x=+-50 and y=+-40:
import numpy as np
x,y=np.meshgrid(np.linspace(0,6,7),np.linspace(0,8,9)) # create x,y grid
z=x**2*y # and z values
# create larger versions with two more columns/rows
xlarge=np.zeros((x.shape[0]+2,x.shape[1]+2))
ylarge=np.zeros((x.shape[0]+2,x.shape[1]+2))
zlarge=np.zeros((x.shape[0]+2,x.shape[1]+2))
xlarge[1:-1,1:-1]=x # copy data on centre
ylarge[1:-1,1:-1]=y
zlarge[1:-1,1:-1]=z
# fill extra columns/rows
xmin,xmax=-50,50
ymin,ymax=-40,40
xlarge[:,0]=xmin;xlarge[:,-1]=xmax # fill first/last column
xlarge[0,:]=xlarge[1,:];xlarge[-1,:]=xlarge[-2,:] # copy first/last row
ylarge[0,:]=ymin;ylarge[-1,:]=ymax
ylarge[:,0]=ylarge[:,1];ylarge[:,-1]=ylarge[:,-2]
# for speed gain: store factor of first/last column/row
first_column_factor=(xlarge[:,0]-xlarge[:,1])/(xlarge[:,1]-xlarge[:,2])
last_column_factor=(xlarge[:,-1]-xlarge[:,-2])/(xlarge[:,-2]-xlarge[:,-3])
first_row_factor=(ylarge[0,:]-ylarge[1,:])/(ylarge[1,:]-ylarge[2,:])
last_row_factor=(ylarge[-1,:]-ylarge[-2,:])/(ylarge[-2,:]-ylarge[-3,:])
# extrapolate z; this operation only needs to be repeated when zlarge[1:-1,1:-1] is updated
zlarge[:,0]=zlarge[:,1]+first_column_factor*(zlarge[:,1]-zlarge[:,2]) # extrapolate first column
zlarge[:,-1]=zlarge[:,-2]+last_column_factor*(zlarge[:,-2]-zlarge[:,-3]) # extrapolate last column
zlarge[0,:]=zlarge[1,:]+first_row_factor*(zlarge[1,:]-zlarge[2,:]) # extrapolate first row
zlarge[-1,:]=zlarge[-2,:]+last_row_factor*(zlarge[-2,:]-zlarge[-3,:]) #extrapolate last row
然后可以在(xlarge,ylarge,zlarge)上插值.由于所有操作都是numpy slices操作,我希望它对您来说足够快.更新z数据后,将其复制到zlarge[1:-1,1:-1]
中,然后重新执行最后4行.
Then you can interpolate on (xlarge,ylarge,zlarge). Since all operations are numpy slices operations, I hope it will be fast enough for you. When z data are updated, copy them in zlarge[1:-1,1:-1]
and re-execute the 4 last lines.
这篇关于用LinearNDInterpolator推断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!