从Python中的数据点查找移动平均值

din*_*o_d 41 python plot average sum

我再次使用Python,我找到了一本带有例子的简洁书.其中一个例子是绘制一些数据.我有一个包含两列的.txt文件,我有数据.我把数据绘制得很好,但是在练习中它说:进一步修改程序以计算和绘制数据的运行平均值,定义如下:

$Y_k=\frac{1}{2r}\sum_{m=-r}^r y_{k+m}$
Run Code Online (Sandbox Code Playgroud)

其中r=5在此情况下(以及y_k在数据文件中的第二列).让程序在同一图表上绘制原始数据和运行平均值.

到目前为止我有这个:

from pylab import plot, ylim, xlim, show, xlabel, ylabel
from numpy import linspace, loadtxt

data = loadtxt("sunspots.txt", float)
r=5.0

x = data[:,0]
y = data[:,1]

plot(x,y)
xlim(0,1000)
xlabel("Months since Jan 1749.")
ylabel("No. of Sun spots")
show()
Run Code Online (Sandbox Code Playgroud)

那么如何计算总和呢?在Mathematica中它很简单,因为它是符号操作(例如Sum [i,{i,0,10}]),但是如何计算python中的sum,它取数据中的每十个点并对其进行平均,直到结束分数?

我看了看这本书,却发现没有什么可以解释这个:


heltonbiker的代码诀窍^^:D

from __future__ import division
from pylab import plot, ylim, xlim, show, xlabel, ylabel, grid
from numpy import linspace, loadtxt, ones, convolve
import numpy as numpy

data = loadtxt("sunspots.txt", float)

def movingaverage(interval, window_size):
    window= numpy.ones(int(window_size))/float(window_size)
    return numpy.convolve(interval, window, 'same')

x = data[:,0]
y = data[:,1]


plot(x,y,"k.")
y_av = movingaverage(y, 10)
plot(x, y_av,"r")
xlim(0,1000)
xlabel("Months since Jan 1749.")
ylabel("No. of Sun spots")
grid(True)
show()
Run Code Online (Sandbox Code Playgroud)

我得到了这个:

图片

非常感谢^^ :)

hel*_*ker 74

在阅读这个答案之前,请记住下面还有另一个答案,来自Roman Kh,它使用numpy.cumsum并且比这个更快.


最佳将一个移动/滑动平均值(或任何其他滑动窗函数)应用于信号的一种常用方法是使用numpy.convolve().

def movingaverage(interval, window_size):
    window = numpy.ones(int(window_size))/float(window_size)
    return numpy.convolve(interval, window, 'same')
Run Code Online (Sandbox Code Playgroud)

这里,interval是你的x数组,window_size是要考虑的样本数.窗口将以每个样本为中心,因此它在当前样本之前和之后采样以计算平均值.您的代码将变为:

plot(x,y)
xlim(0,1000)

x_av = movingaverage(interval, r)
plot(x_av, y)

xlabel("Months since Jan 1749.")
ylabel("No. of Sun spots")
show()
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

  • 嗯,这意味着你没有导入numpy.实际上,你只导入了一些函数:`linspace`和`loadtxt`.你应该添加`ones`和`convolve`; o) (2认同)

Rom*_* Kh 51

由于numpy.convolve相当慢,那些需要快速执行解决方案的人可能更喜欢更容易理解的cumsum方法.这是代码:

cumsum_vec = numpy.cumsum(numpy.insert(data, 0, 0)) 
ma_vec = (cumsum_vec[window_width:] - cumsum_vec[:-window_width]) / window_width
Run Code Online (Sandbox Code Playgroud)

其中,数据包含您的数据,并ma_vec将包含移动平均window_width长度.

平均而言,cumsum快于约30-40倍卷积.

  • 我想如果我今天要实现离线移动平均线,我会从一开始就使用你的解决方案,而不是卷积.其实我很惊讶这个答案没有得到更多的赞成... (2认同)
  • 为什么是“numpy.insert(data, 0, 0)”?它在数据的开头添加了一个 0,对吗? (2认同)
  • 开头的插入只加0是的。我不确定它的目的到底是什么。如果你想填充你的数组以保持类似的数组大小,你可以使用这个东西。通常: data = np.pad( data, int(wsize/2) , mode='edge') 将允许复制边缘值,并且不会获得比数据中原始值更低的值。如果 wsize 是奇数,则在数据开头添加补充 y[0] 很有用。 (2认同)

rep*_*cus 25

移动平均线是一个卷积,而numpy将比大多数纯粹的python操作更快.这将给你10点移动平均线.

import numpy as np
smoothed = np.convolve(data, np.ones(10)/10)
Run Code Online (Sandbox Code Playgroud)

如果您正在使用时间序列数据,我还强烈建议使用大熊猫包.内置了一些不错的移动平均操作.