Search code examples
numpynumpy-ndarraynumpy-slicing

Turn close proximity elements of a 2d NumPy array into that proximity average


What I have is an array of numpy arrays (a 2d numpy array).

    my_array = [
        [1, 2, 3, 4]
        [1, 2, 3, 4]
        [2, 3, 4, 5]
        [2, 3, 4, 5]
    ]

and I want to turn it into:

    proximity = 2 
    my_array = [ 
        [1.5, 1.5, 3.5, 3.5]
        [1.5, 1.5, 3.5, 3.5]
        [2.5, 2.5, 4.5, 4.5]
        [2.5, 2.5, 4.5, 4.5]
    ]

I have this bit of code:

    proximity = 2
    for i in range(0, len(my_array), proximity):
        for j in range(0, len(my_array), proximity):
            ii = i + proximity 
            jj = j + proximity 
            my_array[i:ii, j:jj] = np.average(my_array[i:ii, j:jj])

Now my current solution does the trick, but I want to know the pure numpy solution, one without the 2 'for' loops that I use.

Edit: each dimension is divisible by proximity


Solution

  • If it's guaranteed that each dimension is divisible by proximity, you can reshape:

    (my_array.reshape(rows//proximity, proximity, cols//proximity, proximity)
       .mean(axis=(1,3))           # mean along proximity axes
       .repeat(proximity, axis=0)  # repeat vertically
       .repeat(proximity, axis=1)  # repeat horizontally
    )
    

    Output:

    array([[1.5, 1.5, 3.5, 3.5],
           [1.5, 1.5, 3.5, 3.5],
           [2.5, 2.5, 4.5, 4.5],
           [2.5, 2.5, 4.5, 4.5]])
    

    Another input:

    my_array = np.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]])
    

    Output:

    array([[ 2.5,  2.5,  4.5,  4.5],
           [ 2.5,  2.5,  4.5,  4.5],
           [10.5, 10.5, 12.5, 12.5],
           [10.5, 10.5, 12.5, 12.5],
           [18.5, 18.5, 20.5, 20.5],
           [18.5, 18.5, 20.5, 20.5]])