【问题标题】:How to efficiently turn a boolean numpy array into threshold boolean array?如何有效地将布尔 numpy 数组转换为阈值布尔数组?
【发布时间】:2014-12-20 03:08:38
【问题描述】:

我正在使用 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 正如我在问题中所写,我需要使用生成的数组作为另一个 numpy 数组的掩码。

标签: python arrays numpy boolean vectorization


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这是一个简单的问题。您需要选择每一行。使用 np.where() 找到 False 的位置,并将 True 放置在除了由 index [- 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)
    

    【讨论】:

      【解决方案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 版本更快。谢谢你:)
      【解决方案4】:

      您也可以为此目的使用 xor 运算符 ^。只需将数组“左移”一位并将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 值的情况。

      【讨论】:

      • 谢谢,你的回复是最快的!
      • 这看起来是一个很有前途的想法 - 是否可以使用问题中给出的完整数组 A(而不仅仅是更简单的数组)?
      • @ajcr 我通过为每个矩阵添加一个维度并将hstack 替换为concatenate 来做到这一点。
      • @ProGM 感谢您的解释 - 我非常喜欢这种方法!
      猜你喜欢
      • 1970-01-01
      • 2014-12-22
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 2013-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多