Binning multidimensional array in numpy
I have a 4d numpy array (these are stacks of imaging data) and would like to perform mean binning along all but one of the axes.
starting with say
x=np.random.random((3,100,100,100))
I want to apply binning to axes 1,2,3 with bin size 10 and average the values in each bin.
expected result would be an array of shape (3,10,10,10)
I have looked into np.reshape like so:
result=x.reshape(3,1,10,100,100).mean(axis=1)
result=result.reshape(3,10,1,10,100).mean(axis=2)
and so on, but this messes up the structure of the image arrays
is there a more straightforward way to do this?
3 answers

Try this:
x=np.random.random((3,100,100,100)) x_resized=np.zeros((3,10,10,10)) for i in range(len(x_resized[0])): for j in range(len(x_resized[0][0])): for k in range(len(x_resized[0][0][0])): x_resized[0,i,j,k]=np.average(x[0,i*10:i*10+10,j*10:j*10+10,k*10:k*10+10]) x_resized[1,i,j,k]=np.average(x[1,i*10:i*10+10,j*10:j*10+10,k*10:k*10+10]) x_resized[2,i,j,k]=np.average(x[2,i*10:i*10+10,j*10:j*10+10,k*10:k*10+10])
which performs the averaging blockwise.

How about this:
import numpy as np import skimage.measure a = np.arange(36).reshape(6, 6) b = skimage.measure.block_reduce(a, (2,2), np.mean)
output:
a = [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23] [24 25 26 27 28 29] [30 31 32 33 34 35]] b = [[ 3.5 5.5 7.5] [15.5 17.5 19.5] [27.5 29.5 31.5]]
But instead of my 2d example, you can do that for a block size of (1, 10, 10, 10) of your data.

#block size bs = (10,10,10) s = 1 shape = [3, x.shape[s+0]//bs[0], bs[0], x.shape[s+1]//bs[1], bs[1] x.shape[s+2]//bs[2], bs[2]] result = x.reshape(*shape).mean(axis = (2,4,6))
Possibly a redundant answer at this point, but if you prefer not to use skimage then this should do the same thing.