Python/Scipy 二维插值(非均匀数据)
这是我之前帖子的问题的后续:Python/Scipy 插值 (map_coordinates)
假设我想在一个二维的矩形区域内进行插值。我的变量'z'包含了如下的数据。每一列的值是固定的,但每一行的值可能会不同,下面的注释中有说明。
from scipy import interpolate
from numpy import array
import numpy as np
# # 0.0000, 0.1750, 0.8170, 1.0000
z = array([[-2.2818,-2.2818,-0.9309,-0.9309], # 0.0000, 0.0000, 0.0000, 0.0000
[-2.2818,-2.2818,-0.9309,-0.9309], # 0.2620, 0.2784, 0.3379, 0.3526
[-1.4891,-1.4891,-0.5531,-0.5531], # 0.6121, 0.6351, 0.7118, 0.7309
[-1.4891,-1.4891,-0.5531,-0.5531]]) # 1.0000, 1.0000, 1.0000, 1.0000
# Rows, Columns = z.shape
cols = array([0.0000, 0.1750, 0.8170, 1.0000])
rows = array([0.0000, 0.2620, 0.6121, 1.0000])
sp = interpolate.RectBivariateSpline(rows, cols, z, kx=1, ky=1, s=0)
xi = np.array([0.00000, 0.26200, 0.27840, 0.33790, 0.35260, 0.61210, 0.63510,
0.71180, 0.73090, 1.00000], dtype=np.float)
yi = np.array([0.000, 0.167, 0.815, 1.000], dtype=np.float)
print sp(xi, yi)
为了更好地理解,我知道的值的数组应该是这样的:
rows = array([0.0000, 0.2620, 0.2784, 0.3379, 0.3526,
0.6121, 0.6351, 0.7118, 0.7309, 1.0000])
# # 0.0000, 0.1750, 0.8170, 1.0000
z = array([[-2.2818,-2.2818,-0.9309,-0.9309], # 0.0000
[-2.2818, ?, ?, ?], # 0.2620,
[ ?,-2.2818, ?, ?], # 0.2784
[ ?, ?,-0.9309, ?], # 0.3379
[ ? ,?, ?,-0.9309], # 0.3526
[-1.4891, ?, ?, ?], # 0.6121
[ ?,-1.4891, ?, ?], # 0.6351
[ ?, ?,-0.5531, ?], # 0.7118
[ ?, ?, ?,-0.5531], # 0.7309
[-1.4891,-1.4891,-0.5531,-0.5531]]) # 1.0000
我不知道的'?'值需要通过插值来计算。我尝试用None来替换它们,但结果却都是'nan'。
编辑:
我觉得我需要使用'griddata'或者'interp2'。使用griddata似乎能得到我想要的结果,但'interp2'却不行。
from scipy import interpolate
from numpy import array
import numpy as np
z = array([[-2.2818,-2.2818,-0.9309,-0.9309],
[-2.2818,-2.2818,-0.9309,-0.9309],
[-1.4891,-1.4891,-0.5531,-0.5531],
[-1.4891,-1.4891,-0.5531,-0.5531]])
rows = array([0.0000, 0.0000, 0.0000, 0.0000,
0.2620, 0.2784, 0.3379, 0.3526,
0.6121, 0.6351, 0.7118, 0.7309,
1.0000, 1.0000, 1.0000, 1.0000])
cols = array([0.0000, 0.1750, 0.8180, 1.0000,
0.0000, 0.1750, 0.8180, 1.0000,
0.0000, 0.1750, 0.8180, 1.0000,
0.0000, 0.1750, 0.8180, 1.0000])
xi = array([0.0000, 0.2620, 0.2784, 0.3379, 0.3526, 0.6121, 0.6351, 0.7118,
0.7309, 1.0000], dtype=np.float)
yi = array([0.000, 0.175, 0.818, 1.000], dtype=np.float)
GD = interpolate.griddata((rows, cols), z.ravel(),
(xi[None,:], yi[:,None]), method='linear')
I2 = interpolate.interp2d(rows, cols, z, kind='linear')
print GD.reshape(4, 10).T
print '\n'
print I2(xi, yi).reshape(4, 10).T
import matplotlib.pyplot as plt
import numpy.ma as ma
plt.figure()
GD = interpolate.griddata((rows.ravel(), cols.ravel()), z.ravel(),
(xi[None,:], yi[:,None]), method='linear')
CS = plt.contour(xi,yi,GD,15,linewidths=0.5,colors='k')
CS = plt.contourf(xi,yi,GD,15,cmap=plt.cm.jet)
plt.colorbar()
plt.scatter(rows,cols,marker='o',c='b',s=5)
plt.figure()
I2 = I2(xi, yi)
CS = plt.contour(xi,yi,I2,15,linewidths=0.5,colors='k')
CS = plt.contourf(xi,yi,I2,15,cmap=plt.cm.jet)
plt.colorbar()
plt.scatter(rows,cols,marker='o',c='b',s=5)
plt.show()
1 个回答
看起来你已经明白了。
在你上面的代码示例和你之前提到的(链接)问题中,你有的是结构化数据。这种数据可以用 RectBivariateSpline
或 interp2d
来进行插值。这意味着你的数据可以在一个网格上描述(网格上的所有点都有已知的值)。这个网格的每个点之间的距离(dx和dy)不一定要相同。如果所有的dx和dy都相等,那就是一个规则网格。
现在,你当前的问题是,如果不是所有的点都有已知值,该怎么处理。这种情况被称为非结构化数据。你只有一些选定的点,无法构建出所有角点都有已知值的矩形。对于这种数据,你可以使用(正如你所做的)griddata
,或者某种形式的 BivariateSpline
。
那么该选择哪种呢?
与结构化的 RectBivariateSpline
最接近的非结构化 BivariateSpline
类别是 SmoothBivariateSpline
或 LSQBivariateSpline
。如果你想用样条插值数据,可以选择这些。这会让你的函数变得光滑且可微分,但可能会出现超出 Z.max() 或 Z.min() 的情况。
因为你设置了 ky=1
和 kx=1
,并且我相信你得到的只是对结构化数据的线性插值,我个人建议你可以从 RectBivariateSpline
切换到 interp2d
这个结构化网格插值方案。我知道文档上说它是用于 规则网格,但文档中的示例实际上是结构化的,而不是规则的。
如果你真的切换了方法,我很好奇你是否发现了两者之间的显著差异。欢迎使用 SciPy。