当我在 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
的边界元素。 当它计算您认为是新左边界的元素的梯度时,它实际上将使用具有齐次步长的中心差分公式h
、gradient[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
在数组的末端切换到单侧差,但屏蔽数组的孔不算作末端。
第二个示例显示了模具中的孔:您可以在数据中的隔离孔中计算它。