当我需要在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()
来自我自己的函数的插值给出了我认为是正确的:
而来自griddata
的插值导致(注意差异,特别是在轮廓的右下部分):
我正确使用griddata
吗?如果是这样,差异来自哪里?是一个结果"更好"比另一个?我能看到的一个解释是我在双三次函数中计算导数的方式,但这并不能解释两种双线性方法之间的差异。
答案 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完全一致。