【问题标题】:How to get moving average of past months in Pandas如何在熊猫中获得过去几个月的移动平均值
【发布时间】:2018-01-31 05:36:12
【问题描述】:

我有一个数据集,第一列是日期,第二列是价格。 日期为交易日。

我要返回的表是这样的:

其中日期是从2006年开始的每个月,价格MA是过去N个月的平均价格。(N = [1,2,3,4,5,6])

例如:如果我希望 N = 1 在 2006 年 1 月 1 日 马应该是去年12月的平均价格 如果 N =2 Ma 应该是去年 11 月和 12 月的平均价格

我已经阅读了一些关于从 datetime 和 groupby 中提取月份的解决方案。 但不知道如何将它们放在一起。

【问题讨论】:

  • here并使用滚动平均值

标签: python pandas datetime


【解决方案1】:

将返回窗口参数指定的周期数的滚动平均值。例如。 window=1 将返回原始列表。 Window=2 将计算 2 天的平均值,依此类推。

index=pd.date_range(start="4th of July 2017",periods=30,freq="D")



df=pd.DataFrame(np.random.randint(0,100,30),index=index)


print([pd.rolling_mean(df,window=i,freq="D") for i in range(1,5)])

.....

2017-07-04   NaN
2017-07-05  20.5
2017-07-06  64.5
2017-07-07  58.5
2017-07-08  13.0
2017-07-09   4.5
2017-07-10  17.5
2017-07-11  23.5
2017-07-12  40.5
2017-07-13  60.0
2017-07-14  73.0
2017-07-15  90.0
2017-07-16  56.5
2017-07-17  55.0
2017-07-18  57.0
2017-07-19  45.0
2017-07-20  77.0
2017-07-21  46.5
2017-07-22   3.5
2017-07-23  48.5
2017-07-24  71.5
2017-07-25  52.0
2017-07-26  56.5
2017-07-27  47.5
2017-07-28  64.0
2017-07-29  82.0
2017-07-30  68.0
2017-07-31  72.5
2017-08-01  58.5
2017-08-02  67.0

.....

您还可以使用 df dropna 方法删除 NA 值,例如:

df.rolling(window=2,freq="D").mean().dropna() #Here you must adjust the window  size

所以应该打印你几个月的滚动平均值的整个代码是:

print([df.rolling(i,freq="m").mean().dropna() for i in range(len(df.rolling(window=1,freq="m").sum()))])

【讨论】:

  • 但是,特定月份的交易天数并不是一个固定的数字。我该怎么办
  • 可以设置频率为月
  • df.sort_index().rolling(1,freq="m").mean().dropna() 参考文
  • 这将以月份为频率,与该月有多少天无关
  • 但自然要调整频率参数
【解决方案2】:

或者你干脆试试

df.sort_index(ascending=False).rolling(5).mean().sort_index(ascending=True)

关于您的其他问题

index=pd.date_range(start="4th of July 2017",periods=30,freq="D")
df=pd.DataFrame(np.random.randint(0,100,30),index=index)
df['Month']=df.index
df.Month=df.Month.astype(str).str[0:7]
df.groupby('Month')[0].mean()


Out[162]: 
Month
2017-07    47.178571
2017-08    56.000000
Name: 0, dtype: float64

编辑 3:对于滚动两个月平均值的缺失值

index=pd.date_range(start="4th of July 2017",periods=300,freq="D")
df=pd.DataFrame(np.random.randint(0,100,300),index=index)
df['Month']=df.index
df.Month=df.Month.astype(str).str[0:7]
df=df.groupby('Month')[0].agg({'sum':'sum','count':'count'})
df['sum'].rolling(2).sum()/df['count'].rolling(2).sum()


Out[200]: 
Month
2017-07          NaN
2017-08    43.932203
2017-09    45.295082
2017-10    46.967213
2017-11    46.327869
2017-12    49.081967
#etc

【讨论】:

  • 结合 dropna 来去掉末尾的 NA 值,比如df.sort_index().rolling(5).mean().dropna()
  • @2Obe 也许他想要 fillna 有一些价值
  • 通过使用 rolling(5) 我们将观察数固定为 5 对吗?但上个月的交易天数不是固定的。
  • @Wen 谢谢,我发现 df.resample('M').mean() 在 N = 1 时完全解决了我的问题。当我想尝试 N = 2 的情况时。我使用 df.resample('2M').mean() 我得到一月、三月、五月、七月。这些数字是我想要的正确数字(过去 2 个月的平均值。)但是我没有 2 月、4 月等的价格。我应该如何修改这个?
【解决方案3】:

首先,设置Date为索引:

price_df.set_index('Date', inplace=True)
price_df.index = pd.to_datetime(price_df.index)

然后,计算过去 N 个月的移动平均值:
mv = price_df.rolling(window=i*30, center=False).mean().dropna() for N=i

最后,只返回每个月的第一天的子集(如果你想返回的话):
mv.ix[mv.index.day==1]

【讨论】:

  • 您假设每个月有 30 天,这是不正确的
猜你喜欢
  • 1970-01-01
  • 2021-08-16
  • 1970-01-01
  • 2023-02-17
  • 2015-09-11
  • 2021-04-04
  • 2020-04-23
  • 1970-01-01
相关资源
最近更新 更多