如何使用pandas计算加权移动平均?

16

使用Pandas,我可以计算:

  • 使用 pandas.stats.moments.rolling_mean 计算简单移动平均线SMA
  • 使用 pandas.stats.moments.ewma 计算指数移动平均线EMA

但是,我如何像维基百科(http://en.wikipedia.org/wiki/Exponential_smoothing)所述一样计算加权移动平均线(WMA)? 是否有Pandas函数可以计算WMA?


这里有2个答案:https://dev59.com/Iqrka4cB1Zd3GeqPZShW#75495234 - Laurent B.
4个回答

17

使用pandas,您可以使用以下方式计算加权移动平均值(WMA):
.rolling()结合.apply()

这是一个带有3个权重和窗口= 3的示例

data = {'colA': random.randint(1, 6, 10)}
df = pd.DataFrame(data)

weights = np.array([0.5, 0.25, 0.25])
sum_weights = np.sum(weights)

df['weighted_ma'] = (df['colA']
    .rolling(window=3, center=True)
    .apply(lambda x: np.sum(weights*x) / sum_weights, raw=False)
)
请注意,在.rolling()中,我使用了参数center=True。您应该检查是否适用于您的用例,或者您是否需要center=False

7
不,没有实现那个确切的算法。在这里创建了一个GitHub问题:https://github.com/pydata/pandas/issues/886
我很乐意接受拉取请求——实现应该是简单的Cython编码,并可集成到pandas.stats.moments中。

2
非常感谢。我正准备在Github上添加一个功能请求。然后我看到了http://pandas.pydata.org/community.html上的评论,说要先在这里询问。 - thatshowthe
1
问题已经解决,支持在statsmodels中获取某些内容,但很难确定在statsmodels中有什么。存在ARMA模型,我猜如果将AR系数设置为0,就可以使用它了? - naught101

1
如果data是Pandas DataFrame或Series,且您想计算行上的WMA,则可以使用以下方法进行操作。
wma = data[::-1].cumsum().sum() * 2 / data.shape[0] / (data.shape[0] + 1)

如果您想使用窗口长度为n的滚动WMA,请使用以下代码。
data.rolling(n).apply(lambda x: x[::-1].cumsum().sum() * 2 / n / (n + 1))

n = x.shape[0] 时,请注意这个解决方案可能比 Sander van den Oord 的解决方案慢一些,但你不必担心权重问题。


你能解释一下为什么反转数据的累积和之和等于 n * P_n + (n-1)* P_(n-1) + ... + P_1 吗?我用 n=3 和 data=[1,2,3] 在纸上尝试了一下,但是我无法弄清楚到底发生了什么,即为什么 3 + 5 + 6 == 33 + 22 + 1*1(累积和之和等于加权和)。 - Elfen Dew
1
没问题!将cumsum()应用于反转的数据[3, 2, 1]会得到[3, 3+2, 3+2+1] = [3, 5, 6],如果你将这3个元素相加,你会得到3 + 5 + 6 = 3 + (3+2) + (3+2+1) = 3*3 + 2*2 + 1*1。你看,诀窍在于如何计算cumsum()。 - Sven Meinhardt

1
构建一个带有权重的内核,并使用numpy.convolve将其应用于您的系列。
import pandas as pd
import numpy as np

def wma(arr, period):
    kernel = np.arange(period, 0, -1)
    kernel = np.concatenate([np.zeros(period - 1), kernel / kernel.sum()])
    return np.convolve(arr, kernel, 'same')

df = pd.DataFrame({'value':np.arange(11)})
df['wma'] = wma(df['value'], 4)

根据此页面https://en.wikipedia.org/wiki/Moving_average,我在解释WMA。

对于这种类型的WMA,权重应该是n个值的线性范围,加起来等于1.0。

请注意,我在内核前面填充了零。这是因为我们想要一个“单侧”窗口函数,以便时间序列中的“未来”值不会影响移动平均值。

numpy.convolve很快,不像apply()!如果你反转内核,也可以使用numpy.correlate


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接