57

我又玩了一下 Python,发现了一本带有示例的简洁书。示例之一是绘制一些数据。我有一个包含两列的 .txt 文件,并且我有数据。我将数据绘制得很好,但在练习中它说:进一步修改您的程序以计算和绘制数据的运行平均值,定义为:

$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 中计算总和,它取数据中的每十个点并取平均值,直到最后点数?

我看了这本书,但没有找到任何可以解释这一点的东西:\


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

我得到了这个:

图片

非常感谢^^ :)

4

7 回答 7

97

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

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

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

平均而言,cumsum比convolve快 30-40 倍。

于 2015-12-21T02:00:15.293 回答
90

在阅读这个答案之前,请记住下面还有另一个答案,来自 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')

在这里,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()

希望这可以帮助!

于 2012-07-05T20:37:47.593 回答
31

移动平均是卷积,numpy 会比大多数纯 python 操作更快。这将为您提供 10 点移动平均线。

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

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

于 2012-07-05T20:41:10.537 回答
4
ravgs = [sum(data[i:i+5])/5. for i in range(len(data)-4)]

这不是最有效的方法,但它会给出您的答案,我不清楚您的窗口是 5 分还是 10。如果是 10,请将每个 5 替换为 10,将 4 替换为 9。

于 2012-07-05T20:36:15.813 回答
4

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

作为一个例子,试试这个数据集的 MA = [1,5,7,2,6,7,8,2,2,7,8,3,7,3,7,3,15,6]- 结果应该是[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) 

用 valid & same 试试这个,看看数学是否有意义。

另见-:http ://sentdex.com/sentiment-analysisbig-data-and-python-tutorials-algorithmic-trading/how-to-chart-stocks-and-forex-doing-your-own-financial-charting/计算简单移动平均 sma-python/

于 2014-10-29T04:27:19.317 回答
1

我的移动平均线函数,没有 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
于 2015-12-23T22:07:26.657 回答
0

我认为是这样的:

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

但我总是要仔细检查指数是否符合我的预期。你想要的范围是 (0, 5, 10, ...) 和 data[0:6] 会给你 data[0]...data[5]

ETA:哎呀,当然,你想要 ave 而不是 sum。所以实际上使用你的代码和公式:

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]
于 2012-07-05T20:29:20.280 回答