2013-10-14 41 views
6

我正在嘗試編寫一個函數,該函數可以在二維數組內創建一個由5個像素組成的規則網格。我希望numpy.arangenumpy.repeat的組合可以做到這一點,但到目前爲止我還沒有運氣,因爲numpy.repeat只會在同一行重複。Numpy常規在二維數組內創建規則網格

下面是一個例子:

比方說,我想形狀(20, 15)的二維陣列內的5×5格。它應該看起來像:

array([[ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11], 
     [ 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11], 
     [ 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11], 
     [ 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11], 
     [ 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11]]) 

我知道我可以簡單地使用循環和切片做到這一點,但我可以將其應用到非常大的陣列和我擔心的是,性能將是太慢或不切實際。

任何人都可以推薦一種方法來完成這個?

在此先感謝。

UPDATE

所有提供的答案似乎運作良好。任何人都可以告訴我哪個最有效的用於大型數組?大數組我的意思是它可能是100000 x 100000或更多與15 x 15網格單元格大小。

+1

這裏有兩個解決方案,一個涉及'numpy.kron',一個涉及'numpy.repeat':http://stackoverflow.com/questions/7525214/how-to-scale-a-numpy-array – Brionius

+0

我發佈了這裏有一個答案,但事實證明,在你的鏈接問題中使用@NPE的方法是一樣的。 – jorgeca

+0

@Brionius - 'numpy.kron'絕對有效。你認爲這和@Mr有很大的性能差異嗎? E的回答? – Brian

回答

3

廣播是這裏的答案:

m, n, d = 20, 15, 5 
arr = np.empty((m, n), dtype=np.int) 
arr_view = arr.reshape(m // d, d, n // d, d) 
vals = np.arange(m // d * n // d).reshape(m // d, 1, n // d, 1) 
arr_view[:] = vals 

>>> arr 
array([[ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8], 
     [ 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11], 
     [ 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11], 
     [ 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11], 
     [ 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11], 
     [ 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11]]) 
+0

感謝您的回答。不幸的是,這並不適合我。我結束了'arr_view.shape =(4L,5L,3L,5L)'而不是'(20,15)'。 – Brian

+0

@Brian'arr_view'是您的原始數組的視圖,僅用於具有可廣播的形狀。這是你想要看的'arr':它仍然具有形狀'(20,15)'。 – Jaime

+0

我明白了。感謝澄清。我不熟悉觀點的概念。我得看看那個。 – Brian

3

雅伊梅的答案類似:

np.repeat(np.arange(0, 10, 3), 4)[..., None] + np.repeat(np.arange(3), 5)[None, ...] 
+0

這似乎比Jaime的答案簡單得多,更接近我想要做的。我不熟悉'[...,無]'。這到底是什麼意思? – Brian

+0

這就是所謂的廣播。最好的解釋是[這裏](http://scipy-lectures.github.io/intro/numpy/numpy.html#broadcasting)和[here](http://docs.scipy.org/doc/numpy/user /basics.broadcasting.html)。閱讀關於省略號和更多關於廣播[這裏](http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html)。您可能會在文檔中看到'np.newaxis'而不是'None'。 – YXD

2

kron會做這種擴張(如Brionius的意見還建議):

xi, xj, ni, nj = 5, 5, 4, 3 
r = np.kron(np.arange(ni*nj).reshape((ni,nj)), np.ones((xi, xj))) 

儘管我沒有測試過它,但我認爲它比廣播方法效率低,但是一點更簡潔,更容易理解(我希望)。它可能效率較低,因爲:1)它需要一個數組,2)它用1乘以xi*xj,3)它執行一連串的連接。

+0

這實際上並沒有工作。一個小的更正是必需的。 ((xi * ni,xj * nj))'應該是'np.ones((xi,xj))'。隨着更正,它確實奏效。感謝您對效率的解釋。 – Brian

+0

謝謝。糾正。 – tom10