用numpy和csv绘制移动平均线

时间:2013-08-17 20:45:34

标签: arrays numpy matplotlib plot average

我需要帮助在我已经能够绘制的数据之上绘制移动平均线(见下文)

我试图让m(我的移动平均线)等于y(我的数据)的长度,然后在我的'for'循环中,我似乎对我的移动平均线有正确的数学。

什么有效:绘制x和y

什么行不通:在x和x之上绘制m? y并给我这个错误

RuntimeWarning:double_scalars中遇到无效值

我的理论:我将m设置为np.arrays = y.shape,然后创建for循环使m等于循环内的数学集,从而将所有0替换为移动平均值

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import csv
import math


def graph():
    date, value = np.loadtxt("CL1.csv", delimiter=',', unpack=True,
                         converters = {0: mdates.strpdate2num('%d/%m/%Y')})
    fig = plt.figure()

    ax1 = fig.add_subplot(1,1,1, axisbg = 'white')

    plt.plot_date(x=date, y=value, fmt = '-')

    y = value
    m = np.zeros(y.shape)
    for i in range(10, y.shape[0]):
       m[i-10] = y[i-10:1].mean()

    plt.plot_date(x=date, y=value, fmt = '-', color='g')
    plt.plot_date(x=date, y=m, fmt = '-', color='b')

    plt.title('NG1 Chart')
    plt.xlabel('Date')
    plt.ylabel('Price')

    plt.show()

graph ()

3 个答案:

答案 0 :(得分:1)

这里的问题存在于你对移动平均线的计算中 - 你只是在索引中遇到了几个一对一的问题!

y = value
m = np.zeros(y.shape)
for i in range(10, y.shape[0]):
   m[i-10] = y[i-10:1].mean()

除了:1]之外,你已经掌握了一切。这告诉解释器从i-10恰好是什么开始,并在1之前结束。但如果i-10大于1,则会产生空列表!要解决此问题,只需将1替换为i

此外,您的范围最后需要延长一个。将y.shape[0]替换为y.shape[0]+1

替代

我只是想提一下,您可以使用np.convolvedocs)更自动地计算移动平均线:

m = np.convolve(y, [1. / 10] * 10, 'same')

在这种情况下,m的长度与y相同,但移动平均值在开头和结尾可能看起来很奇怪。这是因为'same'有效地导致y在两端用零填充,以便在计算卷积时有足够的y值。

如果您只想获得使用y(而不是其他零填充)的值计算的移动平均值,则可以将'same'替换为'valid'。在这种情况下,正如Ryan指出的那样,m将比y(更确切地说,len(m) == len(y) - len(filter) + 1)更短,您可以通过删除您的第一个或最后一个元素来解决这个问题。日期数组。

答案 1 :(得分:1)

我认为lmjohns3的答案是正确的,但你的移动平均功能有几个问题。首先,lmjohns3指出了索引问题。以下列数据为例:

In [1]: import numpy as np

In [2]: a = np.arange(10)

In [3]: a
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

您的函数提供以下移动平均值:

In [4]: for i in range(3, a.shape[0]):
   ...:     print a[i-3:i].mean(),
1.0 2.0 3.0 4.0 5.0 6.0 7.0

此数组(7)的大小太小了一个数字。移动平均线的最后一个值应为(7 + 8 + 9)/ 3 = 8。要解决此问题,您可以按如下方式更改功能:

In [5]: for i in range(3, a.shape[0] + 1):
    ...:     print a[i-3:i].sum()/3,
1 2 3 4 5 6 7 8

第二个问题是,为了绘制两组数据,数据点的总数需要相同。您的函数返回一组小于原始数据集的新数据。 (您可能没有注意到,因为您预先分配了一个相同大小的零数组。您的for循环将始终生成一个末尾带有一堆零的数组。)

卷积函数为您提供了正确的数据,但由于same参数,它有两个额外的值(每端有一些),这可以确保新数据数组与原始数据大小相同。 / p>

In [6]: np.convolve(a, [1./3]*3, 'same')
Out[6]: 
array([ 0.33333333,  1.        ,  2.        ,  3.        ,  4.        ,
        5.        ,  6.        ,  7.        ,  8.        ,  5.66666667])

作为替代方法,您可以使用Numpy的cumsum function对代码进行矢量化。

In [7]: (cs[3-1:] - np.append(0,cs[:-3]))/3.
Out[7]: array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.])

(最后一个是对previous post中答案的修改。)

诀窍可能是您应该删除date数组的第一个值。例如,使用以下绘图调用,其中n是平均值中的点数:

plt.plot_date(x=date[n-1:], y=m, fmt = '-', color='b')

答案 2 :(得分:0)

好吧,无论是我疯了还是实际工作 - 我将我的图表与另一张图表进行了对比,它似乎有效。

这有意义吗?

m = np.zeros(y.shape)
for i in range(10, y.shape[0]):
    m[i-10] = y[i-10:i].mean()
plt.plot_date(x=date, y=m, fmt = '-', color='r')