python - 如何矢量化 numpy 数组的 2x2 子数组的平均值?

标签 python arrays numpy vectorization aggregation

我有一个非常大的 2D numpy 数组,其中包含我需要取平均值的 2x2 子集。我正在寻找一种方法来矢量化此操作。例如,给定 x:

#               |- col 0 -|   |- col 1 -|   |- col 2 -|       
x = np.array( [[ 0.0,   1.0,   2.0,   3.0,   4.0,   5.0],  # row 0
               [ 6.0,   7.0,   8.0,   9.0,  10.0,  11.0],  # row 0
               [12.0,  13.0,  14.0,  15.0,  16.0,  17.0],  # row 1
               [18.0,  19.0,  20.0,  21.0,  22.0,  23.0]]) # row 1

我需要得到一个 2x3 数组,它是每个 2x2 子数组的平均值,即:

result = np.array( [[ 3.5,  5.5,  7.5],
                    [15.5, 17.5, 19.5]])

所以元素 [0,0] 计算为 x[0:2,0:2] 的平均值,而元素 [0,1] 将是 x[2:4, 0:2] 的平均值。 numpy 是否有矢量化/有效的方法来对这样的子集进行聚合?

最佳答案

如果我们形成 reshape 矩阵 y = x.reshape(2,2,3,2),则 (i,j) 2x2 子矩阵由 y[i, :,j,:]。例如:

In [340]: x
Out[340]: 
array([[  0.,   1.,   2.,   3.,   4.,   5.],
       [  6.,   7.,   8.,   9.,  10.,  11.],
       [ 12.,  13.,  14.,  15.,  16.,  17.],
       [ 18.,  19.,  20.,  21.,  22.,  23.]])

In [341]: y = x.reshape(2,2,3,2)

In [342]: y[0,:,0,:]
Out[342]: 
array([[ 0.,  1.],
       [ 6.,  7.]])

In [343]: y[1,:,2,:]
Out[343]: 
array([[ 16.,  17.],
       [ 22.,  23.]])

要获取 2x2 子矩阵的平均值,请使用 mean 方法,其中 axis=(1,3):

In [344]: y.mean(axis=(1,3))
Out[344]: 
array([[  3.5,   5.5,   7.5],
       [ 15.5,  17.5,  19.5]])

如果您使用的是旧版本的 numpy,它不支持对轴使用元组,您可以这样做:

In [345]: y.mean(axis=1).mean(axis=-1)
Out[345]: 
array([[  3.5,   5.5,   7.5],
       [ 15.5,  17.5,  19.5]])

有关 reshape “技巧”的更多背景信息,请参阅@dashesy 在评论中给出的链接。


要将其概括为形状为 (m, n) 的二维数组,其中 m 和 n 是偶数,请使用

y = x.reshape(x.shape[0]/2, 2, x.shape[1], 2)

y 然后可以解释为 2x2 数组的数组。 4 维数组的第一个和第三个索引槽用作选择一个 2x2 block 的索引。要获得左上角的 2x2 block ,请使用 y[0, :, 0, :];到 block 的第二行第三列的 block ,使用y[1, :, 2, :];通常,要访问 block (j, k),请使用 y[j, :, k, :]

要计算这些 block 的减少平均值数组,请使用 mean 方法,其中 axis=(1, 3)(即轴 1 和 3 的平均值) :

avg = y.mean(axis=(1, 3))

这是一个示例,其中 x 的形状为 (8, 10),因此 2x2 block 的平均值数组的形状为 (4, 5):

In [10]: np.random.seed(123)

In [11]: x = np.random.randint(0, 4, size=(8, 10))

In [12]: x
Out[12]: 
array([[2, 1, 2, 2, 0, 2, 2, 1, 3, 2],
       [3, 1, 2, 1, 0, 1, 2, 3, 1, 0],
       [2, 0, 3, 1, 3, 2, 1, 0, 0, 0],
       [0, 1, 3, 3, 2, 0, 3, 2, 0, 3],
       [0, 1, 0, 3, 1, 3, 0, 0, 0, 2],
       [1, 1, 2, 2, 3, 2, 1, 0, 0, 3],
       [2, 1, 0, 3, 2, 2, 2, 2, 1, 2],
       [0, 3, 3, 3, 1, 0, 2, 0, 2, 1]])

In [13]: y = x.reshape(x.shape[0]/2, 2, x.shape[1]/2, 2)

看看几个 2x2 block :

In [14]: y[0, :, 0, :]
Out[14]: 
array([[2, 1],
       [3, 1]])

In [15]: y[1, :, 2, :]
Out[15]: 
array([[3, 2],
       [2, 0]])

计算 block 的平均值:

In [16]: avg = y.mean(axis=(1, 3))

In [17]: avg
Out[17]: 
array([[ 1.75,  1.75,  0.75,  2.  ,  1.5 ],
       [ 0.75,  2.5 ,  1.75,  1.5 ,  0.75],
       [ 0.75,  1.75,  2.25,  0.25,  1.25],
       [ 1.5 ,  2.25,  1.25,  1.5 ,  1.5 ]])

关于python - 如何矢量化 numpy 数组的 2x2 子数组的平均值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26871083/

相关文章:

python - 绘制多轴对象数组

python 功能来解析包含表的 csv 文件

python - hashlib 中 `block_size` 和 `digest_size` 之间的区别?

python - 在函数中打印变量标签

php - 为什么我们不能像 For 循环那样在字符串上使用 Foreach 循环

python - 尝试用 numpy 向量化迭代计算

对 getChar 和 printf 的调用似乎修改了不相关的数据

java - 将 EnumSet 转换为整数数组

python - 使用 scipy/numpy 在 python 中添加 2 矩阵和乘以 2 矩阵

arrays - 从两个列表创建 numpy.recararray python