3 回答

TA貢獻(xiàn)1780條經(jīng)驗 獲得超5個贊
如果你只是想要一個簡單的非加權(quán)移動平均線,您可以輕松地實現(xiàn)它np.cumsum,這可能 是比基于FFT方法快:
編輯糾正了代碼中Bean發(fā)現(xiàn)的一個錯誤的索引。編輯
def moving_average(a, n=3) :
ret = np.cumsum(a, dtype=float)
ret[n:] = ret[n:] - ret[:-n]
return ret[n - 1:] / n
>>> a = np.arange(20)
>>> moving_average(a)
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.,
12., 13., 14., 15., 16., 17., 18.])
>>> moving_average(a, n=4)
array([ 1.5, 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, 15.5, 16.5, 17.5])
所以我猜答案是:它實現(xiàn)起來非常簡單,而且numpy可能已經(jīng)變得有點臃腫了。

TA貢獻(xiàn)1934條經(jīng)驗 獲得超2個贊
NumPy缺乏特定的特定于域的功能可能是由于Core Team的紀(jì)律和對NumPy主要指令的保真度:提供N維數(shù)組類型,以及創(chuàng)建和索引這些數(shù)組的函數(shù)。像許多基本目標(biāo)一樣,這個目標(biāo)并不小,NumPy非常出色。
(更大)的SciPy包含更大的域特定庫集合(SciPy開發(fā)人員稱為子包) - 例如,數(shù)值優(yōu)化(優(yōu)化),信號處理(信號)和積分微積分(積分)。
我的猜測是你所追求的功能至少在一個SciPy子包中(或許是scipy.signal); 然而,我會先看看SciPy scikits的集合,找出相關(guān)的scikit(s)并尋找那里感興趣的功能。
Scikits是基于NumPy / SciPy獨立開發(fā)的軟件包,并針對特定的技術(shù)學(xué)科(例如,scikits-image,scikits-learn等)。其中一些(特別是用于數(shù)值優(yōu)化的令人敬畏的OpenOpt)受到高度重視,成熟的項目早在選擇居住在相對較新的scikits標(biāo)題之前。該Scikits主頁喜歡約30個這樣的上述清單scikits,但至少數(shù)那些正在積極發(fā)展不再。
遵循這個建議會引導(dǎo)你到scikits-timeseries ; 但是,這個包裹不再處于積極發(fā)展之中; 實際上,Pandas已成為AFAIK,事實上 基于NumPy的時間序列庫。
熊貓有幾個可用于計算移動平均值的函數(shù); 其中最簡單的可能就是rolling_mean,你可以這樣使用:
>>> # the recommended syntax to import pandas
>>> import pandas as PD
>>> import numpy as NP
>>> # prepare some fake data:
>>> # the date-time indices:
>>> t = PD.date_range('1/1/2010', '12/31/2012', freq='D')
>>> # the data:
>>> x = NP.arange(0, t.shape[0])
>>> # combine the data & index into a Pandas 'Series' object
>>> D = PD.Series(x, t)
現(xiàn)在,只需調(diào)用函數(shù)rolling_mean傳遞Series對象和窗口大小,在下面的示例中為10天。
>>> d_mva = PD.rolling_mean(D, 10)
>>> # d_mva is the same size as the original Series
>>> d_mva.shape
(1096,)
>>> # though obviously the first w values are NaN where w is the window size
>>> d_mva[:3]
2010-01-01 NaN
2010-01-02 NaN
2010-01-03 NaN
驗證它是否有效 - 例如,比較原始系列中的值10 - 15與使用滾動平均值平滑的新系列
>>> D[10:15]
2010-01-11 2.041076
2010-01-12 2.041076
2010-01-13 2.720585
2010-01-14 2.720585
2010-01-15 3.656987
Freq: D
>>> d_mva[10:20]
2010-01-11 3.131125
2010-01-12 3.035232
2010-01-13 2.923144
2010-01-14 2.811055
2010-01-15 2.785824
Freq: D
Rolling_mean函數(shù)以及大約十幾個其他函數(shù)在Rubric 移動窗口函數(shù)下的Pandas文檔中非正式地分組; Pandas中第二個相關(guān)的函數(shù)組稱為指數(shù)加權(quán)函數(shù)(例如,ewma,它計算指數(shù)移動的加權(quán)平均值)。第二組未包含在第一組(移動窗口函數(shù))中的事實可能是因為指數(shù)加權(quán)變換不依賴于固定長度的窗口

TA貢獻(xiàn)1802條經(jīng)驗 獲得超5個贊
實現(xiàn)這一目標(biāo)的一種簡單方法是使用np.convolve。這背后的想法是利用計算離散卷積的方式,并使用它來返回滾動均值。這可以通過卷積np.ones一個長度等于我們想要的滑動窗口長度的序列來完成。
為此,我們可以定義以下函數(shù):
def moving_average(x, w):
return np.convolve(x, np.ones(w), 'valid') / w
該函數(shù)將對序列x和一系列長度進(jìn)行卷積w。請注意,所選擇的mode是valid僅對序列完全重疊的點給出卷積乘積。
用例
一些例子:
x = np.array([5,3,8,10,2,1,5,1,0,2])
對于具有長度窗口的移動平均線,2我們將:
moving_average(x, 2)
# array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])
并為一個長度的窗口4:
moving_average(x, 4)
# array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2. ])
細(xì)節(jié)
讓我們更深入地了解計算離散卷積的方式。以下函數(shù)旨在復(fù)制np.convolve計算輸出值的方式:
def mov_avg(x, w):
for m in range(len(x)-(w-1)):
yield sum(np.ones(w) * x[m:m+w]) / w
對于上面的相同例子,這也會產(chǎn)生:
list(mov_avg(x, 2))
# [4.0, 5.5, 9.0, 6.0, 1.5, 3.0, 3.0, 0.5, 1.0]
因此,在每一步中所做的是在1的數(shù)組和當(dāng)前窗口之間獲取內(nèi)積。在這種情況下,乘法np.ones(w)是多余的,因為我們直接采用sum序列。
貝婁是如何計算第一個輸出以使其更清晰的一個例子。讓我們想要一個窗口w=4:
[1,1,1,1]
[5,3,8,10,2,1,5,1,0,2]
= (1*5 + 1*3 + 1*8 + 1*10) / w = 6.5
以下輸出將計算為:
[1,1,1,1]
[5,3,8,10,2,1,5,1,0,2]
= (1*3 + 1*8 + 1*10 + 1*2) / w = 5.75
依此類推,一旦完成所有重疊,就返回序列的移動平均值。
添加回答
舉報