用于在 2D 数组内创建常规网格的 Numpy 例程



我正在尝试编写一个函数,该函数将在 2d 数组内创建 5 x 5 像素的常规网格。 我希望numpy.arangenumpy.repeat的某种组合可以做到这一点,但到目前为止我没有任何运气,因为numpy.repeat只会在同一行重复。

下面是一个示例:

假设我想要一个 5x5 网格在形状 (20, 15) 的 2d 数组中。 它应如下所示:

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网格单元大小。

广播是这里的答案:

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

类似于Jaime的回答:

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

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)它做一堆concats。

最新更新