切片numpy。ndarray通过列索引

时间:2023-01-25 21:21:10

Is there a way to slice the array below without having to define the row indices i.e. not having to write range(len(X))?

是否有一种方法可以在不需要定义行索引的情况下分割下面的数组,即不需要写入范围(len(X))?

X = np.arange(10*2).reshape((10,2))
L = np.random.randint(0,2,10)

Xs = X[range(len(X)),L]

I thought it was possible to slice with X[:,L] but looks like it's not.

我以为用X[:,L]切片是可能的,但看起来不是。

3 个解决方案

#1


3  

You're probably looking for np.choose:

您可能正在寻找np.choose:

In [25]: X = np.arange(10*2).reshape((10,2)); X
Out[25]: 
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6,  7],
       [ 8,  9],
       [10, 11],
       [12, 13],
       [14, 15],
       [16, 17],
       [18, 19]])

In [26]: L = np.random.randint(0,2,10); L
Out[26]: array([1, 1, 1, 1, 1, 0, 0, 0, 0, 1])

In [27]: L.choose(X.T)
Out[27]: array([ 1,  3,  5,  7,  9, 10, 12, 14, 16, 19])

In [28]: # or otherwise

In [29]: np.choose(L, X.T)
Out[29]: array([ 1,  3,  5,  7,  9, 10, 12, 14, 16, 19])

Performance note: while this solution is a direct answer to the question, it's quickly becomes not the most optimal with increase of len(X). As of numpy 1.9.0, np.arange approach is faster:

性能说明:虽然这个解决方案直接回答了这个问题,但是随着len(X)的增加,它很快就不是最优的了。从1。9。0到np。不等方法更快:

In [17]: %timeit X[range(len(X)), L]
1000 loops, best of 3: 629 µs per loop

In [18]: %timeit X[np.arange(len(X)), L]
10000 loops, best of 3: 78.8 µs per loop

In [19]: %timeit L.choose(X.T)
10000 loops, best of 3: 146 µs per loop

In [20]: X.shape, L.shape
Out[20]: ((10000, 2), (10000,))

#2


1  

You take the diagonal elements of X[:,L] using diag (or diagonal):

取X[:,L]的对角线元素diag(或对角线):

np.diag(X[:,L])

Another way to do it is with where:

另一种方法是使用where:

np.where(L,X[:,1],X[:,0])

#3


0  

Note that

请注意,

In [9]: X[:, L]
Out[9]:
array([[ 1,  1,  0,  0,  1,  0,  1,  0,  1,  0],
   [ 3,  3,  2,  2,  3,  2,  3,  2,  3,  2],
   [ 5,  5,  4,  4,  5,  4,  5,  4,  5,  4],
   [ 7,  7,  6,  6,  7,  6,  7,  6,  7,  6],
   [ 9,  9,  8,  8,  9,  8,  9,  8,  9,  8],
   [11, 11, 10, 10, 11, 10, 11, 10, 11, 10],
   [13, 13, 12, 12, 13, 12, 13, 12, 13, 12],
   [15, 15, 14, 14, 15, 14, 15, 14, 15, 14],
   [17, 17, 16, 16, 17, 16, 17, 16, 17, 16],
   [19, 19, 18, 18, 19, 18, 19, 18, 19, 18]])

And you want the diagonal elements:

你想要对角线的元素

So just do:

所以只做:

In [14]: X[:, L].diagonal()
Out[14]: array([ 1,  3,  4,  6,  9, 10, 13, 14, 17, 18])

#1


3  

You're probably looking for np.choose:

您可能正在寻找np.choose:

In [25]: X = np.arange(10*2).reshape((10,2)); X
Out[25]: 
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6,  7],
       [ 8,  9],
       [10, 11],
       [12, 13],
       [14, 15],
       [16, 17],
       [18, 19]])

In [26]: L = np.random.randint(0,2,10); L
Out[26]: array([1, 1, 1, 1, 1, 0, 0, 0, 0, 1])

In [27]: L.choose(X.T)
Out[27]: array([ 1,  3,  5,  7,  9, 10, 12, 14, 16, 19])

In [28]: # or otherwise

In [29]: np.choose(L, X.T)
Out[29]: array([ 1,  3,  5,  7,  9, 10, 12, 14, 16, 19])

Performance note: while this solution is a direct answer to the question, it's quickly becomes not the most optimal with increase of len(X). As of numpy 1.9.0, np.arange approach is faster:

性能说明:虽然这个解决方案直接回答了这个问题,但是随着len(X)的增加,它很快就不是最优的了。从1。9。0到np。不等方法更快:

In [17]: %timeit X[range(len(X)), L]
1000 loops, best of 3: 629 µs per loop

In [18]: %timeit X[np.arange(len(X)), L]
10000 loops, best of 3: 78.8 µs per loop

In [19]: %timeit L.choose(X.T)
10000 loops, best of 3: 146 µs per loop

In [20]: X.shape, L.shape
Out[20]: ((10000, 2), (10000,))

#2


1  

You take the diagonal elements of X[:,L] using diag (or diagonal):

取X[:,L]的对角线元素diag(或对角线):

np.diag(X[:,L])

Another way to do it is with where:

另一种方法是使用where:

np.where(L,X[:,1],X[:,0])

#3


0  

Note that

请注意,

In [9]: X[:, L]
Out[9]:
array([[ 1,  1,  0,  0,  1,  0,  1,  0,  1,  0],
   [ 3,  3,  2,  2,  3,  2,  3,  2,  3,  2],
   [ 5,  5,  4,  4,  5,  4,  5,  4,  5,  4],
   [ 7,  7,  6,  6,  7,  6,  7,  6,  7,  6],
   [ 9,  9,  8,  8,  9,  8,  9,  8,  9,  8],
   [11, 11, 10, 10, 11, 10, 11, 10, 11, 10],
   [13, 13, 12, 12, 13, 12, 13, 12, 13, 12],
   [15, 15, 14, 14, 15, 14, 15, 14, 15, 14],
   [17, 17, 16, 16, 17, 16, 17, 16, 17, 16],
   [19, 19, 18, 18, 19, 18, 19, 18, 19, 18]])

And you want the diagonal elements:

你想要对角线的元素

So just do:

所以只做:

In [14]: X[:, L].diagonal()
Out[14]: array([ 1,  3,  4,  6,  9, 10, 13, 14, 17, 18])