屏蔽数组中的 numpy 渐变



当我在 numpy 中计算屏蔽数组的梯度时为

import numpy as np
import numpy.ma as ma
x = np.array([100, 2, 3, 5, 5, 5, 10, 100])
mx = ma.masked_array(x, mask=[1, 0, 0, 0, 0, 0, 0, 1])

生成的数组的掩码与原始掩码不同:

np.gradient(mx) 
masked_array(data = [-- -- 1.5 1.0 0.0 2.5 -- --],
mask = [ True  True False False False False  True  True],
fill_value = 999999)

为什么梯度不是在"新"边界处计算的?我该如何改变它?

对于中间的屏蔽条目,它变得更奇怪:

x = np.array([100, 2, 3, 5, 5, 6, 6, 6, 6, 6, 7, 5, 10, 100])
mx = ma.masked_array(x, mask=[1, 0, 0, 0,0, 0,1,0,0,0, 0, 0, 0, 1])
np.gradient(mx)
masked_array(data = [-- -- 1.5 1.0 0.5 -- 0.0 -- 0.0 0.5 -0.5 1.5 ----],
mask = [ True  True False False False  True False  True False False False False
True  True],
fill_value = 1e+20)

我希望np.gradient只是将被掩盖的细胞视为边界。

更新:

我想做什么: 我需要计算数组上的梯度,而不是更改掩码,也不更改数组的形状(我最终想要 2d) 蒙版单元格不应影响梯度。遮罩像元旁边的点应被视为边界,并应用单侧差值。

- - - - - - - - - - -
- - - - o o - - o - -
- - - o x x o o x o -
- - - o x o - - o - -
- - - - o - - - - - -
- - - - - - - - - - -

在此草图中,x表示一个被屏蔽的单元格,o是应计算单侧差的单元格(该区域边缘的单元格也需要是单侧的,但为了清楚起见,我不在这里绘制它们)。

我认为原因是您希望在计算梯度期间跳过mx数组的屏蔽元素,因此我们将在x = np.array([2, 3, 5, 5, 5, 10])上计算它,而不是在x = np.array([100, 2, 3, 5, 5, 5, 10, 100])上计算梯度,但实际行为是不同的,np.ma.MaskedArray是从np.ndarray继承而来的,np.gradient()不会对np.ndarray或其子类做任何特殊的事情。因此,在mx = ma.masked_array(x, mask=[1, 0, 0, 0, 0, 0, 0, 1])的情况下,梯度将在数组上计算:

[--, 2, 3, 5, 5, 5, 10, --]

首先,它将尝试计算第一个元素的梯度,默认情况下具有一阶差和步长h=1(默认情况下,np.gradient在输入的每个维度中将步数视为一元。

gradient[0] = (mx[1] - mx[0]) / h

因为,这取决于mask不允许使用mx[0]gradient[0]的值将被"True"掩盖。

当它将尝试计算您认为是数组的新左边界的元素的索引 1 处的梯度时;该元素实际上不是ndarray的边界元素。 当它计算您认为是新左边界的元素的梯度时,它实际上将使用具有齐次步长的中心差分公式hgradient[1] = (mx[2] - mx[0]) / 2h,但由于mx[0]被屏蔽为无法使用的公式,因此也无法检索gradient[1]的值,因此它被True屏蔽。同样的情况也发生在数组的另一端。

现在关于掩盖中间的某些内容,假设:

x = np.array([1, 2, 3, 4, 5])
mask = [0, 0, 1, 0, 0]
mx = ma.masked_array(x, mask=mask)    

再次应用于 mx 的梯度函数将使用齐次步长的中心差分公式,当我们计算时:

masked_gradient[1] = (mx[2] - mx[0]) / 2h
masked_gradient[3] = (mx[4] - mx[2]) / 2h

这两个值都无法计算,因为 mx[2] 被True屏蔽。同时:

masked_gradient[2] = (mx[3] - mx[1]) / 2h

可以评估,因为它所依赖的所有值都被屏蔽为False,所以结果将有一个掩码:

[0, 1, 0, 1, 0]

和价值观:

[1.0, --, 1.0, --, 1.0]

它计算的中心差值,不能在边界(或缺失值)附近构造。numpy.gradient在数组的末端切换到单侧差,但屏蔽数组的孔不算作末端。

第二个示例显示了模具中的孔:您可以在数据中的隔离孔计算它。

最新更新