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

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

问题描述:

我在Python中再玩一遍,并且找到了一个带有示例的整洁书。其中一个例子是绘制一些数据。我有一个两列的.txt文件,我有数据。我绘制的数据不错,但在运动,它说:进一步修改程序来计算和绘制数据,通过规定的移动平均:从Python中的数据点中找到移动平均数

$Y_k=\frac{1}{2r}\sum_{m=-r}^r y_{k+m}$ 

其中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() 

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

我看着书,但没有发现任何可以解释这一点:\


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() 

而且我得到了这一点:

image

非常感谢你^^ :)

+1

这是奇怪的。由于我们没有你的txt文件,所以不可能在这里测试,但我认为'xlim'行不应该被使用(以防万一) – heltonbiker 2012-07-05 21:11:30

+0

我从这里得到了点:http:// www-personal。 umich.edu/~mejn/computational-physics/sunspots.dat 并删除xlim没有帮助:\ – 2012-07-05 21:14:29

+2

我犯了一个错误的代码!您必须在y阵列上执行平均值,而不是x: 'y_av = movingaverage(y,r)' 'plot(x,y_av)'。我想,你可以再次使用xlim。 – heltonbiker 2012-07-05 21:20:15

Before reading this answer, bear in mind that there is another answer below, from Roman Kh, which uses numpy.cumsum and is MUCH MUCH FASTER than this one.


最佳 一种常见方式替换每个5 10和4施加移动/到一个信号的滑动平均(或任何其它的滑动窗函数)是通过使用numpy.convolve()

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

在这里,时间间隔为您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() 

希望这有助于!

+0

这里我得到的错误: 回溯(最近呼叫最后): 文件“C:/用户/ ***** /桌面/ sunspots_plot.py”,第18行,在 x_av = movingaverage(x,5) 文件“C:/ Users/*****/Desktop/sunspots_plot.py”,第8行,移动平均值 window = numpy.ones(int(window_size ))/ float(window_size) NameError:没有定义全局名'numpy' – 2012-07-05 20:57:11

+2

嗯,这意味着你没有导入numpy。实际上,你只是从中导入了一些函数:'linspace'和'loadtxt'。你应该添加'ones'和'convolve'; o) – heltonbiker 2012-07-05 21:04:46

+0

我编辑了我的代码,现在我有了图像,但平均值只在图的最后部分,我应该手动更改间隔来排序? – 2012-07-05 21:09:49

我觉得是这样的:

aves = [sum(data[i:i+6]) for i in range(0, len(data), 5)] 

但我总是要仔细检查指标都在做什么,我的期望。你想要的范围是(0,5,10,...),data [0:6]会给你数据[0] ... data [5]

ETA:oops,当然,不是总和。因此,实际使用您的代码和公式:

r = 5 
x = data[:,0] 
y1 = data[:,1] 
y2 = [ave(y1[i-r:i+r]) for i in range(r, len(y1), 2*r)] 
y = [y1, y2] 
+0

有了这个我得到了一堆数组,我得到错误当我尝试绘制它们:\ – 2012-07-05 20:36:16

+0

对不起,没有修复一个错字,应该是y1 [ir:i + r]而不是数据 – dreadsci 2012-07-05 20:41:26

+0

而且无论如何,y1有len(y1)分,y2有len(y1)/2r点,所以......你想分别将它们添加到图中。改为使用卷积解决方案! – dreadsci 2012-07-05 20:46:57

ravgs = [sum(data[i:i+5])/5. for i in range(len(data)-4)] 

这不是最有效的方法,但它会给你的答案,我还不清楚,如果你的窗口是5分或10。如果其10与9.

移动平均值是一个卷积,numpy比大多数纯Python操作要快。这会给你10点移动平均线。

import numpy as np 
smoothed = np.convolve(data, np.ones(10)/10) 

我也要强烈使用大包熊猫建议,如果你是时间序列数据的工作。有一些不错的moving average operations built in

+0

我得到错误: 回溯(最近的通话最后): 文件“ C:\ Python26“C:/ Users/*****/Desktop/sunspots_plot.py”,第7行,在 smoothed = np.convolve(data,np.ones(10)/(10)) 文件“C:\ Python26 \ lib \ site-packages \ numpy \ core \ numeric.py“,第787行,在卷积 返回multiarray.correlate(a,v [:: - 1],模式) ValueError:object too deep for desired array – 2012-07-05 20:49:46

+0

Thats您的案例中的b/c数据是多维numpy数组,您应该传递一维数组。在你的情况下,它会平滑= np.convolve(y,np.ones/10) – reptilicus 2012-07-06 14:55:55

+0

+10到“使用熊猫”的建议。对于每个案例来说都不是很完美,但是对于阅读这篇文章的人来说,可能会节省很多麻烦。 – Owen 2017-01-25 08:58:58

接受的答案存在问题。我认为我们需要使用“有效”而不是“相同”这里 - return numpy.convolve(interval, window, 'same')

作为一个实施例尝试这个数据集= [1,5,7,2,6,7,8,2,2,7,8,3,7,3,7,3,15,6]的MA - 结果应该是[4.2,5.4,6.0,5.0,5.0,5.2,5.4,4.4,5.4,5.6,5.6,4.6,7.0,6.8],但是具有“相同”让我们的[2.6,3.0,4.2,5.4,6.0,5.0,5.0,5.2,5.4,4.4,5.4,5.6,5.6, 4.6,7.0,6.8,6.2,4.8]

生锈的代码不正确的输出,以尝试了这一点 - :

result=[] 
dataset=[1,5,7,2,6,7,8,2,2,7,8,3,7,3,7,3,15,6] 
window_size=5 
for index in xrange(len(dataset)): 
    if index <=len(dataset)-window_size : 
     tmp=(dataset[index]+ dataset[index+1]+ dataset[index+2]+ dataset[index+3]+ dataset[index+4])/5.0 
     result.append(tmp) 
    else: 
     pass 

result==movingaverage(y, window_size) 

试试这个有效的&相同,看看数学是否有意义。

参见 - :http://sentdex.com/sentiment-analysisbig-data-and-python-tutorials-algorithmic-trading/how-to-chart-stocks-and-forex-doing-your-own-financial-charting/calculate-simple-moving-average-sma-python/

+0

还没有尝试过,但我会研究它,它是自从我使用Python进行编码以来已经有一段时间了 – 2014-10-29 07:07:06

+0

@dingo_d为什么不快速尝试一下生锈的代码(以及示例数据集(作为一个简单列表),我发布了?对于一些懒惰的人(比如我一开始就是这样) - 它的掩码事实上,移动平均数是不正确的,可能你应该考虑编辑你的原始答案,我昨天试了一下,双重检查让我从面对报告到Cxo水平时面临不好的问题,你只需要尝试一次相同的移动平均值与“有效”和其他时间与“相同” - - 一旦你确信给我一些爱(aka-up-vote) – ekta 2014-10-29 07:16:22

+0

我目前工作,所以我没有访问Python,但是当我'在家我会试试:) – 2014-10-29 07:25:18

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

cumsum_vec = numpy.cumsum(numpy.insert(data, 0, 0)) 
ma_vec = (cumsum_vec[window_width:] - cumsum_vec[:-window_width])/window_width 

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

平均而言,cumsum卷积快了约30-40倍。

+2

我想如果我今天要实现一个离线移动平均线,我会从一开始就使用您的解决方案,而不是使用卷积。其实我很惊讶这个答案还没有收到很多upvotes ... – heltonbiker 2016-08-09 17:13:58

+0

'step'参数在哪里? – 2016-08-11 17:03:45

+0

@ roman-kh,如果你能看看这个和谢谢,我将不胜感激。 https://*.com/questions/45839123/python-how-can-we-smooth-a-noisy-signal-using-moving-average – 2017-08-23 12:17:54

我的移动平均线功能,无需numpy的功能:

from __future__ import division # must be on first line of script 

class Solution: 
    def Moving_Avg(self,A): 
     m = A[0] 
     B = [] 
     B.append(m) 
     for i in range(1,len(A)): 
      m = (m * i + A[i])/(i+1) 
      B.append(m) 
     return B 
+0

对不起,添加第一行:from _future_ import division。否则输出将是int而不是float – 2015-12-23 22:09:39

+0

@Arnanda_An,你可以在'1'中用一个小数点强制在Python 2中进行浮点除法:m =(m * i + A [i])/(i + 1 。)' – 2017-08-02 14:38:12