12

これが冗長または超基本的である場合はご容赦ください。私は R から Python/Numpy に来て、頭の中で物事をひっくり返すのに苦労しています。

インデックス値の別の n 次元配列を使用して並べ替えたい次元配列があります。これをループでラップできることはわかっていますが、これを打ち負かして提出するための非常に簡潔な Numpyonic の方法が必要なようです。n=2 の問題を設定するコード例を次に示します。

a1 = random.standard_normal(size=[2,5]) 
index = array([[0,1,2,4,3] , [0,1,2,3,4] ]) 

これで、乱数の 2 x 5 配列と 2 x 5 インデックスができました。ヘルプを 10 回ほど読んだことがありますtake()が、明らかに、私の脳はそれを理解していません。

私はこれが私をそこに連れて行くかもしれないと思った:

take(a1, index)

array([[ 0.29589188, -0.71279375, -0.18154864, -1.12184984,  0.25698875],
       [ 0.29589188, -0.71279375, -0.18154864,  0.25698875, -1.12184984]])

しかし、それは明らかに最初の要素のみを並べ替えています(平坦化のためだと思います)。

a1 の要素 0 をインデックス ... 要素 n の要素 0 でソートするソリューションに、現在の場所からどのように到達するかについてのヒントはありますか?

4

2 に答える 2

13

これを 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]

aN 次元では複雑になりますが、上で定義した 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]]])

を生成i1i2て呼び出される便利な numpy 関数np.mgridnp.ogrid前に話した派手な魔法のため、この場合は同等の答えを使用します。

それが役立つことを願っています!

于 2012-06-06T21:11:17.367 に答える
3

今日これをもう少し遊んだ後、テイクと一緒にマッパー関数を使用すると、2次元バージョンを次のように簡単に解くことができることがわかりました。

a1 = random.standard_normal(size=[2,5]) 
index = array([[0,1,2,4,3] , [0,1,2,3,4] ]) 
map(take, a1, index)

map()私はのtake()各要素に必要でしたa1

もちろん、受け入れられた答えはn次元バージョンを解決します。しかし、振り返ってみると、私は実際にはn次元のソリューションは必要なく、2次元バージョンのみが必要であると判断しました。

于 2012-06-07T16:45:09.420 に答える