python/scipy中的多变量样条曲线插值?

31 人关注

是否有一个库模块或其他直接的方法来实现Python中的多变量样条插值?

具体来说,我在一个有规则间隔的三维网格上有一组标量数据,我需要在散布在整个领域的少量点上进行插值。 对于二维,我一直使用 scipy.interpolate.RectBivariateSpline ,而我基本上是在寻找一种对三维数据的扩展。

我发现的N维插值程序还不够好:我更喜欢花样图,而不是花样图。 LinearNDInterpolator 我有太多的数据点(经常超过一百万),例如径向基函数无法工作。

如果有人知道有一个Python库可以做到这一点,或者有一个我可以调用或移植的其他语言的库,我将非常感激。

1 个评论
为了确定我的理解是否正确,你的数据已经在一个规则的网格上了,你想在不规则的点上进行插值?(如果是这样,你需要scipy.ndimage.map_coordinates,我一会儿会发一个例子...)
python
numpy
scipy
interpolation
Chris P
Chris P
发布于 2011-06-05
2 个回答
Joe Kington
Joe Kington
发布于 2011-06-05
已采纳
0 人赞同

如果我对你的问题理解正确,你输入的 "观察 "数据是有规律的网格化的?

If so, scipy.ndimage.map_coordinates 这正是你想要的结果。

一开始有点难以理解,但本质上,你只是给它提供了一个坐标序列,你想在像素/体素/n维指数坐标中插值网格的值。

作为一个2D的例子。

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt
# Note that the output interpolated coords will be the same dtype as your input
# data.  If we have an array of ints, and we want floating point precision in
# the output interpolated points, we need to cast the array as floats
data = np.arange(40).reshape((8,5)).astype(np.float)
# I'm writing these as row, column pairs for clarity...
coords = np.array([[1.2, 3.5], [6.7, 2.5], [7.9, 3.5], [3.5, 3.5]])
# However, map_coordinates expects the transpose of this
coords = coords.T
# The "mode" kwarg here just controls how the boundaries are treated
# mode='nearest' is _not_ nearest neighbor interpolation, it just uses the
# value of the nearest cell if the point lies outside the grid.  The default is
# to treat the values outside the grid as zero, which can cause some edge
# effects if you're interpolating points near the edge
# The "order" kwarg controls the order of the splines used. The default is 
# cubic splines, order=3
zi = ndimage.map_coordinates(data, coords, order=3, mode='nearest')
row, column = coords
nrows, ncols = data.shape
im = plt.imshow(data, interpolation='nearest', extent=[0, ncols, nrows, 0])
plt.colorbar(im)
plt.scatter(column, row, c=zi, vmin=data.min(), vmax=data.max())
for r, c, z in zip(row, column, zi):
    plt.annotate('%0.3f' % z, (c,r), xytext=(-10,10), textcoords='offset points',
            arrowprops=dict(arrowstyle='->'), ha='right')
plt.show()
data = np.arange(3*5*9).reshape((3,5,9)).astype(np.float)
coords = np.array([[1.2, 3.5, 7.8], [0.5, 0.5, 6.8]])
zi = ndimage.map_coordinates(data, coords.T)

As far as scaling and memory usage goes, map_coordinates will create a filtered copy of the array if you're using an order > 1 (i.e. not linear interpolation). If you just want to interpolate at a very small number of points, this is a rather large overhead. It doesn't increase with the number points you want to interpolate at, however. As long as have enough RAM for a single temporary copy of your input data array, you'll be fine.

如果你不能在内存中存储一份数据,你可以a)指定prefilter=Falseorder=1并使用线性内插。或者b)用ndimage.spline_filter的过滤版本替换原始数据,然后用prefilter=False调用map_coordinates。

即使你有足够的内存,如果你需要多次调用map_coordinates(如交互式使用等),保持过滤后的数据集也会有很大的加速作用。