如何为长格式Pandas DataFrame补全年份内缺失的月份数据?
Pandas补全年度缺失月份记录并填充最近值
问题背景
现有长格式Pandas DataFrame,部分月份数据缺失。需要为每个国家的每一年补全1-12月的记录,缺失月份的total_points、rank等字段沿用最近已有月份的数值,同时rank_date需对应补全后的月份调整日期。
输入示例
country_full year month rank rank_date total_points Zimbabwe 2021 8 108 2021-08-12 1171.88 Zimbabwe 2021 10 108 2021-09-12 1171.88 Zimbabwe 2022 01 108 2022-01-12 1171.88 Germany 1994 01 10 1994-01-10 1171.88 Germany 1994 02 10 1994-02-09 1327.8 Germany 1994 04 10 1994-04-07 1459.9
期望输出示例
country_full year month rank rank_date total_points Zimbabwe 2021 8 108 2021-08-12 1171.88 Zimbabwe 2021 9 108 2021-08-12 1171.88 Zimbabwe 2021 10 108 2021-10-12 1171.88 Zimbabwe 2021 11 108 2021-11-12 1171.88 Zimbabwe 2021 12 108 2021-12-12 1171.88 Zimbabwe 2022 01 108 2022-01-12 1171.88 Germany 1994 01 10 1994-01-10 1171.88 Germany 1994 02 10 1994-02-09 1327.8 Germany 1994 03 10 1994-03-09 1459.9 Germany 1994 04 10 1994-04-07 1459.9
实现方法
以下是完整的代码实现步骤:
数据类型预处理
先将month转为整数,rank_date转为日期类型,确保后续操作正常:import pandas as pd # 定义原始数据(实际场景可替换为读取文件) df = pd.DataFrame({ 'country_full': ['Zimbabwe', 'Zimbabwe', 'Zimbabwe', 'Germany', 'Germany', 'Germany'], 'year': [2021, 2021, 2022, 1994, 1994, 1994], 'month': [8, 10, 1, 1, 2, 4], 'rank': [108, 108, 108, 10, 10, 10], 'rank_date': ['2021-08-12', '2021-09-12', '2022-01-12', '1994-01-10', '1994-02-09', '1994-04-07'], 'total_points': [1171.88, 1171.88, 1171.88, 1171.88, 1327.8, 1459.9] }) # 转换数据类型 df['month'] = df['month'].astype(int) df['rank_date'] = pd.to_datetime(df['rank_date'])生成完整月份序列
按country_full和year分组,为每组生成1到12月的完整月份记录:# 创建每组的完整月份索引 def create_full_months(group): year = group['year'].iloc[0] country = group['country_full'].iloc[0] full_months = pd.DataFrame({ 'country_full': [country]*12, 'year': [year]*12, 'month': range(1, 13) }) return full_months # 对原数据分组并生成完整序列,再合并为新表 full_df = df.groupby(['country_full', 'year']).apply(create_full_months).reset_index(drop=True)合并原数据并填充缺失值
将原数据与完整月份表合并,用向前填充(ffill)补全缺失的字段值,同时调整rank_date的月份:# 合并原数据和完整月份表 merged_df = pd.merge(full_df, df, on=['country_full', 'year', 'month'], how='left') # 按国家和年份分组,向前填充缺失的rank、total_points等字段 merged_df = merged_df.groupby(['country_full', 'year']).ffill() # 调整rank_date的月份为当前行的month值 merged_df['rank_date'] = merged_df.apply( lambda x: x['rank_date'].replace(month=x['month']), axis=1 ) # 按国家、年份、月份排序,恢复顺序 merged_df = merged_df.sort_values(['country_full', 'year', 'month']).reset_index(drop=True)结果整理
最终得到的merged_df就是补全后的数据集,与期望输出一致。
关键说明
ffill():按分组向前填充,确保缺失月份沿用最近已有月份的数值,完全匹配需求。rank_date调整:通过replace方法替换日期中的月份部分,保证日期与当前行的月份匹配。- 分组生成完整序列:确保每个国家的每一年都有1-12月的记录,不会遗漏任何月份。
内容的提问来源于stack exchange,提问作者Maxime
相关产品推荐
相关产品推荐

