Hei我正在尝试计算行和列的平均值
Ex我有阵列
a = np.array([
[1,2,3,4,5,6,7,8],
[2,3,6,1,7,4,3,6],
[6,3,5,8,9,2,6,8],
[6,2,5,8,9,3,2,7],
[5,7,3,4,7,8,5,3],
[7,3,4,5,7,4,5,6],
[5,3,7,6,7,8,4,2],
[5,4,7,7,2,1,6,4]])
我想计算第一行[1,2]和第二行[2,3]的平均值。平均值为2.0然后我想计算第一行[3,4]和第二行[6,1]的平均值。等等
结果被放置到一个大小为其一半的新数组中。
我有以下代码可以做到这一点,
完整的代码是
import numpy as np
import sys
a = np.array([
[1,2,3,4,5,6,7,8],
[2,3,6,1,7,4,3,6],
[6,3,5,8,9,2,6,8],
[6,2,5,8,9,3,2,7],
[5,7,3,4,7,8,5,3],
[7,3,4,5,7,4,5,6],
[5,3,7,6,7,8,4,2],
[5,4,7,7,2,1,6,4]])
ni = nj = 2
dim_i = a.shape[0]
dim_j = a.shape[1]
b = np.empty((int(a.shape[0]/ni), int(a.shape[1]/nj)))
for ii, i in enumerate(range(0, dim_i, ni)):
for jj, j in enumerate(range(0, dim_j, nj)):
flat = np.array([a[i][j:j+ni], a[i+1][j:j+ni]]).flatten()
b[ii,jj] = np.mean(flat)
print(b)
[[2. 3.5 5.5 6. ]
[4.25 6.5 5.75 5.75]
[5.5 4. 6.5 4.75]
[4.25 6.75 4.5 4. ]]
我正在寻找一种更快、更优雅的方式。因为真实数据在每个维度上都有几百或更多的大小。
这可能吗?
Mvh,Birgir。
您可以利用numpy
stride_ticks模块将阵列重塑为块形状。一种解决方案:
from numpy.lib.stride_tricks import as_strided
as_strided(a, shape=(4, 4, 2, 2), strides=(128, 16, 64, 8)).mean(axis=(2,3))
输出:
array([[2. , 3.5 , 5.5 , 6. ],
[4.25, 6.5 , 5.75, 5.75],
[5.5 , 4. , 6.5 , 4.75],
[4.25, 6.75, 4.5 , 4. ]])
注意,我明确定义了形状和步长,但它们可以很容易地推断出来(对于2*2平均池的一般情况(
strides = tuple(map(lambda x: x*2, a.strides)) + a.strides
shape = tuple(map(lambda x: int(x / 2), a.shape)) + (2, 2)
该技巧的性能比天真环路快10倍
%%timeit
as_strided(a, shape=(4, 4, 2, 2), strides=(128, 16, 64, 8)).mean(axis=(2,3))
11.5 µs ± 44.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
ni = nj = 2
dim_i = a.shape[0]
dim_j = a.shape[1]
b = np.empty((int(a.shape[0]/ni), int(a.shape[1]/nj)))
for ii, i in enumerate(range(0, dim_i, ni)):
for jj, j in enumerate(range(0, dim_j, nj)):
flat = np.array([a[i][j:j+ni], a[i+1][j:j+ni]]).flatten()
b[ii,jj] = np.mean(flat)
128 µs ± 1.38 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
对于较大的阵列(X200用于1000*1000阵列(,增益更显著