我正在尝试计算移动平均值,但每个平均值之间有一个设定的步长。例如,如果我计算 4 元素窗口每 2 个元素的平均值:
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
这应该产生 [1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10] 的平均值。
window_avg = [2.5, 4.5, 6.5, 8.5]
我的数据是这样的,在处理之前结尾会被截断,因此长度相对于窗口大小没有问题。
我读过一些关于如何在 Python 中进行移动平均线的内容,并且似乎有很多 itertools 的使用;然而,迭代器一次只处理一个元素,我不知道如何在每次计算平均值之间设置步长。 (How to calculate moving average in Python 3?)
我之前也能够在 MATLAB 中执行此操作,方法是创建一个重叠的索引矩阵,然后对数据向量进行索引并执行列均值 ( Create matrix by repeatedly overlapping a vector )。然而,由于这个向量相当大(约 70 000 个元素,450 个样本的窗口,每 30 个样本进行平均),计算可能需要太多内存。
任何帮助将不胜感激。我使用的是 Python 2.7。
最佳答案
在 Python 中计算列表上滑动窗口平均值的一种方法是使用列表推导式。您可以使用
>>> range(0, len(data), 2)
[0, 2, 4, 6, 8]
获取每个窗口的起始索引,然后使用numpy
的mean
函数获取每个窗口的平均值。请参阅下面的演示:
>>> import numpy as np
>>> window_size = 4
>>> stride = 2
>>> window_avg = [ np.mean(data[i:i+window_size]) for i in range(0, len(data), stride)
if i+window_size <= len(data) ]
>>> window_avg
[2.5, 4.5, 6.5, 8.5]
请注意,列表推导式确实有一个条件来确保它仅计算“完整窗口”的平均值,或恰好具有 window_size
元素的子列表。
当在 OP 中讨论的大小的数据集上运行时,此方法在我的 MBA 上的计算时间略多于 200 毫秒:
In [5]: window_size = 450
In [6]: data = range(70000)
In [7]: stride = 30
In [8]: timeit [ np.mean(data[i:i+window_size]) for i in range(0, len(data), stride)
if i+window_size <= len(data) ]
1 loops, best of 3: 220 ms per loop
在我的机器上,@Abhijit 提出的 itertools
方法的速度大约是两倍:
In [9]: timeit map(np.mean, izip(*(islice(it, i, None, stride) for i, it in enumerate(tee(data, window_size)))))
1 loops, best of 3: 436 ms per loop
关于python - Python 中重叠窗口的平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21097039/