根据布尔向量选择numpy中的列

时间:2015-01-03 23:13:55

标签: python arrays numpy

我有两个NumPy数组ab,尺寸为m n。我有一个长度为b的布尔向量n,我想生成一个新数组c,它会从n中选择a列,{{1如果b为真,我从b[i]开始,而不是b

我如何以最有效的方式做到这一点? 我查看了aselectwhere

3 个答案:

答案 0 :(得分:4)

首先,让我们设置一些示例代码:

import numpy as np

m, n = 5, 3
a = np.zeros((m, n))
b = np.ones((m, n))

boolvec = np.random.randint(0, 2, m).astype(bool)

只是为了显示这些数据的样子:

In [2]: a
Out[2]: 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

In [3]: b
Out[3]: 
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

In [4]: boolvec
Out[4]: array([ True,  True, False, False, False], dtype=bool)

在这种情况下,使用np.where进行此操作效率最高。但是,我们需要boolvec的形状可以广播到与ab相同的形状。因此,我们可以通过使用np.newaxisNone进行切片使它成为列向量(它们相同):

In [5]: boolvec[:,None]
Out[5]: 
array([[ True],
       [ True],
       [False],
       [False],
       [False]], dtype=bool)

然后我们可以使用np.where

制作最终结果
In [6]: c = np.where(boolvec[:, None], a, b)

In [7]: c
Out[7]: 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

答案 1 :(得分:4)

您可以使用np.choose

例如ab数组:

>>> a = np.arange(12).reshape(3,4)
>>> b = np.arange(12).reshape(3,4) + 100
>>> a_and_b = np.array([a, b])

要使用np.choose,我们需要一个包含两个数组的3D数组; a_and_b看起来像这样:

array([[[  0,   1,   2,   3],
        [  4,   5,   6,   7],
        [  8,   9,  10,  11]],

       [[100, 101, 102, 103],
        [104, 105, 106, 107],
        [108, 109, 110, 111]]])

现在让布尔数组为bl = np.array([0, 1, 1, 0])。然后:

>>> np.choose(bl, a_and_b)
array([[  0, 101, 102,   3],
       [  4, 105, 106,   7],
       [  8, 109, 110,  11]])

答案 2 :(得分:3)

(5000,3000)阵列的计时是:

In [107]: timeit np.where(boolvec[:,None],b,a)
1 loops, best of 3: 993 ms per loop

In [108]: timeit np.choose(boolvec[:,None],[a,b])
1 loops, best of 3: 929 ms per loop

In [109]: timeit c=a[:];c[boolvec,:]=b[boolvec,:]
1 loops, best of 3: 786 ms per loop

wherechoose基本相同;布尔索引略快一些。 select使用choose,因此我没有时间。


我的列采样时间相似,但这次索引速度较慢:

In [119]: timeit np.where(cols,b,a)
1 loops, best of 3: 878 ms per loop

In [120]: timeit np.choose(cols,[a,b])
1 loops, best of 3: 915 ms per loop

In [121]: timeit c=a[:];c[:,cols]=b[:,cols]
1 loops, best of 3: 1.25 s per loop

更正,对于索引,我应该使用a.copy()

In [32]: timeit c=a.copy();c[boolvec,:]=b[boolvec,:]
1 loops, best of 3: 783 ms per loop
In [33]: timeit c=a.copy();c[:,cols]=b[:,cols]
1 loops, best of 3: 1.44 s per loop

我得到了Python2.7和3,numpy 1.8.2和1.9.0 dev

的相同时间