如何用Pandas的groupby与reindex将事件型数据转换为时间序列?
将事件型薪资数据转换为规则时间序列的最优方案
我们需要把不规则间隔的事件型薪资数据转换为多时间序列,数据包含日期、员工姓名和变更后的薪资。目前已经通过循环+groupby/reindex/ffill实现了转换,但想找更简洁的标准方案。尝试直接调用df_events.groupby('employee')['salary'].reindex(time_series_index)时遇到错误:AttributeError: 'SeriesGroupBy' object has no attribute 'reindex',求最优实现方式。
原始事件数据
employee salary date 2000-01-01 anna 4500 2003-01-01 oli 5000 2010-01-01 anna 6500 2012-01-01 lena 5000 2013-01-01 oli 7000 2016-01-01 lena 6500 2017-01-09 joe 5000 2018-01-09 peter 5000 2019-01-09 joe 5500 2019-01-31 lena 0 2020-01-01 anna 8500 2020-01-09 peter 5500 2021-01-09 joe 6000 2022-02-28 peter 0
现有可行代码
time_series_index = pd.date_range(df_events.index.min(), df_events.index.max()) df_time_series = pd.DataFrame() for name, group in df_events.groupby('employee'): time_series = group['salary'].reindex(time_series_index) time_series = time_series.ffill().fillna(0) df_time_series[name] = time_series print(df_time_series)
目标转换结果示例
anna joe lena oli peter 2000-01-01 4500.0 0.0 0.0 0.0 0.0 2000-01-02 4500.0 0.0 0.0 0.0 0.0 ... ... ... ... ... ... 2022-02-28 8500.0 6000.0 0.0 7000.0 0.0
最优实现方案
方案1:宽表重塑+全局重索引(推荐,性能最优)
通过unstack将长格式数据转为宽表,再一次性完成重索引和填充,完全避免循环:
# 生成完整时间索引 time_series_index = pd.date_range(df_events.index.min(), df_events.index.max()) df_time_series = ( df_events['salary'] .unstack('employee') # 转成员工为列、日期为索引的宽表 .reindex(time_series_index) # 对齐到完整时间序列 .ffill() # 前向填充,延续上一次薪资值 .fillna(0) # 填充员工入职前的初始缺失值为0 ) print(df_time_series)
方案2:GroupBy+Apply(兼容原思路)
如果坚持用分组逻辑,可通过groupby.apply调用reindex,本质是封装了循环,但代码更简洁:
time_series_index = pd.date_range(df_events.index.min(), df_events.index.max()) df_time_series = ( df_events.groupby('employee')['salary'] .apply(lambda x: x.reindex(time_series_index).ffill().fillna(0)) .unstack('employee') # 转成宽表格式 )
内容的提问来源于stack exchange,提问作者barium
相关产品推荐
相关产品推荐

