利用 Numpy 函数生成 2D 数组中的规则网格

104 阅读3分钟

我们希望在给定的 2D 数组中生成一个规则网格,比如在一个形状为 (20, 15) 的 2D 数组中生成一个 5x5 的网格。如下图所示:

huake_00152_.jpg 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]])

我们尝试使用 NumPy 函数 arangerepeat 来创建这个网格。但是,repeat 函数只能沿同一行重复元素,无法实现跨行重复。

2. 解决方案

为了解决这个问题,我们可以使用广播来创建网格。广播是 NumPy 中的一项强大功能,它允许我们在不显式重复数组的情况下对数组进行操作。

import numpy as np

# 创建一个 20x15 的空数组
m, n = 20, 15

arr = np.empty((m, n), dtype=np.int)

# 使用广播来创建网格
d = 5  # 网格单元的大小

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

# 打印网格
print(arr)

上述代码将生成一个 20x15 的网格,其中每个网格单元的大小为 5x5。

代码例子

import numpy as np

# 在 2D 数组中生成 5x5 的规则网格(基于广播)
def create_grid(m, n, d):
    """
    :param m: 2D 数组的行数
    :param n: 2D 数组的列数
    :param d: 网格单元的大小
    :return: 一个包含规则网格的 2D 数组
    """

    # 创建一个空数组
    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

    return arr

# 创建一个 20x15 的空数组
m, n = 20, 15

# 创建一个 5x5 的网格
d = 5

arr = create_grid(m, n, d)

# 打印网格
print(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],