average of "row"and "column" in list

Question:

I am trying to make an new list with the averages from every n row and column. my original list looks like this:

list =
[[1,1,1,2,2,2,3,3,3],
[4,4,4,5,5,5,6,6,6],
[7,7,7,8,8,8,9,9,9],
[0,0,0,1,1,1,2,2,2],
[3,3,3,4,4,4,5,5,5],
[6,6,6,7,7,7,8,8,8]]

n = 3

my new list should look like this:
list = [[4,5,6],[3,4,5]]

i tried it in al lot of ways but i get lost along the way

Asked By: Bart008

||

Answers:

(Note that this solution relies on the numpy package, and assumes that your list is represented as a 2D NumPy array.)


Input Data

import numpy as np

lst = [[1,1,1,2,2,2,3,3,3],
       [4,4,4,5,5,5,6,6,6],
       [7,7,7,8,8,8,9,9,9],
       [0,0,0,1,1,1,2,2,2],
       [3,3,3,4,4,4,5,5,5],
       [6,6,6,7,7,7,8,8,8]
      ]

n = 3

# Convert the list of lists to a 2D array.
arr_2d = np.array(lst)

print(arr_2d)

Solution

Partitioning a 2D array

There appears to be no simple method to partition a 2D array into 2D sub-arrays in Python. But this answer provides a function that can accomplish this:

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 sub-blocks with
    each sub-blocks preserving the "physical" layout of arr.
    """
    h, w = arr.shape
    assert h % nrows == 0, f"{h} rows is not evenly divisible by {nrows}"
    assert w % ncols == 0, f"{w} cols is not evenly divisible by {ncols}"
    return (arr.reshape(h//nrows, nrows, -1, ncols)
               .swapaxes(1,2)
               .reshape(-1, nrows, ncols))

Output of blockshaped(arr_2d, n, n) (will be represented as a 3D array):

[[[1 1 1]
  [4 4 4]
  [7 7 7]]

 [[2 2 2]
  [5 5 5]
  [8 8 8]]

 [[3 3 3]
  [6 6 6]
  [9 9 9]]

 [[0 0 0]
  [3 3 3]
  [6 6 6]]

 [[1 1 1]
  [4 4 4]
  [7 7 7]]

 [[2 2 2]
  [5 5 5]
  [8 8 8]]]

Calculating average of partitions

After applying the blockshaped() function, you can use np.mean() to calculate the averages of each sub-array, and then np.array_split() to then group them as sub-lists according to the rows of the original array.

I’ve created a function to accomplish all of this:

def avg_partitions(arr, n):
    """
    Partitions a a 2D array into n x n sub-arrays and outputs 
    as a list of lists each of their average values grouped row-wise.
    """

    # Partition into 2D sub arrays each of size n x n
    sub_arrs = blockshaped(arr, n, n)

    # Create a list made up of the mean of each of these sub-arrays
    avg_values = [np.mean(a) for a in sub_arrs]

    # Work out how many sublists to split the resulting chucks into (Number of Rows / n)
    n_lists = arr.shape[0] // n

    # Split the average into sub-lists (made of arrays)
    avg_sublists = np.array_split(avg_values, n_lists)

    # Convert the arrays to lists
    avg_sublists = [a.tolist() for a in avg_sublists]

    return avg_sublists

Output of avg_partitions(arr_2d, n):

[[4.0, 5.0, 6.0], [3.0, 4.0, 5.0]]
Answered By: user21283023
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.