我从2D函数f
的网格点x, y
处采样了数据z
,就像在z = f(x, y)
中一样。
使用scipy.interp2d
通过f = interp2d(x, y, z
对f
进行插值很容易)。
但是,计算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中几乎任何其他方法的行为。
我想要这种行为的原因是,我正在寻找一对(t, u(t))
在“时间”上沿着f
表面所描绘出的路径。
同样令人惊讶的是,np.diag(f(t, u(t)))
不同于np.array([f(ti, u(ti)) for ti in t])
,所以我不清楚如何从interp2d
返回的内容中获取路径f(t, u(t))
。
编辑:关于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)]))
我希望两个print
语句的输出是相同的。
发布于 2017-11-11 08:46:44
方法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
属性传递给内部bispeu
方法,后面是x,y坐标。如下所示:
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,以便让它知道我们不需要网格求值。遗憾的是,它没有实现。)
发布于 2017-11-03 10:05:30
看起来interp2d()
的行为是这样的,因为相应的Fortran函数就是这样构思出来的。唯一的解决方法(我能想到的)是对坐标对调用f
:
[f(*p)[0] for p in zip(x, y)]
发布于 2019-06-13 07:42:12
根据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)
https://stackoverflow.com/questions/47087109
复制相似问题