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

3

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

我有一个名为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循环(这些循环相当慢)来实现?


这是一种奇怪的转换 - 你基本上失去了除最后一个 False 值的索引以外的所有信息。这样做有什么意义呢? - Marcin
@Marcin,如我所写在问题中,我需要将生成的数组用作另一个NumPy数组的掩码。 - ProGM
4个回答

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)

解释:

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

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

  • 通过添加新的轴(axis=2),使这个新索引数组与A兼容。将这个新数组命名为x

  • 构造一个与A具有相同维数的数组,其中axis=2的每一行都是np.arange(5)。所需的布尔数组可通过将此构造数组与x进行不等式测试来获得。


+1 这个想法不错,但是 hildensia 版本更快。谢谢 :) - ProGM

3

您也可以使用异或运算符^来实现。只需将数组向左移动一位并在右侧添加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值时,这个方法才有效。


谢谢,你的回答是最快的! - ProGM
这看起来是一个很有前途的想法 - 它能够在问题中给出的完整数组A上运行吗(而不仅仅是简单的数组)? - Alex Riley
@ajcr,我通过为每个矩阵添加一个维度并将“hstack”替换为“concatenate”来完成了它。 - ProGM
@ProGM 感谢您的解释 - 我非常喜欢这种方法! - Alex Riley

1
如果您反转数组,就可以使用numpy.nonzero找到所有(原来)为假的条目,然后从中每行取最后一个。然后,您可以使用它来构建掩码数组。

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接