Pandas 5 年和 10 年移动平均线

Pandas 5yr & 10yr Moving average

我有一个数据框,其中我的索引是 datetime dtype,但日期没有按任何顺序排列。我希望计算我的数据集的 5 年和 10 年移动平均值。通过使用 .rolling_mean 我可以根据我设置的 window 取平均值,但是,由于日期不是连续的,所以这不起作用。

Dataframe:
    Date          Count
    1981-01-08    10
    1981-05-12    65
    1982-03-17    96
    1982-09-15    33
    1982-12-01    85
    1983-02-03    14
    .
    .
    . 
    2017-01-28    56

Code: 
counts_df = pd.DataFrame(df.groupby('DATE').size().rename('counts'))
start_date_periods = counts_df.loc[counts_df.index > '1981-01-01']
start_date_periods['5yrMA'] = pd.rolling_mean(start_date_periods, window=5)
start_date_periods['10yrMA'] = pd.rolling_mean(start_date_periods, window=10)

在计算滚动数据之前,根据索引对数据框进行排序。

这是滚动功能如所宣传的那样工作但没有按您希望的那样工作的情况之一。在最新版本的 Pandas 中,您应该在使用 rolling_mean 时收到警告,因为它已被弃用,取而代之的是 rolling 因此为了说明,我将使用 rolling:

滚动函数旨在处理任何数据,而不仅仅是时间序列。所以它 'looks back' x 单位数。使用 window 参数设置回溯。它根据数据帧的排序顺序进行回顾。因此,即使您对数据进行了正确排序,rolling 也不知道当您给它一个 window 5 时,您指的是年份......它只看到 "look back 5 cells"

因此,如果您想回顾 5 年前的缺失值数据,您需要用一些东西来填充这些值。您可以使用 NaN,也可以使用 Pandas 提供的众多插值方法之一。我将说明 NaN 方法:

因为你没有提供一些简单易用的合成数据,我设置了一些:

np.random.seed(1)
ts_data = pd.DataFrame(np.random.randn(6210),
                       index = pd.date_range('2000-01-01', '2016-12-31', freq='D'), 
                       columns=['data']) # index of every day for 7 years

ts_sample = ts_data.sample(n=10).sort_index() ## sample then sort
print ts_sample

那个 returns 一个很好排序的例子 df 有 10 个值和一个日期索引:

               data
2001-07-21  0.107343
2003-07-12  0.658537
2004-08-21 -0.463338
2006-07-13 -0.866955
2011-12-14  0.020956
2012-05-14 -2.685125
2012-12-27  0.494037
2013-06-09 -1.299026
2013-12-12  0.371309
2015-06-17  0.201656

所以为了填补那些缺失的值,让我们创建一个新的 df,其中只有一个包含所有日期的完整索引:

full_period = pd.DataFrame(index = pd.date_range('2000-01-01', '2016-12-31', freq='D') )

由于 Pandas 使用索引的方式,如果将我们的示例数据弹出到列中,Pandas 将使用 NaN:

填充缺失值
full_period['data'] = ts_sample.data
print full_period['2015-06-16':'2015-06-18']

我只打印了三天,所以我们可以看看它是如何弹出数据的:

                data
2015-06-16       NaN
2015-06-17  0.201656
2015-06-18       NaN

所以现在我们有了完整的每日数据集,缺失数据用 NaN 填充。现在我们可以做滚动均值了:

rolling = full_period.rolling(min_periods=1, window=365*5,center=False).mean() # daily data so using 5 years of days
print rolling['2015-06-16':'2015-06-18']

并再次打印相同的 3 个值:

                data
2015-06-16 -0.619570
2015-06-17 -0.482699
2015-06-18 -0.482699

如果您只想select返回原始日期的滚动平均值,您可以使用一个小衬垫来做到这一点:

print rolling.ix[ts_sample.index.tolist()]

                data
2001-07-21  0.107343
2003-07-12  0.382940
2004-08-21  0.100847
2006-07-13 -0.141103
2011-12-14  0.020956
2012-05-14 -1.332085
2012-12-27 -0.723377
2013-06-09 -0.867290
2013-12-12 -0.619570
2015-06-17 -0.482699

使用pandas中的当前rolling函数,可以直接传window天的大小:rolling('365d') 1年,rolling('1826d') 5年其中考虑了闰年的额外天数(不是很准确,但涵盖了大多数情况),滚动('3652d')10 年。将仅计算滚动 window.

中观察到的数据点的平均值