NumPy使用索引列表选择每行的特定列索引

时间:2014-05-02 19:44:13

标签: python python-2.7 numpy

我很难选择NumPy矩阵每行的特定列。

假设我有以下矩阵,我称之为X

[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

我每行都有list个列索引,我称之为Y

[1, 0, 2]

我需要获取值:

[2]
[4]
[9]

我可以生成与list形状相同的矩阵,而不是Y索引X,其中每列都是bool / {{1}在0-1范围内,表示这是否是必需的列。

int

我知道这可以通过迭代数组并选择我需要的列值来完成。但是,这将在大数据阵列上频繁执行,这就是为什么它必须尽可能快地运行。

我当时想知道是否有更好的解决方案?

谢谢。

7 个答案:

答案 0 :(得分:70)

如果你有一个布尔数组,你可以根据它进行直接选择:

>>> a = np.array([True, True, True, False, False])
>>> b = np.array([1,2,3,4,5])
>>> b[a]
array([1, 2, 3])

与您的初始示例一起,您可以执行以下操作:

>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> b = np.array([[False,True,False],[True,False,False],[False,False,True]])
>>> a[b]
array([2, 4, 9])

您也可以添加arange并对其进行直接选择,但取决于您如何生成布尔数组以及您的代码看起来像YMMV。

>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> a[np.arange(len(a)), [1,0,2]]
array([2, 4, 9])

希望有所帮助,如果您有任何疑问,请与我联系。

答案 1 :(得分:25)

您可以这样做:

In [7]: a = np.array([[1, 2, 3],
   ...: [4, 5, 6],
   ...: [7, 8, 9]])

In [8]: lst = [1, 0, 2]

In [9]: a[np.arange(len(a)), lst]
Out[9]: array([2, 4, 9])

有关索引多维数组的更多信息:http://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays

答案 2 :(得分:6)

最近的numpy版本添加了take_along_axis(和put_along_axis),可以清楚地进行索引编制。

In [101]: a = np.arange(1,10).reshape(3,3)                                                             
In [102]: b = np.array([1,0,2])                                                                        
In [103]: np.take_along_axis(a, b[:,None], axis=1)                                                     
Out[103]: 
array([[2],
       [4],
       [9]])

它的运行方式与

相同
In [104]: a[np.arange(3), b]                                                                           
Out[104]: array([2, 4, 9])

但具有不同的轴处理方式。它特别旨在应用argsortargmax的结果。

答案 3 :(得分:3)

一种简单的方式可能如下:

In [1]: a = np.array([[1, 2, 3],
   ...: [4, 5, 6],
   ...: [7, 8, 9]])

In [2]: y = [1, 0, 2]  #list of indices we want to select from matrix 'a'

range(a.shape[0])将返回array([0, 1, 2])

In [3]: a[range(a.shape[0]), y] #we're selecting y indices from every row
Out[3]: array([2, 4, 9])

答案 4 :(得分:2)

您可以使用迭代器来完成。像这样:

np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int)

时间:

N = 1000
X = np.zeros(shape=(N, N))
Y = np.arange(N)

#@Aशwini चhaudhary
%timeit X[np.arange(len(X)), Y]
10000 loops, best of 3: 30.7 us per loop

#mine
%timeit np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int)
1000 loops, best of 3: 1.15 ms per loop

#mine
%timeit np.diag(X.T[Y])
10 loops, best of 3: 20.8 ms per loop

答案 5 :(得分:1)

作为纯粹的numpythonic方法,您可以使用np.take()从第二轴获取索引,然后结果的对角线将是您的预期输出:

np.diagonal(np.take(arr, idx, axis=1))

演示:

>>> arr = np.array([[1, 2, 3],
... [4, 5, 6],
... [7, 8, 9]])
>>> 
>>> idx = [1, 0, 2]
>>> 
>>> np.diagonal(np.take(arr, idx, axis=1))
array([2, 4, 9])

答案 6 :(得分:0)

另一个聪明的方法是首先转置数组并在之后对其进行索引。最后,走对角线,它始终是正确的答案。

X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
Y = np.array([1, 0, 2, 2])

np.diag(X.T[Y])

一步一步:

原始阵列:

>>> X
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])

>>> Y
array([1, 0, 2, 2])

转置以使其可以正确索引。

>>> X.T
array([[ 1,  4,  7, 10],
       [ 2,  5,  8, 11],
       [ 3,  6,  9, 12]])

按Y顺序获取行。

>>> X.T[Y]
array([[ 2,  5,  8, 11],
       [ 1,  4,  7, 10],
       [ 3,  6,  9, 12],
       [ 3,  6,  9, 12]])

对角线现在应该变得清晰。

>>> np.diag(X.T[Y])
array([ 2,  4,  9, 12]