我在列表中有一些事件时间,我想绘制它们的指数加权移动平均值。我可以使用以下代码执行此操作。
import numpy as np
import matplotlib.pyplot as plt
print "Code runnning"
a=0.01
l = [3.0,7.0,10.0,20.0,200.0]
y = np.zeros(1000)
for item in l:
y[item]=1
s = np.zeros(1000)
x = np.linspace(0,1000,1000)
for i in xrange(1000):
s[i] = a*y[i-1]+(1-a)*s[i-1]
plt.plot(x, s)
plt.show()
然而,这显然是一种使用python的可怕方式。这样做的正确方法是什么?是否可以在不制作所有这些额外稀疏数组的情况下完成它?
输出应该如下所示。
答案 0 :(得分:1)
import pandas as pd
l = [3.0,7.0,10.0,20.0,200.0]
s = pd.Series(np.ones_like(l), index=l)
y = s.reindex(range(1000), fill_value=0)
pd.ewma(y, 199).plot()
199 期间与您的参数alpha 0.01 相关,为n=2/(a+1)
。结果:
答案 1 :(得分:0)
AFAIK使用numpy
或scipy.sparse
模块执行此操作的方法不是很好 - scipy.sparse
中的稀疏矩阵设计为2D矩阵,并创建一个第一个地方你基本上需要使用你已经在第一个循环中编写的代码(即,在稀疏矩阵中设置所有非零位置),并且总是必须指定两个索引值。
好像这还不够,np.convolve
不适用于稀疏数组,所以你仍然需要在第二个循环中写出计算来计算移动平均值。
我的建议,如果你正在寻找一个花哨的numpy
版本可能没什么帮助,那就是回归Python作为通用语言的出色支持:
import matplotlib.pyplot as plt
a=0.01
l = set([3, 7, 10, 20, 200])
s = np.zeros(1000)
for i in xrange(len(s)):
s[i] = a * int(i-1 in l) + (1-a) * s[i-1]
plt.plot(s)
plt.show()
在这里,我已经将事件索引值存储在l中,就像你一样,但我使用set
来查找时间为O(1) - 尽管如果len(l)
不是非常大,你甚至可以用简单的列表或元组更好,你需要测量它以确定。然后,您可以避免创建y
数组,只需依靠Iverson's convention将布尔值x in y
转换为int
。你可能甚至不需要显式演员,但我觉得明确是有帮助的。
答案 2 :(得分:0)
我认为你正在寻找这样的东西:
import numpy as np
import matplotlib.pyplot as plt
from scikits.timeseries.lib.moving_funcs import mov_average_expw
l = [ 3.0, 7.0, 10.0, 20.0, 200.0 ]
y = np.zeros(1000)
y[[l]] = 1
emav = mov_average_expw(y, 199)
plt.plot(emav)
plt.show()
这可以使用mov_average_expw
中的scikits.timeseries
。检查该方法的文档,看看我是如何根据代码的a
变量提出span参数的。