0

I have a 6x6 numpy array

From this I want to find the average of every 2x2 array inside the large 6x6 array. Like:

array= 
[10, 20, 30, 20, 40, 15
 34, 56, 67, 34, 45, 91
 23, 87, 56, 90, 34, 44
 10, 20, 30, 12, 15, 15
 34, 56, 67, 11, 10, 91
 23, 87, 56, 90, 34, 44]


set1= 
[10, 20
34, 56]  Average=30

set2=
[20, 30
56, 67]  Average=43

....
....

setN=
[10, 91
34, 44]  Average=44

Thanks in advance.

  • 1
    Welcome to StackOverflow. Regardless of the answers already given, you need to post your attempt at solving the problem and not expect people to write code for you. – HazardousGlitch Jul 20 '20 at 16:34

3 Answers3

2

Essentially you want to calculate the 2D moving average of your array, with a 2x2 window. This can be done by convolution, scipy.signal.convolve2d can calculate a 2D convolution.

First, you should define your array to actually be 2D:

import numpy as np

arr = np.array(
[[10, 20, 30, 20, 40, 15],
 [34, 56, 67, 34, 45, 91],
 [23, 87, 56, 90, 34, 44],
 [10, 20, 30, 12, 15, 15],
 [34, 56, 67, 11, 10, 91],
 [23, 87, 56, 90, 34, 44]])

Then do a 2D convolution using scipy.signal.convolve2d:

from scipy.signal import convolve2d

# create an averaging kernel
kernel = np.ones((2, 2), dtype=float)
kernel /= kernel.size

# compute 2d moving average
conv = convolve2d(arr, kernel, mode='valid')
print(conv[0][0]) # 30.

If you want to get the result as dtype=int, do:

conv = conv.astype(int)

You can also check this answer.

Jan Christoph Terasa
  • 5,781
  • 24
  • 34
2

You can use skimage.util.shape.view_as_windows:

import numpy as np
from skimage.util.shape import view_as_windows
array = np.array([[10, 20, 30, 20, 40, 15],
                 [34, 56, 67, 34, 45, 91],
                 [23, 87, 56, 90, 34, 44],
                 [10, 20, 30, 12, 15, 15],
                 [34, 56, 67, 11, 10, 91],
                 [23, 87, 56, 90, 34, 44]])

My implementiation:

b = view_as_windows(array, window_shape=(2, 2), step=1)

np.array(list(map(lambda x: [np.mean(i) for i in x], b)))

Result:

array([[30.  , 43.25, 37.75, 34.75, 47.75],
       [50.  , 66.5 , 61.75, 50.75, 53.5 ],
       [35.  , 48.25, 47.  , 37.75, 27.  ],
       [30.  , 43.25, 30.  , 12.  , 32.75],
       [50.  , 66.5 , 56.  , 36.25, 44.75]])
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
0

You could do something like:

m, n = 2, 2

avgs = [
    array[x:x+m,y:y+n].mean()
    for x in range(array.shape[0]-m) 
    for y in range(array.shape[1]-n)
]

This will raster across your array collecting the average value in the MxN subarrays

Michael Green
  • 719
  • 6
  • 15
  • 1
    `min(avgs)` but you really should show an attempt at solving this yourself when you ask a question, otherwise it's [off-topic](https://stackoverflow.com/help/on-topic). – ggorlen Jul 20 '20 at 16:09
  • @AdarshBabu You can use the logic here to create a function that stores (m, n) if it's the current lowest value, then return (m, n) once done – Michael Green Jul 20 '20 at 16:12