2016-02-05 10 views
6

これはのリシェイプの使用に関するもので、多次元スケールでこの軸がどのように使用されているかを示しています。numpy任意の軸を介して多次元配列を再整形

最初のインデックスでインデックスされた行列を含む次の配列があるとします。 私が達成したいのは、代わりに最初のインデックスで各マトリックスの列を索引付けすることです。この問題を説明するために、次の例を考えてみましょう。ここでは、最初のインデックスを持つ行列をインデックスするnumpy配列がzです。 zは次のようになります

x = np.arange(9).reshape((3, 3)) 
y = np.arange(9, 18).reshape((3, 3)) 
z = np.dstack((x, y)).T 

array([[[ 0, 3, 6], 
    [ 1, 4, 7], 
    [ 2, 5, 8]], 

    [[ 9, 12, 15], 
    [10, 13, 16], 
    [11, 14, 17]]]) 

、その形状は(2, 3, 3)です。ここで、第1のインデックスは2つの画像であり、3つのx 3はマトリックスである。

形状 (6, 3)ある
array([[ 0, 1, 2], 
    [ 3, 4, 5], 
    [ 6, 7, 8], 
    [ 9, 10, 11], 
    [12, 13, 14], 
    [15, 16, 17]]) 

より具体的には、その後言い回し質問は、以下所望の出力を得るために変形を使用する方法です。これは、配列の次元が上記のように行列xとyの列を指数化することを達成する。私の自然傾きは、次のようにZに直接再構築を使用することでした:

out = z.reshape(2 * 3, 3) 

しかし、その出力は、インデックス行列の行と列ではない以下の通りである:

array([[ 0, 3, 6], 
    [ 1, 4, 7], 
    [ 2, 5, 8], 
    [ 9, 12, 15], 
    [10, 13, 16], 
    [11, 14, 17]] 

でした上記の所望の出力を得るために再形成を使用するか?または、より一般的には、リシェイプ機能を使用すると、各軸の使用方法を制御できますか?

2つのこと:

  • 私はこの問題を解決する方法を知っています。転置された大きな行列(z)の各要素を調べ、上記のように変形を適用することができます。これは計算時間を少し増加させ、実際に問題にはなりません。しかし、それは一般化されず、Pythonを感じません。だから私はこれを行うための標準的な啓発された方法があるかどうか疑問に思っていた。

  • 私はこの質問をどのようにフレーズするかについて明確ではありませんでした。もし誰かがこの問題をより良く表現する方法を提案しているなら、私はすべての耳です。

答えて

7

すべての配列は、その要素に対して自然な(1Dフラット)順序を持っています。 「自然順」に、0と1が遠く離れていることを

In [54]: z.ravel() 
Out[54]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [55]: z.ravel().reshape(2*3, 3) 
Out[55]: 
array([[ 0, 3, 6], 
     [ 1, 4, 7], 
     [ 2, 5, 8], 
     [ 9, 12, 15], 
     [10, 13, 16], 
     [11, 14, 17]]) 

はご注意:あなたは、配列を再構築するとき、それが(したがって自然の秩序を取得する)最初の平坦化した後、再形成されたているかのように、それはです。これは、この場合にすることにより行うことができるいくつかの並べ替えを必要とし、

desired = np.array([[ 0, 1, 2], 
        [ 3, 4, 5], 
        [ 6, 7, 8], 
        [ 9, 10, 11], 
        [12, 13, 14], 
        [15, 16, 17]]) 

:あなたはそれを再構築しかし、0と1を使用して、希望のアレイで欲しいものである最後の軸に沿って互いに隣接されませんswapaxes

In [53]: z.swapaxes(1,2).reshape(2*3, 3) 
Out[53]: 
array([[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8], 
     [ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]]) 

所望の順序での場所の値を

In [56]: z.swapaxes(1,2).ravel() 
Out[56]: 
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
     17]) 

In [57]: desired.ravel() 
Out[57]: 
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
     17]) 

swapaxes(1,2)ためreshape方法は、01を持っていることパラメータは、要素が配列から読み込まれ、再構成された配列に配置される(CまたはF-)順序を制御するために使用できます。しかし、私はこれがあなたの場合に役立つとは思わない。 reshapeの限界を考える


別の方法ほつれが続くすべての整形が同じであるということである:希望のアレイのラヴェルが異なっているのであれば、ノーあり

In [71]: z.reshape(3,3,2).ravel() 
Out[71]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [72]: z.reshape(3,2,3).ravel() 
Out[72]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [73]: z.reshape(3*2,3).ravel() 
Out[73]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [74]: z.reshape(3*3,2).ravel() 
Out[74]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

それを得るための方法は、再形成するだけです。

In [109]: z.reshape(2,3,3, order='F').ravel(order='F') 
Out[109]: 
array([ 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 
     17]) 

In [110]: z.reshape(2*3*3, order='F').ravel(order='F') 
Out[110]: 
array([ 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 
     17]) 

In [111]: z.reshape(2*3,3, order='F').ravel(order='F') 
Out[111]: 
array([ 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 
     17]) 

2つの整形使用して、所望の配列を得ることが可能である:

In [83]: z.reshape(2, 3*3, order='F').reshape(2*3, 3) 
Out[83]: 
array([[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8], 
     [ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]]) 
をあなたもorder='F'とラヴェル提供


同じことがorder='F'と再形成のために行きます、

しかし、私はこれを驚いた。


私は完全にあなたの質問やxを誤解してきたとyがギブンス(ないz)であれば、あなたはrow_stack代わりのdstackを用いて所望の配列を得ることができます:

In [88]: z = np.row_stack([x, y]) 

In [89]: z 
Out[89]: 
array([[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8], 
     [ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]]) 
+0

ない、あなたは完全にそれを釘付け、誤解しませんでした。 xとyは実際の例のためだけに構成されています。私が気にするのは、最初の軸に沿ってはるかに大きなzです。 –

0

それあなたが見てdstackコードが見つかります。

np.dstack((x, y)).T 

はefですfectively:

np.concatenate([i[:,:,None] for i in (x,y)],axis=2).transpose([2,1,0]) 

これは、各コンポーネント配列を変形してから、この新しい軸に沿って結合します。最後に軸を転置します。

あなたの目標は、だから、リバースエンジニアリングのビットで、我々は

np.concatenate([i[...,0] for i in np.split(z.T,2,axis=2)],axis=0) 
np.concatenate([i.T[:,:,0] for i in np.split(z,2,axis=0)],axis=0) 

または

np.concatenate(np.split(z.T,2,axis=2),axis=0)[...,0] 

zからそれを作成することができます

np.concatenate((x,y),axis=0) 

(行スタック)と同じですまたは部分的なトランスポーズを使用すると、スプリットおよびリジョインの軸を最初に保つことができ、ちょうどを使用します:

np.concatenate(z.transpose(0,2,1),axis=0) 

またはそのリシェイプ同等

(z.transpose(0,2,1).reshape(-1,3)) 
関連する問題