Pandas补全DataFrame分组缺失月份行 新增行指定列填0其余列保留原值
pandas按分组补全缺失月份行方案
需求说明
基于pandas的DataFrame数据集存在月份缺失问题,补全规则如下:
- 补全范围为数据集全局最早月份到最晚月份的所有连续月份,时间范围需支持动态适配
- 新增的缺失月份行中
Random列值填充为0 - 其余固定属性列(如
Home、Mat)保留对应分组的原有属性值 - 补全后重新生成依赖日期字段的
id列
原有尝试的问题
之前的实现代码存在三个核心问题:
- 列名拼写错误,原数据列名为大写开头的
Home,代码中写为小写home - 将依赖日期生成的
id列放入索引做长宽表转换,id本身是派生字段,缺失月份无对应id值,会导致补全逻辑错乱 - 未区分固定属性列和值列,所有列参与unstack/stack操作容易引入额外缺失值
可直接运行的实现代码
初始数据构造(和提问中逻辑一致):
import pandas as pd import numpy as np df = pd.DataFrame(np.random.randint(0,30,size=10), columns=["Random"], index=pd.date_range("20180101", periods=10)) df = df.reset_index() df['Date']=['2018-01-01', '2018-02-01', '2018-04-01', '2018-05-01', '2018-07-01', '2018-02-01', '2018-04-01', '2018-03-01', '2018-04-01', '2018-08-01'] df['Random']=[44,65,78,32,55,61,78,85,91,56] df['Home'] = ['843','843','843','843','843', '976','976','976','976','976',] df['Mat'] = ['327837', '327837', '327837','327837','327837', 'eid78', 'eid78','eid78','eid78','eid78',] df.loc[5, 'index'] = pd.to_datetime('2018-01-02') df['id'] = df.Mat.astype(str) + '_' + df.Home.astype(str) + '_' + df.Date.astype(str) df['Date']= pd.to_datetime(df['Date']) df['Date'] = df['Date'].dt.to_period('m') df.drop('index', axis=1, inplace=True)
缺失月份补全逻辑:
# 动态提取全局时间范围,生成连续月份序列 min_month = df['Date'].min() max_month = df['Date'].max() full_month_seq = pd.period_range(start=min_month, end=max_month, freq='M') # 提取所有唯一的固定属性分组 attr_groups = df[['Home', 'Mat']].drop_duplicates() # 生成所有分组+所有月份的全量索引框架 full_frame = pd.MultiIndex.from_product( [attr_groups['Home'], attr_groups['Mat'], full_month_seq], names=['Home', 'Mat', 'Date'] ).to_frame(index=False) # 左连接原数据,填充缺失的Random值为0 result = full_frame.merge(df, on=['Home', 'Mat', 'Date'], how='left') result['Random'] = result['Random'].fillna(0).astype(int) # 重新生成派生id列 result['id'] = result['Mat'].astype(str) + '_' + result['Home'].astype(str) + '_' + result['Date'].astype(str)
实现逻辑说明
- 时间范围直接从数据集动态取最小、最大月份,无需硬编码时间值,适配任意时间跨度的数据集
- 固定属性分组通过去重提取,后续如果新增其他固定属性列,只需要把列名加到分组提取的列表中即可,扩展性强
- 采用左连接合并原数据,原有已存在的行数据不会被改动,仅补全缺失的月份行
- 最后统一重新生成
id列,避免新增行出现id为空的问题,最终输出结果和预期完全一致
内容的提问来源于stack exchange,提问作者ash1
相关产品推荐
相关产品推荐

