在尝试@Scott Boston 答案后,对于 1.8m 记录 df,第一行
df_out = pd.concat([pd.DataFrame(index=pd.date_range(df.iloc[i].stdt,df.iloc[i].enddt)).assign(**df.iloc[i,0:3]) for i in pd.np.arange(df.shape[0])]).reset_index()
1小时后仍在运行,并慢慢侵蚀记忆。所以我想我会尝试以下操作:
def reindex_by_date(df):
dates = pd.date_range(df.index.min(), df.index.max())
return df.reindex(dates)
def replace_last_0(group):
group.loc[max(group.index),'change']=0
return group
def ctidloop(partdf):
coid=partdf.cid.max()
cols=['cid', 'stdt', 'enddt']
partdf=partdf[cols]
partdf['jid']=partdf.index
partdf = pd.melt(partdf, id_vars=['ctid', 'jid'],var_name='change', value_name='newdate')
partdf['change'] = partdf['change'].replace({'stdt': 1, 'enddt': -1})
partdf.newdate=pd.DatetimeIndex(partdf['newdate'])
partdf=partdf.groupby(['ctid', 'newdate'],as_index=False)['change'].sum()
partdf=partdf.groupby('ctid').apply(replace_last_0).reset_index(drop=True)
partdf['cnt'] = partdf.groupby('ctid')['change'].cumsum()
partdf.index=partdf['newdate']
cols=['ctid', 'change', 'cnt', 'newdate']
partdf=partdf[cols]
partdf=partdf.groupby('ctid').apply(reindex_by_date).reset_index(0, drop=True)
partdf['newdate']=partdf.index
partdf['ctid']=partdf['ctid'].fillna(method='ffill')
partdf.cnt=partdf.cnt.fillna(method='ffill')
partdf.change=partdf.change.fillna(0)
partdf['cid']=coid
return partdf
gb=df.groupby('cid').apply(ctidloop)
此代码返回正确的结果:
%timeit gb=df.groupby('cid').apply(ctidloop)
1 loop, best of 3: 9.74 s per loop
解释:
基本上,melt
非常快。所以我想打破第一个groupby
分组并对其运行函数。所以这段代码采用df
, then groupsby
the cid
and apply
功能cidloop
.
In the cidloop
,按行发生以下情况:
1)抓住cid
以供将来使用。
2,3)建立核心partdf
通过分配所需的列进行处理
4)创建jid
从索引
5)运行pd.melt
它通过为每个数据框创建一行来展平数据框jid
for stdt
and enddt
。
6)创建一个'change'
将+1分配给的列stdt
,和 -1 到enddt
。
7) 使newdate
a datetimeindex
(只是更容易进一步处理)
8)对我们所拥有的进行分组ctid
and newdate
,总结change
9) 分组依据ctid
再次,用 0 替换最后一个值(这只是我需要的,而不是特定于问题的)
10) 创造cnt
按组按ctid
and cumsumming
改变
11) 生成新的索引newdate
12,13) 格式化列/名称
14) 另一个groupbyctid
但按高日期和低日期重新索引,填补空白。
15) 分配newdate
从新的reindex
价值观
16,17,18)填充各种值以填补空白(我需要此增强功能)
19) 分配cid
再次从顶部变量coid
聚集在1号线。
对每个都执行此操作cid
通过最后一行代码gb=df.groupby.....
感谢@Scott Boston 的尝试。当然它有效,但对我来说花了太长时间。
感谢@DSM 的解决方案HERE这是我解决方案的基础。