Numpy Routine(s)在2d数组中创建一个常规网格

时间:2013-10-14 15:50:20

标签: python numpy grid

我正在尝试编写一个函数,在2d数组中创建一个5像素乘5像素的规则网格。我希望numpy.arangenumpy.repeat的某些组合可能会这样做,但到目前为止,我没有任何运气,因为numpy.repeat将在同一行重复。

以下是一个例子:

假设我想在形状(20, 15)的2d数组中使用5x5网格。它应该看起来像:

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

我意识到我可以简单地使用循环和切片来实现这一点,但我可以将它应用于非常大的数组,我担心它的性能太慢或不切实际。

有人可以推荐一种方法来实现这个目标吗?

提前致谢。

更新

所提供的所有答案似乎都运作良好。任何人都可以告诉我哪些对大型阵列使用效率最高?对于大数组,我的意思是100000 x 100000或更多15 x 15网格单元格大小。

3 个答案:

答案 0 :(得分: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]])

答案 1 :(得分:3)

与Jaime的答案类似:

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

答案 2 :(得分: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)它需要1的数组,2)它乘以xi*xj乘以1,而3)它会做一堆连续。