考虑一个由某个变量组成的不平衡面板:对于每个组,我观察到一个由季度末日期时间对象标识的季度时间序列。时间序列可能有洞,组可能有不同季度的观测值。
我的目标是,以每个组为条件,将季度末的观察结果分配给下个季度的三个月。以组1
的季度2009-12-31
的观察4
为例。我想为组1
生成一个时间序列,该时间序列具有三个月2010-01-31, 2010-02-28, 2010-03-31
的观察4
,但不适用于2009-12-31
。
在我的尝试中,我将季度末的观测值偏移了一个月,使用"M"重新采样,然后使用ffill()
转发填充。但是,这并不能适当地照顾最后一个季度。虽然,我可以手动处理上个月,但我觉得必须有一个更直接的解决方案。
我感谢任何帮助。
这是MWE:
import pandas as pd
date = pd.to_datetime(['2009-12-31','2010-03-31','2010-06-30','2010-09-30','2014-03-31','2014-06-30','2015-09-30','2015-12-31','2016-03-30'])
group = [1,1,1,1,1,1,2,2,2]
variable = [4,5,6,7,8,9,10,11,12]
data = {'date':date, 'group':group, 'var':variable}
df = pd.DataFrame(data)
df.set_index(['group','date'], inplace=True)
下面是输入数据帧:
var
group date
1 2009-12-31 4
2010-03-31 5
2010-06-30 6
2010-09-30 7
2014-03-31 8
2014-06-30 9
2 2015-09-30 10
2015-12-31 11
2016-03-30 12
这是我的期望:
var
group date
1 2010-01-31 4
2010-02-28 4
2010-03-31 4
2010-04-30 5
2010-05-31 5
2010-06-30 5
2010-07-31 6
2010-08-31 6
2010-09-30 6
2010-10-31 7
2010-11-30 7
2010-12-31 7
2014-04-30 8
2014-05-31 8
2014-06-30 8
2014-07-31 9
2014-08-31 9
2014-09-30 9
2 2015-10-31 10
2015-11-30 10
2015-12-31 10
2016-01-31 11
2016-02-28 11
2016-03-31 11
2016-04-30 12
2016-05-31 12
2016-06-30 12
首先创建新组g1
,连续季度按DataFrameGroupBy.diff
比较每个组的差异,这里是 100 天(3 个月(,下个月也增加了 3 天:
df = df.reset_index()
df['date'] = df['date'] + pd.Timedelta(3, unit='d')
df['g1'] = df.groupby('group')['date'].diff().dt.days.gt(100).cumsum()
然后有必要添加具有上次重复值和未来 2 个月的日期时间的帮助程序DataFrame
,以避免仅最后一行:
last = (df.drop_duplicates(['group','g1'], keep='last')
.assign(date = lambda x: x['date'] + pd.offsets.DateOffset(months=2)))
print (last)
group date var g1
3 1 2010-12-03 7 0
5 1 2014-09-03 9 1
8 2 2016-06-02 12 1
加入原件并使用DataFrameGroupBy.resample
:
df = (pd.concat([df, last])
.set_index('date')
.groupby(['group', 'g1'])['var']
.resample('m')
.ffill()
.reset_index(level=1, drop=True))
print(df)
group date
1 2010-01-31 4
2010-02-28 4
2010-03-31 4
2010-04-30 5
2010-05-31 5
2010-06-30 5
2010-07-31 6
2010-08-31 6
2010-09-30 6
2010-10-31 7
2010-11-30 7
2010-12-31 7
2014-04-30 8
2014-05-31 8
2014-06-30 8
2014-07-31 9
2014-08-31 9
2014-09-30 9
2 2015-10-31 10
2015-11-30 10
2015-12-31 10
2016-01-31 11
2016-02-29 11
2016-03-31 11
2016-04-30 12
2016-05-31 12
2016-06-30 12
Name: var, dtype: int64