使用scipy.interpolate.griddata时出现意外结果

时间:2018-03-09 01:15:50

标签: python scipy interpolation

当我需要在Python中插入数据时,我通常使用我自己实现的 Numerical Cipes in C 中的双线性和双三次例程(W.H.Press,1992)。主要原因是我没有得到Scipy的期望。由于我现在需要更多的灵活性(例如,不规则网格),我想使用griddata函数。

我的问题可以通过以下脚本来说明:

from matplotlib import pyplot as plt
from scipy.interpolate import griddata

from interp import *    # My own interpolation functions (from Press. 1992)

# Create test data
nPts = 50
color_ticks = np.linspace(0., 6., 50, endpoint = True)

pts1 = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4],
                 [1, 0], [1, 1], [1, 2], [1, 3], [1, 4],
                 [2, 0], [2, 1], [2, 2], [2, 3], [2, 4],
                 [3, 0], [3, 1], [3, 2], [3, 3], [3, 4]])*2 + 3.3

z1 = np.array([[1], [6], [4], [5], [2],
               [2], [3], [2], [4], [1],
               [4], [5], [1], [2], [1],
               [6], [2], [5], [3], [6]], dtype = np.float64)

# Interpolation coordinates
xi, yi = np.linspace(0,3,nPts)*2 + 3.3, np.linspace(0,4,nPts)*2 + 3.3

# Scipy, bilinear
scipy_linear = griddata((pts1[:,0], pts1[:,1]), z1, (xi[None,:], yi[:,None]), method = 'linear')

# Scipy, bicubic
scipy_cubic = griddata((pts1[:,0], pts1[:,1]), z1, (xi[None,:], yi[:,None]), method = 'cubic')

# Press, bilinear
pts2 = np.zeros((nPts*nPts,2))

for i in range(0, nPts):
    for j in range(0, nPts):
        pts2[i*nPts + j,:] = [xi[i], yi[j]]

press_linear = interp_linear(np.unique(pts1[:,0]), np.unique(pts1[:,1]),
    z1.reshape(4,5), pts2[:,0], pts2[:,1])

# Press, bicubic
press_cubic = interp_cubic(np.unique(pts1[:,0]), np.unique(pts1[:,1]),
    z1.reshape(4,5), pts2[:,0], pts2[:,1])

# Display
fig_scipy = plt.figure()
fig_press = plt.figure()

ax1 = fig_scipy.add_subplot(121, aspect = 'equal')
ax1.set_title("Scipy (linear)")
ax1.contourf(xi, yi, scipy_linear.reshape(nPts, nPts), color_ticks)
ax1.scatter(pts1[:,0], pts1[:,1], color = 'k', s = 2)

ax2 = fig_scipy.add_subplot(122, aspect = 'equal')
ax2.set_title("Scipy (cubic)")
ax2.contourf(xi, yi, scipy_cubic.reshape(nPts, nPts), color_ticks)
ax2.scatter(pts1[:,0], pts1[:,1], color = 'k', s = 2)

ax3 = fig_press.add_subplot(121, aspect = 'equal')
ax3.set_title("Press (linear)")
ax3.contourf(xi, yi, press_linear.reshape(nPts, nPts).T, color_ticks)
ax3.scatter(pts1[:,0], pts1[:,1], color = 'k', s = 2)

ax4 = fig_press.add_subplot(122, aspect = 'equal')
ax4.set_title("Press (cubic)")
ax4.contourf(xi, yi, press_cubic.reshape(nPts, nPts).T, color_ticks)
ax4.scatter(pts1[:,0], pts1[:,1], color = 'k', s = 2)

plt.show()

来自我自己的函数的插值给出了我认为是正确的: enter image description here 而来自griddata的插值导致(注意差异,特别是在轮廓的右下部分): enter image description here

我正确使用griddata吗?如果是这样,差异来自哪里?是一个结果"更好"比另一个?我能看到的一个解释是我在双三次函数中计算导数的方式,但这并不能解释两种双线性方法之间的差异。

1 个答案:

答案 0 :(得分:0)

  

两种双线性方法之间。

你的方法可能是双线性的,但SciPy不是。这可以从图像中的分段线性渐变中看出,documentation证实了这一点:

  

将输入点设置为n维单纯形,并在每个单纯形上进行线性插值。

因此,SciPy的插值在本地a*x + b*y + c,而你的插值是a*x*y + b*x + c*y + d

要使用SciPy对非结构化数据进行双线性插值,请使用SmoothBivariateSpline,其中kx = 1且ky = 1(双线性),s = 0(无平滑)。 (但是看起来你需要比这个例子更多的数据点来实现s = 0.)

对于矩形网格的双线性插值,有RectBivariateSpline,kx = 1且ky = 1。

至于立方版本的差异,有too many details in the procedure期望你的插值与SciPy完全一致。