用2*2块的平均值替换numpy数组元素

5

我有一个在numpy中的m*n矩阵。我想将这个矩阵分成2 * 2的块,然后用块中元素的平均值替换每个元素。例如,考虑以下数组:

[
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]
]

我想制作这个矩阵:

[
    [3.5, 3.5, 5.5, 5.5]
    [3.5, 3.5, 5.5, 5.5]
    [11.5, 11.5, 13.5, 13.5]
    [11.5, 11.5, 13.5, 13.5]
]

什么是最有效的方法?我应该使用for循环吗?

终于找到我一直在寻找的方法了! :) - jtlz2
1个回答

5

一种方法是重新塑造这两个轴,使每个轴变成两个,并在后面的一个轴上找到均值,从而得到平均值。我们将保留使用 keepdims=True 的维度,以便稍后使用 np.repeat 复制沿着缩小的轴进行最终输出。

因此,一种实现方式是-

b = a.reshape(2,2,2,2).mean((1,3), keepdims=1)
out = np.repeat(np.repeat(b,(2),axis=(1)),(2), axis=3).reshape(4,4)

示例运行:

In [17]: a
Out[17]: 
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])

In [18]: b = a.reshape(2,2,2,2).mean((1,3), keepdims=1)

In [19]: np.repeat(np.repeat(b,(2),axis=(1)),(2), axis=3).reshape(4,4)
Out[19]: 
array([[  3.5,   3.5,   5.5,   5.5],
       [  3.5,   3.5,   5.5,   5.5],
       [ 11.5,  11.5,  13.5,  13.5],
       [ 11.5,  11.5,  13.5,  13.5]])

通俗来说,解决方案如下所示 -

m,n = a.shape
p,q = (2,2) # Block size
b = a.reshape(m//p,p,n//q,q).mean((1,3), keepdims=1)
out = np.repeat(np.repeat(b,(p),axis=(1)),(q), axis=3).reshape(a.shape)

性能提升

我们可以用一个基于初始化的部分来替换那个复制的部分,像这样 -

out = np.empty((m//p,p,n//q,q),dtype=float)
out[:] = b
out.shape = a.shape

3
你是谁?@Divakar,一如既往的精彩回答。 - void
我在第一个reshape处遇到了一个reshape错误:ValueError: cannot reshape array of size 72768 into shape (96,2,189,2)。这是因为块不对齐吗? - jtlz2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接