2013-10-14 42 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