【问题标题】:Mask out specific values from an array屏蔽数组中的特定值
【发布时间】:2016-12-25 05:38:48
【问题描述】:

例子:

我有一个数组:

array([[1, 2, 0, 3, 4],
       [0, 4, 2, 1, 3],
       [4, 3, 2, 0, 1],
       [4, 2, 3, 0, 1],
       [1, 0, 2, 3, 4],
       [4, 3, 2, 0, 1]], dtype=int64)

我有一组“坏”值(长度可变,顺序无关紧要):

{2, 3}

我想返回隐藏这些值的掩码:

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

在 NumPy 中最简单的方法是什么?

【问题讨论】:

    标签: python arrays numpy membership


    【解决方案1】:

    使用np.in1d 为我们提供此类匹配事件的展平掩码,然后重新整形为所需输出的输入数组形状,就像这样 -

    np.in1d(a,[2,3]).reshape(a.shape)
    

    请注意,我们需要将要搜索的数字作为列表或数组输入。

    示例运行 -

    In [5]: a
    Out[5]: 
    array([[1, 2, 0, 3, 4],
           [0, 4, 2, 1, 3],
           [4, 3, 2, 0, 1],
           [4, 2, 3, 0, 1],
           [1, 0, 2, 3, 4],
           [4, 3, 2, 0, 1]])
    
    In [6]: np.in1d(a,[2,3]).reshape(a.shape)
    Out[6]: 
    array([[False,  True, False,  True, False],
           [False, False,  True, False,  True],
           [False,  True,  True, False, False],
           [False,  True,  True, False, False],
           [False, False,  True,  True, False],
           [False,  True,  True, False, False]], dtype=bool)
    

    2018 版:numpy.isin

    使用 NumPy 内置的 np.isin(在 1.13.0 中引入)保持形状,因此不需要我们之后重新整形 -

    In [153]: np.isin(a,[2,3])
    Out[153]: 
    array([[False,  True, False,  True, False],
           [False, False,  True, False,  True],
           [False,  True,  True, False, False],
           [False,  True,  True, False, False],
           [False, False,  True,  True, False],
           [False,  True,  True, False, False]])
    

    【讨论】:

      【解决方案2】:
      In [965]: np.any([x==i for i in (2,3)],axis=0)
      Out[965]: 
      array([[False,  True, False,  True, False],
             [False, False,  True, False,  True],
             [False,  True,  True, False, False],
             [False,  True,  True, False, False],
             [False, False,  True,  True, False],
             [False,  True,  True, False, False]], dtype=bool)
      

      这确实会迭代,但如果(2,3) 集很小(相对于x 的大小),则相对较快。事实上对于小arr2np.in1d 是这样做的:

              mask = np.zeros(len(ar1), dtype=np.bool)
              for a in ar2:
                  mask |= (ar1 == a)
      

      由此创建一个掩码数组:

      In [970]: np.ma.MaskedArray(x,mask)
      Out[970]: 
      masked_array(data =
       [[1 -- 0 -- 4]
       [0 4 -- 1 --]
       [4 -- -- 0 1]
       [4 -- -- 0 1]
       [1 0 -- -- 4]
       [4 -- -- 0 1]],
                   mask =
       [[False  True False  True False]
       [False False  True False  True]
       [False  True  True False False]
       [False  True  True False False]
       [False False  True  True False]
       [False  True  True False False]],
             fill_value = 999999)
      

      【讨论】:

      • [x==i for i in (2,3)] 将占用N 倍于最终输出的内存,N 是搜索数组中元素的数量。提问者发布示例,这不一定是他们处理那些确切的小输入,特别是在他们寻找性能时。
      • in1d 的循环等效项节省了更大的内存使用。速度应该是一样的。但我们必须进行测试。它可能不是所有情况的最佳解决方案,但我认为这是一个很好的基本解决方案。
      • 是的,np.in1d 会有函数包装器开销,但我认为大部分性能相当。
      【解决方案3】:

      可能有比这更简单的方法。但这可能是一种方式:

      import numpy as np
      
      a = np.array([[1, 2, 0, 3, 4],
             [0, 4, 2, 1, 3],
             [4, 3, 2, 0, 1],
             [4, 2, 3, 0, 1],
             [1, 0, 2, 3, 4],
             [4, 3, 2, 0, 1]], dtype=np.int64)
      
      f = np.vectorize(lambda x: x in {2,3})
      print f(a)
      

      输出:

      [[False  True False  True False]
       [False False  True False  True]
       [False  True  True False False]
       [False  True  True False False]
       [False False  True  True False]
       [False  True  True False False]]
      

      【讨论】:

      • vectorize 只是一个 for 循环,不是吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-07
      • 1970-01-01
      • 2023-01-20
      • 1970-01-01
      相关资源
      最近更新 更多