2016-08-26 8 views
5

与えられたm x n行列はMathematicaのように、任意のオフセット(最小オフセット= 1、最大オフセット=ブロックサイズ)の行列a x a(a = 3またはa = 4) Partition機能を行います。Numpy - オフセットを考慮した行列を分割する

1 2 3 
5 6 7 
9 10 11 

2 3 4 
6 7 8 
10 11 12 

5 6 7 
9 10 11 
13 14 15 

6 7 8 
10 11 12 
14 15 16 
:4×4行列 A Iは3×3つのブロックを与えると、I 4つの行列を取得したい= 1オフセット場合
1 2 3 4 
5 6 7 8 
9 10 11 12 
13 14 15 16 

等所与例えば

行列AA = np.arange(1, 37).reshape((6,6))であると私は3 =オフセットと3×3個のブロックを使用している場合、私は出力として、ブロックをしたい:

1 2 3 
7 8 9 
3 14 15 

4 5 6 
10 11 12 
16 17 18 

19 20 21 
25 26 27 
31 32 33 

22 23 24 
28 29 30 
34 35 36 

私は行列Aは、リストのリストされた状態でOKだと私はと思いますNumPyの機能は必要ありません。 array_splitnumpy.splitのどちらもこのオフセットオプションをそのまま使用できないことに驚きました。これを純粋なPythonでスライスしてコードする方が簡単ですかNumPyの進歩を調べるべきですか?私はコードを読みやすくしたい。

+0

同様の質問は、ローリングウィンドウまたはスライドウィンドウの観点から言えばわかります。誰かが良い重複を見つけるかもしれません。 – hpaulj

答えて

3

あなたがヒントとして、strides

In [900]: M = np.lib.stride_tricks.as_strided(A, shape=(2,2,3,3), strides=(16,4,16,4)) 
In [901]: M 
Out[901]: 
array([[[[ 1, 2, 3], 
     [ 5, 6, 7], 
     [ 9, 10, 11]], 

     [[ 2, 3, 4], 
     [ 6, 7, 8], 
     [10, 11, 12]]], 


     [[[ 5, 6, 7], 
     [ 9, 10, 11], 
     [13, 14, 15]], 

     [[ 6, 7, 8], 
     [10, 11, 12], 
     [14, 15, 16]]]]) 
In [902]: M.reshape(4,3,3) # to get it in form you list 
Out[902]: 
array([[[ 1, 2, 3], 
     [ 5, 6, 7], 
     [ 9, 10, 11]], 

     [[ 2, 3, 4], 
     [ 6, 7, 8], 
     [10, 11, 12]], 

     [[ 5, 6, 7], 
     [ 9, 10, 11], 
     [13, 14, 15]], 

     [[ 6, 7, 8], 
     [10, 11, 12], 
     [14, 15, 16]]]) 

と進歩に問題がこれを行う方法があるが、非常にnumpyの経験のない人に説明するための高度な、ハードであるということです。私は多くの試行錯誤がなくフォームを見つけましたが、私はここであまりにも長くぶら下がっています。 :))。

しかし、この反復解法を説明するのは簡単です:np.array(alist)の配列に変換することができます

In [909]: alist=[] 
In [910]: for i in range(2): 
    ...:  for j in range(2): 
    ...:   alist.append(A[np.ix_(range(i,i+3),range(j,j+3))]) 
    ...:   
In [911]: alist 
Out[911]: 
[array([[ 1, 2, 3], 
     [ 5, 6, 7], 
     [ 9, 10, 11]]), 
array([[ 2, 3, 4], 
     [ 6, 7, 8], 
     [10, 11, 12]]), 
array([[ 5, 6, 7], 
     [ 9, 10, 11], 
     [13, 14, 15]]), 
array([[ 6, 7, 8], 
     [10, 11, 12], 
     [14, 15, 16]])] 

。より明確な場合は、これを使用することで何も問題はありません。 as_stridedアプローチについて心に留めておくべき

ことの一つは、それが図であり、Mへの変更はAを変更することができ、かつM内の1つの場所に変更がMでいくつかの場所を変更することです。しかし、Mを再構成すると、それをコピーにすることができます。だから全体としてMから値を読んで、summeanのような計算に使う方が安全です。適切な場所での変更は予測できません。

反復解は、すべての周りにコピーを生成します。

np.ogrid代わりにnp.ix_有する反復溶液(そうでなければ同じ考え方):

In [970]: np.ogrid[0:3, 0:3] 
Out[970]: 
[array([[0], 
     [1], 
     [2]]), array([[0, 1, 2]])] 

np.array([A[np.ogrid[i:i+3, j:j+3]] for i in range(2) for j in range(2)]) 

両方ix_ogridブロックにインデックスを付けるためのベクターの対を構成するだけの簡単な方法であります

sliceオブジェクトの場合と同じことですが、

これのリストバージョンは、as_stridedソリューションと同様のviewの動作をします(リストの要素はビューです)。非オーバーラップブロックと6x6のために

、試してみてください。

In [1016]: np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(0,6,3) for j i 
     ...: n range(0,6,3)]) 
Out[1016]: 
array([[[ 1, 2, 3], 
     [ 7, 8, 9], 
     [13, 14, 15]], 

     [[ 4, 5, 6], 
     [10, 11, 12], 
     [16, 17, 18]], 

     [[19, 20, 21], 
     [25, 26, 27], 
     [31, 32, 33]], 

     [[22, 23, 24], 
     [28, 29, 30], 
     [34, 35, 36]]]) 

がちょうど外側iためのステッピングとj

、内部スライス/範囲が変化していない、あなたが連続ブロックをしたいと仮定すると、
In [1017]: np.arange(0,6,3) 
Out[1017]: array([0, 3]) 
+0

@hpaujiありがとう、私は 'np.ix_'のバージョンが好きで、それは十分に簡単だと思っていましたが、オフセットを指定して別の行列で動作させることはできません。例えば' numpy as np A :範囲(0、-1のblockSize、オフセット)にiについて= 3 オフセット= np.arange(1、37).reshape((6,6)) プリント連想リスト= [] のblockSize = 3 (j、j + blockSize、offset))]) alist.append(範囲[i、 np.array(alist) 'はオフセット3と1の両方で失敗します。どうすれば修正できますか? – andandandand

+0

私はそのコメントを編集者に伝え、それを読むために改行しなければなりませんでした。この「オフセット」の目的は何ですか? 「範囲」では3番目の値が「ステップ」です。 – hpaulj

+0

これは、スライディングウィンドウのストライドのようなブロック間のオフセットです。 'A = np.arange(1,37).reshape((6,6))'の3 x 3ブロックのオフセット3は 'np.split(A、3)から得られる4つのブロックのみを与えます。 ) '。説明のために質問を拡大しました。 – andandandand

関連する問題