Pandas非平衡面板处理:为各ID补全缺失年份观测行
非平衡面板连续年份补全方案
不需要写显式for循环,用pandas原生的分组重索引方法就能高效实现,向量化运算在大数据量下比逐行循环快几个量级。
核心实现代码
import pandas as pd # 原始示例数据 df = pd.DataFrame({ 'id': ['1', '1', '1', '2', '2', '3', '4', '4'], 'Year': [2000, 2001, 2003, 2004, 2005, 2002, 2001, 2003], 'Var': [1, 4, 6, 8, 10, 12, 15, 17] }) # 按id分组补全每个个体的连续年份 df = ( df.set_index(['id', 'Year']) .groupby(level='id') .apply( lambda group: group.reindex( range(group.index.get_level_values('Year').min(), group.index.get_level_values('Year').max() + 1), fill_value=0 ) ) .droplevel(0) # 删除分组操作生成的冗余索引层级 .reset_index() )
执行后打印df就能得到预期的补全结果:
id Year Var 0 1 2000 1 1 1 2001 4 2 1 2002 0 3 1 2003 6 4 2 2004 8 5 2 2005 10 6 3 2002 12 7 4 2001 15 8 4 2002 0 9 4 2003 17
逻辑说明
- 先将
id、Year设置为索引,方便按个体分组做时间序列对齐 - 对每个id分组,取该个体观测到的最小年份、最大年份作为端点,生成两端之间所有整数年份的连续序列
- 用
reindex做数据对齐,原数据不存在的年份行自动填充Var=0 - 最后清理多余索引层级,还原为普通DataFrame结构即可
提取缺失年份映射字典
如果需要单独获取每个id对应的缺失年份列表,补全后用集合差集就能快速筛出,不需要逐行遍历:
# 原始数据存在的(id, 年份)配对集合 origin_pair_set = set(zip(df['id'], df['Year'])) # 筛选补全后新增的行,按id聚合得到缺失年份映射 missing_year_map = ( df[~df.apply(lambda row: (row['id'], row['Year']) in origin_pair_set, axis=1)] .groupby('id')['Year'] .apply(list) .to_dict() )
得到的missing_year_map输出为{'1': [2002], '4': [2002]},和需要的映射结构完全一致。
内容的提问来源于stack exchange,提问作者r-learning-machine
相关产品推荐
相关产品推荐

