跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何高效合并多个时间序列数据框:按ID对齐并分月填充收入列

本文介绍一种结合拼接(concat)与逐月左连接(merge)的策略,将多个同结构月度数据框合并为宽表,确保id对齐、历史字段保留、新增id自动补零。 本文介绍一种结合拼接(concat)与逐月左连接(merge)的策略,将多个同结构月度数据框合并为宽表,确保id对齐、历史字段保留、新增id自动补零。 在处理多期业务数据(如每月客户收入)时,常需将多个时间切片的数据框整合为统一宽表:以 id_number 为唯一主键,保留首次出现的非数值字段(如 company、type),并将各期 Income 值分别映射至 Income_1、Income_2、Income_3 等列,缺失则填 0。直接链式 merge 易导致字段覆盖或逻辑混乱,而先拼接后索引对齐是更稳健的方案。 核心思路分两步: 构建主键骨架 :拼接所有数据框(忽略 Income 列),按 id_number 去重,保留首次出现的 company 和 type; 逐期注入收入值 :对每个原始数据框,以 id_number 为索引提取 Income,再用 reindex() 对齐主键骨架,缺失位置自动填充 0。 以下是完整可执行代码:
import pandas as pd # 示例数据(3个不同月份) data_22_3 = {'id_number': ['A123', 'B456', 'C789'], 'company': ['Insurance1', 'Insurance2', 'Insurance3'], 'type': ['A', 'A', 'C'], 'Income': [100, 200, 300]} data_22_4 = {'id_number': ['A123', 'B456', 'D012'], 'company': ['Insurance1', 'Insurance2', 'Insurance1'], 'type': ['A', 'B', 'B'], 'Income': [150, 250, 400]} data_22_5 = {'id_number': ['A123', 'C789', 'E034'], 'company': ['Insurance1', 'Insurance3', 'Insurance5'], 'type': ['A', 'C', 'B'], 'Income': [180, 320, 500]} df_22_3 = pd.DataFrame(data_22_3) df_22_4 = pd.DataFrame(data_22_4) df_22_5 = pd.DataFrame(data_22_5) dfs = [df_22_3, df_22_4, df_22_5] # 步骤1:构建唯一ID骨架(保留首次出现的非Income字段) skeleton = ( pd.concat(dfs, ignore_index=True) .drop(columns='Income') .drop_duplicates(subset='id_number', keep='first') # 关键:keep='first' 确保取最早期的company/type .reset_index(drop=True) ) # 步骤2:逐期添加Income列(列名按顺序编号) for i, df in enumerate(dfs, start=1): skeleton[f'Income_{i}'] = ( df.set_index('id_number')['Income'] .reindex(skeleton['id_number'], fill_value=0) # 自动对齐+补零 .values # .values 避免索引对齐警告,更安全 ) # 可选:将Income_1重命名为Income以符合习惯(保持首列为Income) skeleton = skeleton.rename(columns={'Income_1': 'Income'}) print(skeleton)
输出结果:
id_number company type Income Income_2 Income_3 0 A123 Insurance1 A 100 150 180 1 B456 Insurance2 A 200 250 0 2 C789 Insurance3 C 300 0 320 3 D012 Insurance1 B 0 400 0 4 E034 Insurance5 B 0 0 500
关键注意事项: drop_duplicates(keep='first') 是保证 company/type 取最早期值的核心,若需最新期值可改为 'last'; reindex(..., fill_value=0) 比 map() 或 merge() 更简洁高效,避免产生 NaN 后再 fillna(0); 使用 .values 获取 NumPy 数组赋值,可规避 Pandas 版本升级中可能发生的索引对齐警告; 若数据量极大,建议将 dfs 中各 DataFrame 的 id_number 列设为 category 类型以提升 reindex 性能。 该方法逻辑清晰、扩展性强——只需将新月份数据追加到 dfs 列表,即可一键生成带 Income_4、Income_5 的宽表,适用于自动化月报流水线。

相关文章