仍在访问numpy蒙版数组填充值

时间:2015-04-01 00:04:00

标签: python arrays numpy indexing

我正在尝试将图像处理为屏蔽数组以处理NoData区域。我决定先在一维数组上进行一些测试,看到奇怪的东西。这是我的测试代码:

    a = np.array([0,1,4,3,4,-9999,33,34,-9999])
    am = np.ma.MaskedArray(a)
    am.mask = (am==-9999)

    z = np.arange(35)

    z[am]

我希望用掩码数组索引z数组会成功,但我看到以下错误:

    Runtime error 
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    IndexError: index -9999 is out of bounds for size 35

有人可以评论如何正确编码吗?我可以成功运行以下命令:

    z[a[a>0]]

这实际上是一回事。

谢谢!

2 个答案:

答案 0 :(得分:1)

试试此代码

a = np.array([0,1,4,3,4,-9999,33,34,-9999])
am = np.ma.MaskedArray(a)
am.mask = (am==-9999)
np.ma.set_fill_value(am, 0)

z = np.arange(35)

print z[am.filled()]

访问am给出了蒙版数组,其中蒙版值引用原始值(它只是对原始数组的引用)。设置fill_value后调用am.filled()将fill_value替换为fill_value am.filled

返回的数组

答案 1 :(得分:1)

使用标记数组进行索引通常是一个坏主意,正是因为应该在屏蔽值处发生的行为未定义。

以这种方式思考:当我查看您的数组a和数组z时,我可以说&#34;好的,a[0] = 0所以z[a[0]]使感&#34。依此类推,直到我遇到a[5] = -9999,当我可以说,&#34;好的,那作为z&#34;的索引才有意义。并且可以引发异常。

事实上,当您天真地使用am作为索引集时会发生什么......它将恢复为使用包含原始值的所有am.data。如果它试图使用类似[z[i] for i in am]之类的东西,你会遇到遇到numpy.ma.core.MaskedConstant的问题,这对于索引不是一个明智的价值 - 不是为了获取值而是为了忽略请求获取值

In [39]: l = [x for x in am]

In [40]: l
Out[40]: [0, 1, 4, 3, 4, masked, 33, 34, masked]

In [41]: type(l[-1])
Out[41]: numpy.ma.core.MaskedConstant

(事实上,如果你尝试为其中一个人编制索引,你会得到IndexError: arrays used as indices must be of integer (or boolean) type)。

但是现在如果我遇到am.filled()中的蒙版值会怎样? am.filled()的第5个索引处的条目不是numpy.ma.core.MaskedConstant的实例 - 它将是您选择的任何填充值。如果该填充值作为索引有意义,那么您实际上将通过索引该索引来获取值。以0为例。它似乎是一个无害的,中立的填充值,但实际上它代表了一个有效的索引,因此你可以获得对z的第0个条目的两次额外访问:

In [42]: am.fill_value = 0

In [43]: z[am.filled()]
Out[43]: array([ 0,  1,  4,  3,  4,  0, 33, 34,  0])

这并不是面具应该做的事情!

一种半生不熟的方法是迭代am并排除任何type np.ma.core.MaskedConstant的内容:

In [45]: z[np.array([x for x in am if type(x) is not np.ma.core.MaskedConstant])]
Out[45]: array([ 0,  1,  4,  3,  4, 33, 34])

但真正更明确地表达所有这一切只是首先使用简单的逻辑索引:

In [47]: z[a[a != -9999]]
Out[47]: array([ 0,  1,  4,  3,  4, 33, 34])

请注意,像这样的逻辑索引对于2D数组可以正常工作,只要您愿意接受一旦逻辑上对更高维数组进行索引,如果结果不再符合相同的常规2D形状,然后它将以1D呈现,如下:

In [58]: a2 = np.array([[10, -9999, 13], [-9999, 1, 8], [1, 8, 1]])

In [59]: a2
Out[59]: 
array([[   10, -9999,    13],
       [-9999,     1,     8],
       [    1,     8,     1]])

In [60]: z2 = np.random.rand(3,3)

In [61]: z2[np.where(a2 != -9999)]
Out[61]: 
array([ 0.4739082 ,  0.13629442,  0.46547732,  0.87674102,  0.08753297,
        0.57109764,  0.39722408])

如果你想要一个类似于蒙版效果的东西,你可以设置等于NaN的值(对于float数组):

In [66]: a2 = np.array([[10, -9999, 13], [-9999, 1, 8], [1, 8, 1]], dtype=np.float)

In [67]: a2
Out[67]: 
array([[  1.00000000e+01,  -9.99900000e+03,   1.30000000e+01],
       [ -9.99900000e+03,   1.00000000e+00,   8.00000000e+00],
       [  1.00000000e+00,   8.00000000e+00,   1.00000000e+00]])

In [68]: a2[np.where(a2 == -9999)] = np.NaN

In [69]: a2
Out[69]: 
array([[ 10.,  nan,  13.],
       [ nan,   1.,   8.],
       [  1.,   8.,   1.]])

这种使用NaN进行屏蔽的形式适用于NumPy中的大量矢量化数组计算,尽管担心首先将基于整数的图像数据转换为浮点并且安全地转换回来可能会很麻烦结束。