これを N 次元でどのように機能させるかはまだ考えられませんが、2D バージョンは次のとおりです。
>>> a = np.random.standard_normal(size=(2,5))
>>> a
array([[ 0.72322499, -0.05376714, -0.28316358, 1.43025844, -0.90814293],
[ 0.7459107 , 0.43020728, 0.05411805, -0.32813465, 2.38829386]])
>>> i = np.array([[0,1,2,4,3],[0,1,2,3,4]])
>>> a[np.arange(a.shape[0])[:,np.newaxis],i]
array([[ 0.72322499, -0.05376714, -0.28316358, -0.90814293, 1.43025844],
[ 0.7459107 , 0.43020728, 0.05411805, -0.32813465, 2.38829386]])
N 次元バージョンは次のとおりです。
>>> a[list(np.ogrid[[slice(x) for x in a.shape]][:-1])+[i]]
仕組みは次のとおりです。
では、説明のために 3 次元配列から始めましょう。
>>> import numpy as np
>>> a = np.arange(24).reshape((2,3,4))
>>> a
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
次のように、各軸に沿ってインデックスを指定することで、この配列の要素にアクセスできます。
>>> a[0,1,2]
6
これはa[0][1][2]
、配列ではなくリストを扱っている場合に同じ要素にアクセスする方法と同じです。
Numpy を使用すると、配列をスライスするときにさらに手の込んだことができます。
>>> a[[0,1],[1,1],[2,2]]
array([ 6, 18])
>>> a[[0,1],[1,2],[2,2]]
array([ 6, 22])
これらの例は、リストを扱っている場合[a[0][1][2],a[1][1][2]]
と同等です。[a[0][1][2],a[1][2][2]]
繰り返されるインデックスを除外することもでき、numpy は必要なものを見つけ出します。たとえば、上記の例は同等に記述できます。
>>> a[[0,1],1,2]
array([ 6, 18])
>>> a[[0,1],[1,2],2]
array([ 6, 22])
各次元でスライスする配列 (またはリスト) の形状は、返される配列の形状にのみ影響します。言い換えれば、numpy は、(2,3,4)
値をプルするときに shape の配列で配列にインデックスを付けようとしていることを気にしませんが、 shape の配列をフィードバックすることを除きます(2,3,4)
。例えば:
>>> a[[[0,0],[0,0]],[[0,0],[0,0]],[[0,0],[0,0]]]
array([[0, 0],
[0, 0]])
この場合、同じ要素をa[0,0,0]
何度も取得していますが、numpy は渡したものと同じ形状の配列を返しています。
わかりました、あなたの問題に。あなたが望むのは、配列内の数値を使用して、最後の軸に沿って配列にインデックスを付けることですindex
。したがって、あなたの質問の例については、[[a[0,0],a[0,1],a[0,2],a[0,4],a[0,3]],a[1,0],a[1,1],...
先に述べたように、インデックス配列が多次元であるという事実は、これらのインデックスをどこから取得するかについて numpy に何も伝えません。出力配列の形状を指定するだけです。したがって、あなたの例では、最初の 5 つの値が からプルされa[0]
、後者の 5 が からプルされることを numpy に伝える必要がありますa[1]
。簡単!
>>> a[[[0]*5,[1]*5],index]
a
N 次元では複雑になりますが、上で定義した 3 次元配列に対して実行してみましょう。次のインデックス配列があるとします。
>>> i = np.array(range(4)[::-1]*6).reshape(a.shape)
>>> i
array([[[3, 2, 1, 0],
[3, 2, 1, 0],
[3, 2, 1, 0]],
[[3, 2, 1, 0],
[3, 2, 1, 0],
[3, 2, 1, 0]]])
したがって、これらの値はすべて、最後の軸に沿ったインデックスに対するものです。これらの数値が取得される最初と 2 番目の軸に沿ったインデックスを numpy に伝える必要があります。つまり、最初の軸のインデックスが次のとおりであることを numpy に伝える必要があります。
i1 = [[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]]
2 番目の軸のインデックスは次のとおりです。
i2 = [[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2]],
[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2]]]
次に、次のことができます。
>>> a[i1,i2,i]
array([[[ 3, 2, 1, 0],
[ 7, 6, 5, 4],
[11, 10, 9, 8]],
[[15, 14, 13, 12],
[19, 18, 17, 16],
[23, 22, 21, 20]]])
を生成i1
しi2
て呼び出される便利な numpy 関数np.mgrid
。np.ogrid
前に話した派手な魔法のため、この場合は同等の答えを使用します。
それが役立つことを願っています!