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

Python 如何有效地将布尔numpy数组转换为阈值布尔数组?,python,arrays,numpy,boolean,vectorization,Python,Arrays,Numpy,Boolean,Vectorization,我正在使用Python2.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, Fal

我正在使用Python2.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]]])
我必须将其转换为布尔数组,如下所示:

>>> 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而不使用
进行
循环(非常慢)?

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

这是一个简单的问题。您需要选择每一行。使用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)

以下是一种适用于阵列的方法(也适用于具有更多混合行的阵列,例如
[F,T,T,F,T]
):

说明:

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

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

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

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


您也可以使用异或运算符
^
实现此目的。只需将数组“左移”1,然后将
True
值添加到右侧,然后对新数组和旧数组进行异或运算:

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
值时,这才有效。

这是一个奇怪的转换-基本上,除了上一个False值的索引之外,您正在丢失所有信息。这有什么意义?@Marcin,正如我在问题中所写的,我需要使用生成的数组作为另一个numpy数组的掩码。这个想法是+1,但hildensia版本更快。谢谢:)谢谢,你的答案是最快的!这看起来是一个很有希望的想法-它能与问题中给出的完整数组
a
一起工作吗(而不仅仅是简单的数组)?@ajcr我通过向每个矩阵添加一个维度并用
串联
替换
hstack
。@ProGM感谢您的解释-我非常喜欢这种方法!