使用屏蔽数据进行Scipy插值?

时间:2016-03-04 22:34:09

标签: python arrays numpy scipy

我正在尝试插入一个包含屏蔽数据的2D数组。我使用了一些可用的SciPy模块方法,包括interp2dbisplrep/bisplev以及RectBivariateSpline。作为附加信息,我的数据是一个常规数组,这意味着网格具有相同的尺寸(在这种情况下为1ºX1º)。

话虽如此,有没有办法用Python插入避免数组中的掩码数据?我还是使用Python和NumPy / SciPy模块的新手。

3 个答案:

答案 0 :(得分:3)

您实际上可以使用接受x, y, z的每个函数(对于interp2d,也可能是其他函数)与您的屏蔽数据一起使用。但您需要明确创建mgrid

z = ... # Your data
x, y = np.mgrid[0:z.shape[0], 0:z.shape[1]]

然后你需要删除所有这些坐标中的所有蒙版值:

x = x[~z.mask]
y = y[~z.mask]
z = z[~z.mask]

使用这些最终x, y, z,您可以调用每个指定的函数(接受不完整的网格,因此RectBivariateSpline无法工作)。但请注意,其中一些使用插值框,因此如果由于掩码而导致丢弃数据的区域太大,则插值将在那里失败(导致np.nan或0)。但是如果发生这种情况,你可以调整参数来补偿它。

例如:

data = np.random.randint(0, 10, (5,5))
mask = np.random.uniform(0,1,(5,5)) > 0.5
z = np.ma.array(data, mask=mask)
x, y = np.mgrid[0:z.shape[0], 0:z.shape[1]]
x1 = x[~z.mask]
y1 = y[~z.mask]
z1 = z[~z.mask]
interp2d(x1, y1, z1)(np.arange(z.shape[0]), np.arange(z.shape[1]))

array([[  1.1356716 ,   2.45313727,   3.77060294,   6.09790177, 9.31328935],
       [  3.91917937,   4.        ,   4.08082063,   3.98508121, 3.73406764],
       [ 42.1933738 ,  25.0966869 ,   8.        ,   0.        , 0.        ],
       [  1.55118338,   3.        ,   4.44881662,   4.73544593, 4.        ],
       [  5.        ,   8.        ,  11.        ,   9.34152525, 3.58619652]])

你可以看到0的小区域,因为掩码中有许多蒙版值:

mask
array([[False,  True,  True,  True, False],
       [False, False,  True, False, False],
       [ True,  True, False,  True,  True],
       [False,  True, False,  True,  True],
       [False,  True, False, False,  True]], dtype=bool)

data
array([[2, 4, 4, 5, 5],
       [1, 4, 1, 3, 8],
       [9, 1, 8, 0, 9],
       [7, 2, 0, 3, 4],
       [9, 6, 0, 4, 4]])

答案 1 :(得分:0)

我通常遵循@mseifert描述的方法,但如果我厌倦了通过遮罩区域的插值错误,则添加以下细化。这似乎是你关注的问题之一,@ hurrdrought?我们的想法是将掩模传播到插值结果。一维数据的一个简单示例是:

def ma_interp(newx,x,y,mask,propagate_mask=True):
    newy = np.interp(newx,x[~mask],y[~mask]) # interpolate data
    if propagate_mask: # interpolate mask & apply to interpolated data
        newmask = mask[:]
        newmask[mask] = 1; newmask[~mask] = 0
        newmask = np.interp(newx,x,newmask)
        newy = np.ma.masked_array(newy, newmask>0.5)
    return newy

答案 2 :(得分:0)

@MSeifert概述的方法的问题在于规则的网格结构丢失,导致插值效率低下。仅通过插值来填充丢失的数据是合理的,但对于从一个网格到另一个网格的典型插值却没有用,因为在这种情况下,不应填充丢失的数据。

在这种情况下,用np.nan填充缺失值是最简单的方法。这些将在计算中传播,并且在使用缺失值进行插值的地方,所得数组将具有nans。

# fast interpolator that use the regular grid structure (x and y are 1D arrays)
z = z_masked.filled(np.nan)
zinterp = RegularGridInterpolator((x, y), z.T)

# new grid to interpolate on
X2, Y2 = np.meshgrid(x2, y2)
newpoints = np.array((X2, Y2)).T

# actual interpolation
z2 = zinterp(newpoints)
z2_masked = np.ma.array(z2, mask=np.isnan(z2))

为完整起见,另一种方法是内插第二个mask数组(在缺少数据的地方填充1)以在新网格上填写缺失的值。

# fast interpolator that use the regular grid structure (x and y are 1D arrays)
zinterp = RegularGridInterpolator((x, y), z.T)
minterp = RegularGridInterpolator((x, y), (mask+0.).T)

# actual interpolation
z2 = zinterp(newpoints)
mask2 = minterp(newpoints) > 0  # apply threshold, e.g. 0.5 is considered contaminated and will be removed.
z2[mask2] = np.nan  # fill with nans or whatever missing data flag

请注意,如果需要样条互操作,则两种方法也应与RectBivariateSpline一起使用。无论哪种方式,这都应该比使用interp2d快得多。