列表中每个连续段的平均值

4

我有一个列表:

sample_list = array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16])

我想计算每4个元素的平均值。但不是单独计算每4个元素,而是计算前4个元素的平均值:

1,2,3,4

接下来是:

2,3,4,5

紧接着:
3,4,5,6

等等。

结果将是第一个列表中每4个元素之间的平均数的数组或列表。

输出:

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

My attempt:

sample_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
splits = 4

def avgerage_splits(data):
    datasum = 0
    count = 0 
    for num in data:
        datasum += num
    count += 1
    if count == splits: 
        yield datasum / splits
        datasum = count = 0
if count: 
    yield datasum / count

print(list(average_splits(sample_list)))

[1.5, 3.5, 5.5, 7.5, 9.5, 11.0]

这不是我需要的输出,因为它在移动到新的4个元素集之前计算每4个元素的平均值。我想要的是只将列表中的一个元素向上移动,并计算这4个元素的平均值,以此类推。

4个回答

11
如果可用,实现此操作的简单方法是使用np.convolve。可以将其与np.ones数组进行卷积计算以计算滚动平均值
import numpy as np
sample_list = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], dtype=float)

w = 4
np.convolve(sample_list, np.ones(w), 'valid') / w

输出

array([ 2.5,  3.5,  4.5,  5.5,  6.5,  7.5,  8.5,  9.5, 10.5, 11.5, 12.5,   13.5, 14.5])

详情

np.convolve 在两个输入数组之间执行离散卷积。在这种情况下,np.ones(w)将是一个由指定窗口长度(此处为4)的许多1组成的数组array([1., 1., 1., 1.])sample_list

以下列表理解旨在复制np.convolve计算输出值的方式:

w = 4
np.array([sum(ones*sample_list[m:m+w]) for m in range(len(sample_list)-(w-1))]) / w 

array([ 2.5,  3.5,  4.5,  5.5,  6.5,  7.5,  8.5,  9.5, 10.5, 11.5, 12.5,
   13.5, 14.5])

因此,在每次迭代中,它将对“ ones”数组和当前窗口sample_list进行内积。

下面是一个示例,说明如何计算前几个输出,以使其更清晰。请注意,在此情况下,卷积指定的使用模式为valid,这意味着重叠总是完整的:

[1,1,1,1]
[1,2,3,4,5,6,7,8...]
= (1*1 + 1*2 + 1*3 + 1*4) / 4 = 2.5

并将以下内容翻译为:

  [1,1,1,1]
[1,2,3,4,5,6,7,8...]
= (1*2 + 1*3 + 1*4 + 1*5) / 4 = 3.5

因此,如前所述,得出了sample_list移动平均值


你能解释一下 np.ones() 是做什么的吗? - Mazz
1
是的,这非常有帮助。'移动平均线'正是我正在寻找的。已点赞并接受。非常感谢。 - Mazz
使用 numpy.convolve,我们也可以通过以下方式完成操作:new_list = np.convolve(sample_list, np.ones(4)/4, mode='valid') - Gonçalo Peres

4

您可以使用一行列表推导式:

avgs = [sum(sample_list[i:i + splits]) / splits for i in range(len(sample_list) - splits + 1)]

当然,如果您想要一个生成器,请将方括号替换为圆括号。

1
您可以将函数mean()映射到已压缩的迭代器:
from statistics import mean
from itertools import islice

l = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]

zip_iter = zip(*(islice(l, i, None) for i in range(4)))
list(map(mean, zip_iter))
# [2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5]

0
作为一个对大多数Python模块知之甚少的新程序员,这里提供另一种解决方案。4是分割数,可以根据需要进行调整。当3在(Len(nlis)-3)中等于4-1时,将3替换为您所需的分割数减1。
nlis = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]

summation = []
ave = []
for a in range(len(nlis)- 3):
    summation = sum(nlis[a:a+4])
    ave.append(summation/4)
print(ave)

# [2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接