如何在熊猫中迭代时间段

时间:2015-03-17 13:40:36

标签: python pandas

考虑我有一只带有Series日常频率的大熊猫DatetimeIndex。我想以任意频率和任意回顾窗口迭代这个Series。例如:半年一次,回溯期为1年。

这样的事情是理想的:

for df_year in df.timegroup(freq='6m', lookback='1y'):
   # df_year will span one year of daily prices and be generated every 6 months

我知道TimeGrouper但我们还没弄清楚它是如何做到这一点的。无论如何,我可以手动编码,但希望有一个聪明的pandas单行。

编辑: 这有点接近:

pd.rolling_apply(df, 252, lambda s: s.sum(), freq=pd.datetools.BMonthEnd())

这并不是很有效,因为它应用252 * BMonthEnd()的回顾窗口,而我希望它是独立的,并且回溯窗口为252 每个月末。

2 个答案:

答案 0 :(得分:4)

我认为这就是你要找的东西

构建一系列频率。使用1来澄清这里。

In [77]: i = pd.date_range('20110101','20150101',freq='B')

In [78]: s = Series(1,index=i)

In [79]: s
Out[79]: 
2011-01-03    1
2011-01-04    1
2011-01-05    1
2011-01-06    1
2011-01-07    1
             ..
2014-12-26    1
2014-12-29    1
2014-12-30    1
2014-12-31    1
2015-01-01    1
Freq: B, dtype: int64

In [80]: len(s)
Out[80]: 1044

将索引符合另一个频率。这使得每个索引元素都是这里的月末。

In [81]: s.index = s.index.to_period('M').to_timestamp('M')

In [82]: s
Out[82]: 
2011-01-31    1
2011-01-31    1
2011-01-31    1
2011-01-31    1
2011-01-31    1
             ..
2014-12-31    1
2014-12-31    1
2014-12-31    1
2014-12-31    1
2015-01-31    1
dtype: int64

然后直接重新采样到另一个频率。这将为您提供此时期间的工作日数。

In [83]: s.resample('3M',how='sum')
Out[83]: 
2011-01-31    21
2011-04-30    64
2011-07-31    65
2011-10-31    66
2012-01-31    66
              ..
2014-01-31    66
2014-04-30    63
2014-07-31    66
2014-10-31    66
2015-01-31    44
Freq: 3M, dtype: int64

答案 1 :(得分:3)

此解决方案使用列表理解提供单行。从时间序列的左侧开始并向前迭代(也可以进行向后迭代),迭代返回索引的子集,该子集等于环回窗口,并以等于频率的步长跳转。请注意,最后一个句点可能是长度小于回顾窗口的存根。

此方法使用天而不是月或周偏移。

freq = 30      # Days
lookback = 60  # Days

idx = pd.date_range('2010-01-01', '2015-01-01')
[idx[(freq * n):(lookback + freq * n)] for n in range(int(len(idx) / freq))]

Out[86]: 
[<class 'pandas.tseries.index.DatetimeIndex'>
 [2010-01-01, ..., 2010-03-01]
 Length: 60, Freq: D, Timezone: None,
 <class 'pandas.tseries.index.DatetimeIndex'>
 [2010-01-31, ..., 2010-03-31]
 Length: 60, Freq: D, Timezone: None,
...
 Length: 60, Freq: D, Timezone: None,
 <class 'pandas.tseries.index.DatetimeIndex'>
 [2014-11-06, ..., 2015-01-01]
 Length: 57, Freq: D, Timezone: None]