Pandas如何按日期扩展DataFrame并为新增行填充NaN或0
补全个体日级观测数据中的缺失日期行
我有一个按个体划分的日级观测DataFrame,不同个体的观测日期不统一。需要在每个个体已有观测日期的间隔中插入缺失日期的行,将Count字段设为0(或NaN),其余协变量(Cov1、Cov2、Cov3等)以及StartDate、EndDate保持该个体的原值。
原始数据
ID date StartDate EndDate Count Cov1 Cov2 Cov3 A 05/05/2005 04/04/05 06/06/2006 3 1 F 1 A 06/05/2005 04/04/05 06/06/2006 5 1 F 1 A 07/05/2005 04/04/05 06/06/2006 2 1 F 1 A 10/05/2005 04/04/05 06/06/2006 7 1 F 1 B 05/05/2005 04/04/05 06/06/2006 6 0 M 2 B 07/05/2005 04/04/05 06/06/2006 1 0 M 2 C 01/05/2005 04/04/05 06/06/2006 3 1 F 1 C 03/05/2005 04/04/05 06/06/2006 7 1 F 1
期望输出
ID date StartDate EndDate Count Cov1 Cov2 Cov3 A 05/05/2005 04/04/05 06/06/2006 3 1 F 1 A 06/05/2005 04/04/05 06/06/2006 5 1 F 1 A 07/05/2005 04/04/05 06/06/2006 2 1 F 1 A 08/05/2005 04/04/05 06/06/2006 0 1 F 1 A 09/05/2005 04/04/05 06/06/2006 0 1 F 1 A 10/05/2005 04/04/05 06/06/2006 7 1 F 1 B 05/05/2005 04/04/05 06/06/2006 6 0 M 2 B 06/05/2005 04/04/05 06/06/2006 0 0 M 2 B 07/05/2005 04/04/05 06/06/2006 1 0 M 2 C 01/05/2005 04/04/05 06/06/2006 3 1 F 1 C 02/05/2005 04/04/05 06/06/2006 0 1 F 1 C 03/05/2005 04/04/05 06/06/2006 7 1 F 1
解决方案(Python Pandas)
- 转换日期格式:将
date、StartDate、EndDate列转为datetime类型,便于生成连续日期序列。 - 分组补全日期:按ID分组,生成每组已有日期的完整连续序列,重新索引后合并原数据。
- 填充固定字段:新增行的
Count设为0(或NaN),其余字段保留对应ID的原值。
代码实现
import pandas as pd # 加载原始数据(示例) df = pd.DataFrame({ 'ID': ['A', 'A', 'A', 'A', 'B', 'B', 'C', 'C'], 'date': ['05/05/2005', '06/05/2005', '07/05/2005', '10/05/2005', '05/05/2005', '07/05/2005', '01/05/2005', '03/05/2005'], 'StartDate': ['04/04/05']*8, 'EndDate': ['06/06/2006']*8, 'Count': [3,5,2,7,6,1,3,7], 'Cov1': [1,1,1,1,0,0,1,1], 'Cov2': ['F','F','F','F','M','M','F','F'], 'Cov3': [1,1,1,1,2,2,1,1] }) # 转换日期列格式 df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y') df['StartDate'] = pd.to_datetime(df['StartDate'], format='%d/%m/%y') df['EndDate'] = pd.to_datetime(df['EndDate'], format='%d/%m/%Y') # 定义分组补全函数 def fill_missing_dates(group): # 生成该ID的连续日期范围 date_range = pd.date_range(start=group['date'].min(), end=group['date'].max(), freq='D') # 重新索引到完整日期 group = group.set_index('date').reindex(date_range).reset_index() # 填充ID及固定字段(前后填充保证值一致) group['ID'] = group['ID'].ffill().bfill() group[['StartDate', 'EndDate', 'Cov1', 'Cov2', 'Cov3']] = group[['StartDate', 'EndDate', 'Cov1', 'Cov2', 'Cov3']].ffill().bfill() # 填充Count为0,如需NaN可替换为pd.NA group['Count'] = group['Count'].fillna(0) # 重命名索引列为date group = group.rename(columns={'index': 'date'}) return group # 按ID分组应用函数 result_df = df.groupby('ID').apply(fill_missing_dates).reset_index(drop=True) # 转换回原始日期显示格式(可选) result_df['date'] = result_df['date'].dt.strftime('%d/%m/%Y') result_df['StartDate'] = result_df['StartDate'].dt.strftime('%d/%m/%y') result_df['EndDate'] = result_df['EndDate'].dt.strftime('%d/%m/%Y') # 输出结果 print(result_df.to_string(index=False))
内容的提问来源于stack exchange,提问作者nj95
相关产品推荐
相关产品推荐

