当列索引大于每行唯一的某个截止值时,屏蔽数组条目

时间:2014-11-09 00:16:50

标签: python numpy pandas

我希望在列索引大于cutoff[i]的情况下有效地屏蔽具有数十万行和~500列的大数组,0 <= i&lt;行数。

以下是一个例子:

In [2]: x = np.random.randint(0,100,size=24).reshape((6,4)); x
Out[2]:
array([[86, 50, 19, 49],
       [41, 80, 94, 50],
       [36, 58, 66, 50],
       [67, 45, 76, 18],
       [80, 14, 10, 30],
       [25, 90, 44, 38]])

In [3]: cutoff = np.array([10,4,3,2,1,0]); cutoff
Out[3]: array([10,  4,  3,  2,  1,  0])

现在我基本上想要用mask创建一个mask[:, cutoff:]=True,但这当然会给我带来错误。最终结果我正在寻找:

[[86 50 19 49]
 [41 80 94 50]
 [36 58 66 --]
 [67 45 -- --]
 [80 -- -- --]
 [-- -- -- --]]

有更快的方法来执行以下操作吗?

In [4]: mask = np.zeros_like(x)

In [5]: for row in range(x.shape[0]):
   ...:     mask[row, cutoff[row]:] = 1
   ...:

In [6]: mask
Out[6]:
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 1],
       [0, 0, 1, 1],
       [0, 1, 1, 1],
       [1, 1, 1, 1]])

In [7]: np.ma.array(x, mask=mask)
Out[7]:
masked_array(data =
 [[86 50 19 49]
 [41 80 94 50]
 [36 58 66 --]
 [67 45 -- --]
 [80 -- -- --]
 [-- -- -- --]],
             mask =
 [[False False False False]
 [False False False False]
 [False False False  True]
 [False False  True  True]
 [False  True  True  True]
 [ True  True  True  True]],
       fill_value = 999999)

如果它更容易或更快,我可以使用熊猫。

1 个答案:

答案 0 :(得分:2)

您可以使用广播:

cutoff = np.array([10,4,3,2,1,0])
np.arange(4)[None, :] >= cutoff[:, None]

结果如下:

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

或使用ufunc的outer()方法:

np.less_equal.outer(cutoff, np.arange(4))