I have an m*n matrix
in numpy
. I want to divide my matrix into 2*2 blocks and then replace each element with average of the elements in its block. for example consider the following array:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
I want to produce this matrix:
[
[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]
]
What is the most efficient way to do this? Should I use for loops?
all() in Python. The numpy. all() function tests whether all array elements along the mentioned axis evaluate to True.
Method 1: We generally use the == operator to compare two NumPy arrays to generate a new array object. Call ndarray. all() with the new array object as ndarray to return True if the two NumPy arrays are equivalent.
To calculate the average of all values in a 2 dimensional NumPy array called matrix, use the numpy. average(matrix) function. The output will display a numpy array that has three average values, one per column of the input given array.
One approach would be to reshape splitting each of those two axes into two more and find mean
along the latter of those two, giving us the average values. We will keep the dimensions with keepdims=True
, so as to facilitate replicating along the reduced axes later on with np.repeat
for the final output.
Thus, one implementation would be -
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)
Sample run -
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]])
Generically put, the solution would look like this -
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)
Performance boost
We could replace that replicating part with an initialization based section, like so -
out = np.empty((m//p,p,n//q,q),dtype=float)
out[:] = b
out.shape = a.shape
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With