评估沿曲线的scipy 2D插值的输出

时间:2017-11-03 01:31:39

标签: python numpy scipy

我在网格点z处从2D函数f采样数据x, y,与z = f(x, y)一样。

很容易通过fscipy.interp2d插入f = interp2d(x, y, z

但是,评估f(x, y)会返回整个2D网格,就像我已经完成

一样
xx, yy = np.meshgrid(x, y)
f(xx, yy)

我想要的行为是简单地返回值[f(x[i], y[i]) for i in range(len(x))],我认为这几乎是numpy中任何其他方法的行为。

我想要这种行为的原因是我正在寻找f表面上追踪的路径" time"由(t, u(t))对组成。

同样令人惊讶的是np.diag(f(t, u(t)))np.array([f(ti, u(ti)) for ti in t])不同,所以我不清楚如何通过{{1}返回的路径f(t, u(t)) }}

编辑:关于interp2d,我只是认为我们应该diag,但事实并非如此。

完整示例:

np.diag(f(t, u(t))) == np.array([f(ti, u(ti)) for ti in t])

我希望两个def f(t, u): return (t**2) * np.exp((u**2) / (1 + u**2)) x = np.linspace(0, 1, 250) xx, yy = np.meshgrid(x, x) z = f(xx, yy) f = scipy.interpolate.interp2d(x, y, z) print(f(x, y)) print(np.array([f(xi, yi)[0] for xi, yi in zip(x, y)])) 语句的输出都相同。

3 个答案:

答案 0 :(得分:3)

方法interp2d返回一个对象,其调用方法要求x,y向量为矩形网格的坐标。并且你没有从返回数组的对角线获得所需值的原因是它首先对x,y进行排序。

但有一种解决方法,我也在Querying multiple points on a bivariate spline in the B-spline basis中使用过。执行后

import scipy.interpolate as si
f = si.interp2d(x, y, z)

不是通过调用来评估f,而是将其tck属性,后跟x,y坐标传递给内部bispeu方法。像这样:

print(si.dfitpack.bispeu(f.tck[0], f.tck[1], f.tck[2], f.tck[3], f.tck[4], x, y)[0])

以上返回与慢循环

相同
print(np.array([f(xi, yi)[0] for xi, yi in zip(x, y)]))

解释

对象f秘密地是阶数为1的B样条。样条参数(节点,系数,顺序)包含在其tck属性中,可以由低阶例程直接使用达到预期的效果。

(理想情况下,f的调用方法会有一个布尔参数grid,我们将其设置为False,让它知道我们不想要网格评估。唉,它没有实现。)

答案 1 :(得分:0)

interp2d()似乎表现得如此,因为这就是相应的Fortran函数的构思方式。对此(我能想到的)唯一的解决方法是在坐标对上调用f

[f(*p)[0] for p in zip(x, y)]

答案 2 :(得分:0)

根据user6655984的建议,我在另一个thread中发布了以下包装函数:

import scipy.interpolate as si
def interp2d_pairs(*args,**kwargs):
    """ Same interface as interp2d but the returned interpolant will evaluate its inputs as pairs of values.
    """
    # Internal function, that evaluates pairs of values, output has the same shape as input
    def interpolant(x,y,f):
        x,y = np.asarray(x), np.asarray(y)
        return (si.dfitpack.bispeu(f.tck[0], f.tck[1], f.tck[2], f.tck[3], f.tck[4], x.ravel(), y.ravel())[0]).reshape(x.shape)
    # Wrapping the scipy interp2 function to call out interpolant instead
    return lambda x,y: interpolant(x,y,si.interp2d(*args,**kwargs))

# Create the interpolant (same interface as interp2d)
f = interp2d_pairs(X,Y,Z,kind='cubic')
# Evaluate the interpolant on each pairs of x and y values
z=f(x,y)