Mar*_*rkD 5 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
Run Code Online (Sandbox Code Playgroud)
我需要得到一个2x3阵列,它是每个2x2子阵列的平均值,即:
result = np.array( [[ 3.5, 5.5, 7.5],
[15.5, 17.5, 19.5]])
Run Code Online (Sandbox Code Playgroud)
因此,元素[0,0]被计算为x [0:2,0:2]的平均值,而元素[0,1]将是x [2:4,0:2]的平均值.Numpy是否有像这样的子集进行聚合的矢量化/有效方法?
如果我们形成重新形成的矩阵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.]])
Run Code Online (Sandbox Code Playgroud)
要获得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]])
Run Code Online (Sandbox Code Playgroud)
如果您使用的是不支持使用轴的元组的旧版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]])
Run Code Online (Sandbox Code Playgroud)
有关重塑"技巧"的更多背景,请参阅评论中@dashesy给出的链接.
为了将其推广到具有形状(m,n)的二维阵列,其中m和n是偶数,请使用
y = x.reshape(x.shape[0]/2, 2, x.shape[1], 2)
Run Code Online (Sandbox Code Playgroud)
y然后可以解释为2x2数组的数组.4-d阵列的第一和第三索引槽充当选择2x2块之一的索引.要获得左上角的2x2块,请使用y[0, :, 0, :]; 到第二行和第三列的块中,使用y[1, :, 2, :]; 一般来说,访问块(j,k),使用y[j, :, k, :].
要计算这些块的平均值的减少数组,请使用该mean方法axis=(1, 3)(即轴1和3的平均值):
avg = y.mean(axis=(1, 3))
Run Code Online (Sandbox Code Playgroud)
这是一个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)
Run Code Online (Sandbox Code Playgroud)
看看几个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]])
Run Code Online (Sandbox Code Playgroud)
计算块的平均值:
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 ]])
Run Code Online (Sandbox Code Playgroud)