仅通过第一个位置创建蒙版

时间:2017-09-19 14:06:22

标签: arrays numpy indexing where mask

我有阵列:

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

但这是错误的。

3 个答案:

答案 0 :(得分:2)

您可以使用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

容易出错:带有负数的数组会导致此失败。即对于[-1, 1],这将在第1位评估为True

答案 1 :(得分: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)

答案 2 :(得分:2)

此处有一个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