我有很长时间的每周数据系列。对于给定的观察,我想计算该周的价值与同一个月前三年平均值的平均值。
具体示例:对于2019-02-15数据点,我想将其与所有feb-2018,feb-2017和feb-2016数据点的平均值进行比较。
我想以这种方式填充整个时间序列。 (前三年当然是np.nans
)
我做了一个非常粗略的单数据点示例我想做的计算,但我不知道如何在矢量化解决方案中实现它。我也不会对使用这个中间帮助表“mth_avg”感到印象深刻。
import pandas as pd
ix = pd.date_range(freq='W-FRI',start="20100101", end='20190301' )
df = pd.DataFrame({"foo": [x for x in range(len(ix))]}, index=ix) #weekly data
mth_avg = df.resample("M").mean() #data as a monthly average over time
mth_avg['month_hack'] = mth_avg.index.month
#average of previous three years' same-month averages
df['avg_prev_3_year_same-month'] = "?"
#single arbitrary example of my intention
df.loc['2019-02-15', "avg_prev_3_year_same-month"]= (
mth_avg[mth_avg.month_hack==2]
.loc[:'2019-02-15']
.iloc[-3:]
.loc[:,'foo']
.mean()
)
df[-5:]
我认为这实际上是一个非常重要的问题 - 我没有现有的功能我已经知道了Pandas。制作一个帮助表节省了计算时间,实际上我使用了两个。我的解决方案使用循环(即列表理解)和Pandas日期时间感知来避免你的month_hack
。否则我认为这是一个好的开始。很高兴看到更优雅的东西!
# your code
ix = pd.date_range(freq='W-FRI',start="20100101", end='20190301' )
df = pd.DataFrame({"foo": [x for x in range(len(ix))]}, index=ix)
mth_avg = df.resample("M").mean()
# use multi-index of month/year with month first
mth_avg.index = [mth_avg.index.month, mth_avg.index.year]
tmp = mth_avg.sort_index().groupby(level=0).rolling(3).foo.mean()
tmp.index = tmp.index.droplevel(0)
# get rolling value from tmp
res = [tmp.xs((i.month, i.year - 1)) for i in df[df.index > '2010-12-31'].index]
# NaNs for 2010
df['avg_prev_3_year_same-month'] = np.NaN
df.loc[df.index > '2010-12-31', 'avg_prev_3_year_same-month'] = res
# output
df.sort_index(ascending=False).head()
foo avg_prev_3_year_same-month
2019-03-01 478 375.833333
2019-02-22 477 371.500000
2019-02-15 476 371.500000
2019-02-08 475 371.500000
2019-02-01 474 371.500000