如何有效地将布尔numpy数组转换为阈值布尔数组?

时间:2014-10-24 09:28:37

标签: python arrays numpy boolean vectorization

我正在使用 Python 2.7 NumPy 来处理大型布尔值数组。

我有一个数组A,就像这样:

>>> A
array([[[False, False, True, True, True],
        [False, False, False, True, True],
        [False, False, True, True, True],
        [False, False, False, True, True],
        [False, False, False, False, True]],

       [[False, True, True, True, True],
        [False, True, True, True, True],
        [False, False, True, True, True],
        [False, True, True, True, True],
        [False, False, True, True, True]]])

我必须把它转换成这样的布尔数组:

>>> B
array([[[True, False, True, True, True],
        [True, True, False, True, True],
        [True, False, True, True, True],
        [True, True, False, True, True],
        [True, True, True, False, True]],

       [[False, True, True, True, True],
        [False, True, True, True, True],
        [True, False, True, True, True],
        [False, True, True, True, True],
        [True, False, True, True, True]]])

因此,我们的想法是每行的最后False值应保留,任何其他值应为True。 我需要创建它才能将它用作另一个数组的掩码。

有没有办法用 NumPy 而不使用for循环(这很慢)?

4 个答案:

答案 0 :(得分:3)

这是一种适用于您的数组的方法(也适用于具有更多混合行的数组,例如[F, T, T, F, T]):

>>> x = 4 - np.argmin(A[:,:,::-1], axis=2)[:,:,np.newaxis]
>>> (np.arange(5) * np.ones_like(A)) != x
array([[[ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True,  True,  True, False,  True]],

       [[False,  True,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True]]], dtype=bool)

说明:

  • 翻转A上的数组axis=2并在该轴上使用argmin以获取第一个False值的索引。

  • 我们需要知道FalseA的最后一次出现的索引(不是翻转数组中的第一次出现)。这是数组深度(即5)减去1的值减去前一步骤中找到的索引。

  • 通过添加新轴(A)使这个新的索引数组与axis=2兼容。调用这个新的索引数组x

  • 构建与A相同维度的数组,其中axis=2的每一行都是np.arange(5)。通过使用x测试此构造数组的不等式,可以找到所需的布尔数组。

答案 1 :(得分:3)

您也可以使用xor运算符^来实现此目的。简单地将数组“leftshift”为1,并向右添加True值,然后xor为新数组和旧数组:

A = np.array([[False, False, True, True, True],
              [False, False, False, True, True],
              [False, False, True, True, True],
              [False, False, False, True, True],
              [False, False, False, False, True]])

X = np.hstack((A[:,1:], 
               np.array(np.ones((A.shape[0], 1)), dtype=np.bool))))
>>> array([[False, True, True, True, True],
           [False, False, True, True, True],
           [False, True, True, True, True],
           [False, False, True, True, True],
           [False, False, False, True, True]])

np.invert(A ^ X)
>>> array([[True, False, True, True, True],
           [True, True, False, True, True],
           [True, False, True, True, True],
           [True, True, False, True, True],
           [True, True, True, False, True]])

此功能仅在保留所有False值且仅后跟True值的情况下有效。

答案 2 :(得分:1)

如果反转数组,可以使用numpy.nonzero查找所有(最初)错误条目,然后从中获取每行中的最后一个。然后,您可以使用它来构建掩码数组。

答案 3 :(得分:0)

这是一个简单的问题。您需要选择每一行。使用 np.where()找到 False 的位置,并将 True 放在除索引[ - 表示的最后一个]之外的其他位置1] 即可。这是在下面给出的代码中完成的:

>>> import numpy as np
>>> A=np.array([[[False, False, True, True, True],
         [False, False, False, True, True],
         [False, False, True, True, True],
         [False, False, False, True, True],
         [False, False, False, False, True]],

        [[False, True, True, True, True],
         [False, True, True, True, True],
         [False, False, True, True, True],
         [False, True, True, True, True],
         [False, False, True, True, True]]])

>>> for mat in A:
     opmat=[]
     for arr in mat:
         index=np.where(arr==False)
         arr[index[0][:-1]]=True
         opmat.append(arr)
     out.append(opmat)

>>> out=np.array(out)
>>> out
array([[[ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True,  True,  True, False,  True]],

       [[False,  True,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True]]], dtype=bool)