web-dev-qa-db-ja.com

NumPyはインデックスのリストを使用して行ごとに特定の列インデックスを選択します

NumPyマトリックスの行ごとに特定の列を選択するのに苦労しています。

Xと呼ぶ次のマトリックスがあるとします。

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

また、listと呼ぶすべての行ごとに、Yの列インデックスがあります。

[1, 0, 2]

値を取得する必要があります:

[2]
[4]
[9]

インデックスlistを持つYの代わりに、すべての列が0-1値の範囲のX/boolであるintと同じ形状の行列を作成することもできます。これは必須列かどうかを示します。

[0, 1, 0]
[1, 0, 0]
[0, 0, 1]

これは、配列を繰り返し処理し、必要な列の値を選択することで実行できることを知っています。ただし、これはデータの大きな配列で頻繁に実行されるため、できるだけ速く実行する必要があります。

したがって、より良い解決策があるかどうか疑問に思っていましたか?

ありがとうございました。

68
Zee

ブール配列を持っている場合、それに基づいて直接選択することができます。

>>> 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])

ブール配列をどのように生成しているか、コードがYMMVのように見えるかどうかにもよりますが、arangeを追加して直接選択することもできます。

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

それがお役に立てば幸いです。さらに質問がある場合はお知らせください。

73

次のようなことができます:

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

25

簡単な方法は次のようになります。

_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])
_
3
Dhaval Mayatra

イテレータを使用して実行できます。このような:

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
2
Kei Minagawa

純粋なnumpythonicアプローチとして、np.take()を使用して2番目の軸からインデックスを取得できます。結果の対角線は期待される出力になります。

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])
1
Kasrâmvd

別の賢い方法は、最初に配列を転置し、その後インデックスを付けることです。最後に、常に正しい答えである対角線を取ります。

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]
0
Thomas Devoogdt