Python 加快对每个组的结束日期和开始日期进行重新采样,但保持日期之间的间隔
我有以下数据帧:Python 加快对每个组的结束日期和开始日期进行重新采样,但保持日期之间的间隔,python,pandas,dataframe,time-series,Python,Pandas,Dataframe,Time Series,我有以下数据帧: df = pd.DataFrame({'startdate': ['2013-03-04', '2012-01-02', '2012-08-06', '2013-02-04', '2013-05-07'], 'enddate': ['2013-03-07', '2012-01-06', '2012-08-10', '2013-02-11', '2013-05-09'], 'regnr': [111, 1
df = pd.DataFrame({'startdate': ['2013-03-04', '2012-01-02', '2012-08-06', '2013-02-04', '2013-05-07'],
'enddate': ['2013-03-07', '2012-01-06', '2012-08-10', '2013-02-11', '2013-05-09'],
'regnr': [111, 111, 111, 222, 222],
'contracttype': ['ABU', 'ABU', 'ULDB', 'ULDB', 'ABU']})
df['startdate'], df['enddate'] = pd.to_datetime(df['startdate']), pd.to_datetime(df['enddate'])
print(df)
startdate enddate regnr contracttype
0 2013-03-04 2013-03-07 111 ABU
1 2012-01-02 2012-01-06 111 ABU
2 2012-08-06 2012-08-10 111 ULDB
3 2013-02-04 2013-02-11 222 ULDB
4 2013-05-07 2013-05-09 222 ABU
我想要的是将startdate和enddate扩展(重新采样)为每日时间序列。但重要的是,我们要保持日期之间的间隔。因此,如果你看一下regnr=111
,我们会在索引2中看到enddate=2012-11-04
,而下一个startdate=2013-03-04
在索引0上。所以这两个日期之间有差距
因此,预期产出是:
date regnr contracttype
0 2013-03-04 111 ABU
1 2013-03-05 111 ABU
2 2013-03-06 111 ABU
3 2013-03-07 111 ABU
4 2012-01-02 111 ABU
5 2012-01-03 111 ABU
6 2012-01-04 111 ABU
7 2012-01-05 111 ABU
8 2012-01-06 111 ABU
9 2012-08-06 111 ULDB
10 2012-08-07 111 ULDB
11 2012-08-08 111 ULDB
12 2012-08-09 111 ULDB
13 2012-08-10 111 ULDB
14 2013-02-04 222 ULDB
15 2013-02-05 222 ULDB
16 2013-02-06 222 ULDB
17 2013-02-07 222 ULDB
18 2013-02-08 222 ULDB
19 2013-02-09 222 ULDB
20 2013-02-10 222 ULDB
21 2013-02-11 222 ULDB
22 2013-05-07 222 ABU
23 2013-05-08 222 ABU
24 2013-05-09 222 ABU
那么问题出在哪里? 我有一个可行的解决方案,但有点慢。对于66k行的数据帧,我需要约90-110秒的时间,最终将重新采样到1050万行 以下是可行的解决方案:
def resample_data(df):
"""
:param df: dataframe where datetime has to be resampled to daily
:return: resampled dataframe
"""
tables = []
for _, d in df.groupby('regnr'):
for __, data in d.iterrows():
dates = pd.date_range(data['startdate'], data['enddate'])
dfn = pd.DataFrame({'regnr': data['regnr'],
'contracttype': data['contracttype']}, index=dates)
tables.append(dfn)
df = pd.concat(tables).rename_axis('date').reset_index()
return df
矢量化解决方案,但不起作用 因此,我尝试了一种矢量化方法(除了在groupby中应用),但这不起作用,因为它将填补日期之间的空白
dfn = df.melt(id_vars=['regnr', 'contracttype'],
value_name='date',
var_name='start_end').drop('start_end', axis=1)
dfn = (
dfn.groupby('regnr').apply(lambda x: x.set_index('date').resample('D').first().ffill())
.reset_index(level=0, drop=True)
.reset_index()
)
print(dfn)
date regnr contracttype
0 2012-01-02 111.0 ABU
1 2012-01-03 111.0 ABU
2 2012-01-04 111.0 ABU
3 2012-01-05 111.0 ABU
4 2012-01-06 111.0 ABU
.. ... ... ...
521 2013-05-05 222.0 ULDB
522 2013-05-06 222.0 ULDB
523 2013-05-07 222.0 ABU
524 2013-05-08 222.0 ABU
525 2013-05-09 222.0 ABU
[526 rows x 3 columns]
我不确定它是否满足要求,但我认为下面的代码可以处理它。但是,我还没有检查执行速度
tables = pd.DataFrame(index=[], columns=['Date','regnr','contracttype'])
for i in range(len(df)):
days = pd.DataFrame({'Date':list(pd.date_range(df.startdate[i], df.enddate[i])),
'regnr':[df.regnr[i]]*len(pd.date_range(df.startdate[i],df.enddate[i])),
'contracttype':[df.contracttype[i]]*len(pd.date_range(df.startdate[i], df.enddate[i]))})
tables = pd.concat([tables, days], ignore_index=True)
Date regnr contracttype
0 2013-03-04 111 ABU
1 2013-03-05 111 ABU
2 2013-03-06 111 ABU
3 2013-03-07 111 ABU
4 2012-01-02 111 ABU
5 2012-01-03 111 ABU
6 2012-01-04 111 ABU
7 2012-01-05 111 ABU
8 2012-01-06 111 ABU
9 2012-08-06 111 ULDB
10 2012-08-07 111 ULDB
11 2012-08-08 111 ULDB
12 2012-08-09 111 ULDB
13 2012-08-10 111 ULDB
14 2013-02-04 222 ULDB
15 2013-02-05 222 ULDB
16 2013-02-06 222 ULDB
17 2013-02-07 222 ULDB
18 2013-02-08 222 ULDB
19 2013-02-09 222 ULDB
20 2013-02-10 222 ULDB
21 2013-02-11 222 ULDB
22 2013-05-07 222 ABU
23 2013-05-08 222 ABU
24 2013-05-09 222 A
df1=pd.concat([pd.DataFrame({'date':pd.date_range(row.startdate,row.enddate,freq='D'),'regnr':row.regnr,'contracttype':row.contracttype},列=['date','regnr','contracttype']),对于df.itertuples()中的行,忽略索引=True)
这里的一点优化是,我使用的itertuples()
比iterrows()
更快,因为它不进行任何类型检查。我粘贴了结果。如果你能指出我错在哪里,我将不胜感激。