【问题标题】:Create mask by first positions only仅按第一个位置创建掩码
【发布时间】:2018-02-28 08:49:25
【问题描述】:

我有数组:

a = np.array([[ 0,  1,  2,  0,  0,  0],
              [ 0,  4,  1, 35,  0, 10],
              [ 0,  0,  5,  4,  0,  4],
              [ 1,  2,  5,  4,  0,  4]])

我只需要从每行中第一个连续的0 中选择:

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

我试试:

a[np.arange(len(a)), a.argmax(1): np.arange(len(a)), [0,0,0]] = True

但这是错误的。

【问题讨论】:

  • @BradSolomon - 是的,完全正确。第一个连续。
  • 我正在寻找解决方案很长时间,但没有成功:(
  • 第一个零应该总是从头开始还是可以在行的中间?或者2,4,0,0,4,5 怎么样?应该选择零吗?
  • @Psidom - 好问题。我认为并不总是应该开始。

标签: arrays numpy indexing where mask


【解决方案1】:

这是argmin + broadcasting -

(a==0).argmin(1)[:,None] > np.arange(a.shape[1])

示例分步运行说明

1) 输入数组:

In [207]: a
Out[207]: 
array([[ 0,  1,  2,  0,  0,  0],
       [ 0,  4,  1, 35,  0, 10],
       [ 0,  0,  5,  4,  0,  4],
       [ 1,  2,  5,  4,  0,  4]])

2) 零掩码

In [208]: (a==0)
Out[208]: 
array([[ True, False, False,  True,  True,  True],
       [ True, False, False, False,  True, False],
       [ True,  True, False, False,  True, False],
       [False, False, False, False,  True, False]], dtype=bool)

3) 获取 False 出现的索引,表示每行第一个 True 岛的结束。因此,对于没有零或第一个元素非零的任何行,将导致 argmin 输出为0。因此,我们的下一个任务是使用broadcasting 创建一个掩码,该掩码从第一行开始为True,并在那些argmin 索引处停止为True。这将是一个 broadcasted-comparison 对一个范围数组扩展覆盖所有列。

In [209]: (a==0).argmin(1)
Out[209]: array([1, 1, 2, 0])

In [210]: (a==0).argmin(1)[:,None] > np.arange(a.shape[1])
Out[210]: 
array([[ True, False, False, False, False, False],
       [ True, False, False, False, False, False],
       [ True,  True, False, False, False, False],
       [False, False, False, False, False, False]], dtype=bool)

时间安排

In [196]: a = np.random.randint(0,9,(5000,5000))

In [197]: %timeit a.cumsum(axis=1) == 0 #@Brad Solomon
     ...: %timeit np.minimum.accumulate(a == 0, axis=1) #@Psidom
     ...: %timeit (a==0).argmin(1)[:,None] > np.arange(a.shape[1])
     ...: 
10 loops, best of 3: 69 ms per loop
10 loops, best of 3: 64.9 ms per loop
10 loops, best of 3: 32.8 ms per loop

【讨论】:

    【解决方案2】:

    您可以使用np.minimum.accumulate 和条件测试a == 0(在行上);由于非零给出False,因此第一个非零之后的元素将设置为False,因为累积最小值:

    np.minimum.accumulate(a == 0, axis=1)
    #array([[ True, False, False, False, False, False],
    #       [ True, False, False, False, False, False],
    #       [ True,  True, False, False, False, False],
    #       [False, False, False, False, False, False]], dtype=bool)
    

    【讨论】:

      【解决方案3】:

      您可以使用np.cumsum

      假设:您只在每行的开头寻找零。

      a = np.array([[ 0,  1,  2,  0,  0,  0],
                    [ 0,  4,  1, 35,  0, 10],
                    [ 0,  0,  5,  4,  0,  4]])
      
      a.cumsum(axis=1) == 0
      array([[ True, False, False, False, False, False],
             [ True, False, False, False, False, False],
             [ True,  True, False, False, False, False]], dtype=bool)
      

      基础:只要每行的累积总和为 0,就保持 True

      容易出错:带有负整数的数组会导致失败。 IE。对于 [-1, 1],这将在位置 1 处计算为 True

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多