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
(Note that this solution relies on the numpy
package, and assumes that your list is represented as a 2D NumPy array.)
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)
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]]]
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]]