1

I have a matrix like below

c = [[ 1 2 3 4 5 6 7 8 9 1]
     [ 2 3 4 5 6 7 8 9 1 2]
     [ 3 4 5 6 7 8 9 1 2 3]
     [ 4 5 6 7 8 9 1 2 3 4]]

From the given SO ANSWERS in this post, I used it to divide the matrix into blocks (2*5) like below

def blockshaped(arr, nrows, ncols):
"""
Return an array of shape (n, nrows, ncols) where
n * nrows * ncols = arr.size

If arr is a 2D array, the returned array should look like n subblocks with
each subblock preserving the "physical" layout of arr.
"""
    h, w = arr.shape
    assert h % nrows == 0, "{} rows is not evenly divisble by {}".format(h, nrows)
    assert w % ncols == 0, "{} cols is not evenly divisble by {}".format(w, ncols)
    return (arr.reshape(h//nrows, nrows, -1, ncols)
           .swapaxes(1,2)
           .reshape(-1, nrows, ncols))


print(blockshaped(c, 2, 5))

Result:

[[[ 1 2 3 4 5 ]
  [ 2 3 4 5 6 ]]

 [[ 6 7 8 9 1 ]
  [ 7 8 9 1 2]]

 [[ 3 4 5 6 7 ]
  [ 4 5 6 7 8 ]]

 [[ 8 9 1 2 3 ]
  [ 9 1 2 3 4]]]

I got 4 blocks of matrix, and now I need the mean value of each block. How to calculate the mean of this each block?

When I try to use the mean() it is going to calculate the mean for the whole matrix but not for each block.

seralouk
  • 30,938
  • 9
  • 118
  • 133
John
  • 565
  • 8
  • 23
  • For the functionality provided by `blockshaped()`, check out [`skimage.util.view_as_blocks()`](https://scikit-image.org/docs/dev/api/skimage.util.html#view-as-blocks). – AMC Dec 13 '19 at 10:22

2 Answers2

1

1. Half line solution with List comprehension

results = blockshaped(c, 2, 5)
block_means = [np.mean(results[block,:,:]) for block in range(results.shape[0])]

print(block_means)
# [3.5, 5.8, 5.5, 4.2]

Version 2 -- shorter code:

results = blockshaped(c, 2, 5)
block_means = [np.mean(block) for block in results]
# [3.5, 5.8, 5.5, 4.2]

In [15]: %timeit [np.mean(results[block,:,:]) for block in range(results.shape[0])]
10000 loops, best of 3: 35.9 µs per loop

In [16]: %timeit [np.mean(block) for block in results]
10000 loops, best of 3: 33.4 µs per loop

P.S: The second solution will only work if the blocks are in the first (0) dimension of results.

seralouk
  • 30,938
  • 9
  • 118
  • 133
  • Can you benchmark these on larger inputs? Measuring such tiny runtimes isn’t particularly accurate or useful IMO. – AMC Dec 13 '19 at 10:23
1

Another option is to use the map function:

means = np.round(map(np.mean, r),3)
print(means)

which results in:

[ 3.5 5.8 5.5 4.2]

seralouk
  • 30,938
  • 9
  • 118
  • 133
David
  • 8,113
  • 2
  • 17
  • 36