2016-08-26 25 views
5

矩陣給定一個m x n矩陣我想它拆分成正方形a x a(A = 3或= 4)的偏移量的任意的矩陣(最小偏移量= 1,最大值偏移=塊尺寸),如Mathematica的Partition功能的作用:numpy的 - 分裂考慮偏移

例如,給定的4×4矩陣A

1 2 3 4 
5 6 7 8 
9 10 11 12 
13 14 15 16 

如果我給3×3個塊和偏移量= 1,I想要得到的4個矩陣:

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 

如果矩陣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是列出的清單,我認爲,我不需要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的經驗來解釋給別人。我沒有多少試驗和錯誤就想出了這張表格,但我在這裏呆了太久。 :))。

但這迭代求解更容易解釋:

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

哪些可以變成一個數組np.array(alist)。如果它更清晰,使用這個沒什麼問題。

有一點要牢記有關as_strided的做法是,它是一個視圖,並更改M可能改變A,並在M在一個地方的改變可以M修改的幾個地方。但是重塑M可能會將其變成副本。因此總的來說,從M讀取值並將其用於計算如summean會更安全。就地改變可能是不可預測的。

迭代解決方案產生全部副本。

np.ogrid代替np.ix_迭代溶液(否則相同的想法):

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

ix_ogrid只是簡單的方法構建對載體的用於索引的塊:

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

同樣的事情,但與slice對象:

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

此列表版本與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]]]) 

假設你想連續的塊,內片/範圍沒有發生變化,只是步進爲外ij

In [1017]: np.arange(0,6,3) 
Out[1017]: array([0, 3]) 
+0

@hpauji謝謝,我喜歡'np.ix_'版本,我認爲它會很直截了當,但我不能讓它在指定偏移時在另一個矩陣上工作,例如這個'import numpy as np A = np.arange(1,37).reshape((6,6)) 打印甲 ALIST = [] BLOCKSIZE = 3 偏移= 3 對於i在範圍(0,-1 BLOCKSIZE,偏移量): 對於在範圍(0,塊大小-1,偏移量)中的j: (a [np.ix_(範圍(i,i +塊大小,偏移量),範圍(j,j +塊大小,偏移量))]) np.array(alist)'失敗,偏移3和1,我該如何解決? – andandandand

+0

我不得不將該評論放入編輯器並換行來閱讀。這個「抵消」的目的是什麼?在'range'中,第三個值是'step'。 – hpaulj

+0

它是塊之間的偏移量,如滑動窗口跨度。 'A = np.arange(1,37).reshape((6,6))'中3×3塊的偏移量將只給出從np.split(A,3 )'。我擴大了這個問題來說明。 – andandandand