如何矢量化 numpy 数组的 2x2 子数组的平均值?
Posted
技术标签:
【中文标题】如何矢量化 numpy 数组的 2x2 子数组的平均值?【英文标题】:How can I vectorize the averaging of 2x2 sub-arrays of numpy array? 【发布时间】:2015-01-08 08:48:51 【问题描述】:我有一个非常大的 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 是否有矢量化/高效的方法来对这样的子集进行聚合?
【问题讨论】:
你可能想看看这个:***.com/questions/16856788/… 当然之后你可以使用 np.mean(arr, axis=-1) Scikit Image 中有一个函数可以进行整形技巧,以防您发现自己重复编写它:scikit-image.org/docs/dev/api/skimage.util.html#view-as-blocks 【参考方案1】:如果我们形成重构矩阵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]])
有关重塑“技巧”的更多背景信息,请参阅@dashesy 在评论中提供的链接。
要将其推广到形状为 (m, n) 的二维数组,其中 m 和 n 是偶数,请使用
y = x.reshape(x.shape[0]/2, 2, x.shape[1], 2)
y
然后可以解释为 2x2 数组的数组。 The first and third index slots of the 4-d array act as the indices that select one of the 2x2 blocks.要获取左上角的 2x2 块,请使用 y[0, :, 0, :]
;到第二行第三列块的块,使用y[1, :, 2, :]
;通常,要访问块 (j, k),请使用 y[j, :, k, :]
。
要计算这些块的平均简化数组,请使用 mean
方法和 axis=(1, 3)
(即轴 1 和 3 的平均值):
avg = y.mean(axis=(1, 3))
这是一个示例,其中x
的形状为 (8, 10),因此 2x2 块的平均值数组的形状为 (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 块:
In [14]: y[0, :, 0, :]
Out[14]:
array([[2, 1],
[3, 1]])
In [15]: y[1, :, 2, :]
Out[15]:
array([[3, 2],
[2, 0]])
计算块的平均值:
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 ]])
【讨论】:
以上是关于如何矢量化 numpy 数组的 2x2 子数组的平均值?的主要内容,如果未能解决你的问题,请参考以下文章