2012-07-05 172 views
34

我在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

回答

68

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

0

我覺得是這樣的:

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

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

這不是最有效的方法,但它會給你的答案,我還不清楚,如果你的窗口是5分或10。如果其10與9.

22

移動平均值是一個卷積,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

4

接受的答案存在問題。我認爲我們需要使用「有效」而不是「相同」這裏 - 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

27

由於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://stackoverflow.com/questions/45839123/python-how-can-we-smooth-a-noisy-signal-using-moving-average – 2017-08-23 12:17:54

0

我的移動平均線功能,無需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