简体   繁体   中英

Average of elements in a 2d list

I have a list like the following:

[[1, 1], [7, 7], [20, 20], [9, 9], [-12, -12]] 

And I'm trying to have a new list which has the same number of lists inside, but changes the value of the elements by calculating the average of an element with the element after and before. What do I mean by that ?: Let's say I have the sub-list sub = [7,7] at index 1. I want this list to be [9,9], because sub[1][0] + lst_before_sub[0][0] + lst_after_sub[1][0] = 7 + 1 + 20 = 28, and 28//3 = 9 (I want integer divison).

The ideal output would be:

[[4, 4], [9, 9], [12, 12], [5, 5], [-1, -1]] 

I have currently this code:

copy_l = copy.deepcopy(audio_data)
sub_list = []
for i in range(0, len(audio_data)-1):
    sub_data = []
    for j in range(2):
        if i == 0:
            audio_data[i][j] += int(audio_data[i+1][j] / 2)
            sub_data.append(audio_data[i][j])
        elif audio_data[i+1] == audio_data[-1]:
            audio_data[i+1][j] = int((audio_data[i+1][j]+audio_data[i][j])/2)
            sub_data.append(audio_data[i+1][j])
        else:
            audio_data = copy_l
            audio_data[i][j] = int((audio_data[i-1][j] + audio_data[i][j] + audio_data[i+1][j])/3)
            sub_data.append(audio_data[i][j])
    sub_list.append(sub_data)
print(sub_list)

where audio_data is the list [[1, 1], [7, 7], [20, 20], [9, 9], [-12, -12]] that I passed in.

(I have separated the average calculation in three cases: - First element of the list: [1,1] so the average is just 1 + 7 // 2 (no element before [1,1]) - Last element of the list: [-12,-12] so the average is just -12 + 9 // 2 (no element after [-12,-12]) - All the elements in between )

Problem is, my output (sub_list) is: [[4, 4], [9, 9], [12, 12], [-1, -1]] And it seems that [9,9] never turns into [5,5] Does someone have any idea how to achieve what I want, or even an idea to make it simpler ? I hope I was clear enough, if not feel free to ask me more details, thank you!

EDIT: I'm seeking a solution without numpy, list comprehension or zip.

Here is a way to do it:

data = [[1, 1], [7, 7], [20, 20], [9, 9], [-12, -12]] 

out = []
for i in range(len(data)):
    first =  max(i -1, 0)  # don't have the start of the slice <0
    last = min(i + 2, len(data))  # neither beyond the end of the list
    mean = [sum(col) // (last-first) for col in zip(*data[first:last])]
    out.append(mean)

print(out)

# [[4, 4], [9, 9], [12, 12], [5, 5], [-2, -2]] 

We take slices of data around the current item.

Then, we zip the sublists, and we calculate the result on the first (resp. second) values of the sublists.

Also, note that using Python's integer division, we get -2 for -3//2 , not -1 as you got by rounding to the closest to 0. If you really want to do that, you'll have to use a custom function for the division.

Here's a NumPy solution:

import numpy as np

def mean3(data):
    return np.convolve(np.r_[data[:2].mean(), data, data[-2:].mean()], np.ones(3), 'valid')//3
>>> np.apply_along_axis(mean3, 0, audio_data)
array([[ 4.,  4.],
       [ 9.,  9.],
       [12., 12.],
       [ 5.,  5.],
       [-2., -2.]])

Or, if you prefer the int(x/y) definition of integer division:

import numpy as np

def mean3(data):
   return (np.convolve(np.r_[data[:2].mean(), data, data[-2:].mean()], np.ones(3), 'valid')/3).astype(int)
>>> np.apply_along_axis(mean3, 0, audio_data)
array([[ 4,  4],
       [ 9,  9],
       [12, 12],
       [ 5,  5],
       [-1, -1]])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM