Pandas:为每个分组补充缺失的日历周行
Pandas数据处理:按ID补全日历周行
现有一个包含4列的DataFrame,需按ID分组,为每个分组补充缺失的日历周(Calendar Week)行,使每个分组拥有3个日历周。新增行需保留对应分组的ID值,Price和Attribute列填充NaN值。
示例代码
import pandas as pd import numpy as np input = {'ID':['ITEM1', 'ITEM2', 'ITEM1', 'ITEM4', 'ITEM2', 'ITEM3', 'ITEM4', 'ITEM4'], 'Price':['11', '12', '11', '14', '12', '13', '14', '14' ], 'Attribute': ['A', 'B', 'A', 'D', 'B', 'C', 'D', 'D' ], 'Calendar Week':['1', '2', '2', '1', '3', '1', '3', '2'] } df = pd.DataFrame(input) df = df.sort_values(['ID', 'Calendar Week'], ascending = True).reset_index().drop(columns = 'index')
当前DataFrame内容
| ID | Price | Attribute | Calendar Week |
|---|---|---|---|
| ITEM1 | 11 | A | 1 |
| ITEM1 | 11 | A | 2 |
| ITEM2 | 12 | B | 2 |
| ITEM2 | 12 | B | 3 |
| ITEM3 | 13 | C | 1 |
| ITEM4 | 14 | D | 1 |
| ITEM4 | 14 | D | 2 |
| ITEM4 | 14 | D | 3 |
预期输出
| ID | Price | Attribute | Calendar Week |
|---|---|---|---|
| ITEM1 | 11 | A | 1 |
| ITEM1 | 11 | A | 2 |
| ITEM1 | NaN | NaN | 3 |
| ITEM2 | NaN | NaN | 1 |
| ITEM2 | 12 | B | 2 |
| ITEM2 | 12 | B | 3 |
| ITEM3 | 13 | C | 1 |
| ITEM3 | NaN | NaN | 2 |
| ITEM3 | NaN | NaN | 3 |
| ITEM4 | 14 | D | 1 |
| ITEM4 | 14 | D | 2 |
| ITEM4 | 14 | D | 3 |
解决方案
方法1:分组后重新索引
通过分组为每个ID生成完整的日历周序列,再重新索引补全缺失行:
# 转换Calendar Week为整数类型,避免字符串匹配问题 df['Calendar Week'] = df['Calendar Week'].astype(int) # 定义需要补全的完整日历周范围 full_weeks = [1, 2, 3] # 分组处理:为每个ID补全缺失的周行 result = df.groupby('ID').apply( lambda group: group.set_index('Calendar Week').reindex(full_weeks).reset_index() ).droplevel(0).reset_index(drop=True) # 补全ID列(分组后ID会丢失,用向前填充恢复) result['ID'] = result.groupby('ID')['ID'].ffill() print(result)
方法2:生成笛卡尔积后合并
先生成所有ID和日历周的组合,再和原DataFrame合并自动填充NaN:
# 转换Calendar Week为整数类型 df['Calendar Week'] = df['Calendar Week'].astype(int) # 生成所有ID与完整日历周的笛卡尔积 all_combinations = pd.MultiIndex.from_product( [df['ID'].unique(), [1,2,3]], names=['ID', 'Calendar Week'] ).to_frame(index=False) # 合并原数据,缺失行自动填充NaN result = pd.merge(all_combinations, df, on=['ID', 'Calendar Week'], how='left') # 按ID和日历周排序 result = result.sort_values(['ID', 'Calendar Week']).reset_index(drop=True) print(result)
内容的提问来源于stack exchange,提问作者Hapzek
相关产品推荐
相关产品推荐

