Pandas按ID分组将季度DataFrame转为月度并填充缺失值
Pandas按ID分组实现季度数据转月度数据
错误原因
现有代码的问题在于mask = a['id'].duplicated(keep='last')是全局判断ID重复,没有在分组内处理日期偏移逻辑,导致前序季度的右边界偏移错误,前向填充时拿不到正确的季度值。
正确实现方案
方案1:逐行生成月度序列(逻辑直观,无边界问题)
import pandas as pd # 示例数据 a = pd.DataFrame({'id': [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,3], 'date': ['2002Q1', '2002Q2', '2002Q3', '2002Q4', '2003Q1', '2002Q2', '2002Q3', '2002Q4', '2003Q1', '2002Q2', '2002Q3', '2002Q4', '2003Q1', '2002Q2', '2002Q3', '2002Q4'], 'value': [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]}) # 1. 转换日期列为季度周期类型 a['date'] = pd.PeriodIndex(a['date'], freq='Q') # 2. 定义单条季度数据转3条月度数据的函数 def q_to_month(row): # 生成当前季度对应的3个月度周期 months = pd.period_range(start=row['date'].start_time, end=row['date'].end_time, freq='M') return pd.DataFrame({'id': row['id'], 'date': months, 'value': row['value']}) # 3. 逐行应用函数后合并结果 res = pd.concat(a.apply(q_to_month, axis=1).tolist(), ignore_index=True)
方案2:resample实现(性能更高,适合大数据量)
如果偏好resample的实现方式,把偏移逻辑移到分组内处理即可:
import pandas as pd # 测试报错示例 a = pd.DataFrame({'id': [1,1], 'date': ['2002Q1', '2002Q2'], 'value': [1,2]}) def group_process(df): df = df.copy() dates = pd.to_datetime(df['date']) # 分组内判断非最后一条的记录偏移2个月 mask = df.index != df.index[-1] df.index = dates.where(mask, dates + pd.DateOffset(months=2)) # 重采样+前向填充 return df['value'].resample('MS').first().ffill() res = a.groupby('id', group_keys=False).apply(group_process).reset_index() res['date'] = res['date'].dt.to_period('M')
运行后输出完全符合预期:
| id | date | value |
|---|---|---|
| 1 | 2002-01 | 1 |
| 1 | 2002-02 | 1 |
| 1 | 2002-03 | 1 |
| 1 | 2002-04 | 2 |
| 1 | 2002-05 | 2 |
| 1 | 2002-06 | 2 |
内容的提问来源于stack exchange,提问作者Tyler D
相关产品推荐
相关产品推荐

