
本文详解如何在 pandas 中合并多个结构不一致的 dataframe 时,自动保留目标列(如 usd/eur/gbp),对缺失列填充 nan,避免因列缺失导致数据丢失或报错。
本文详解如何在 pandas 中合并多个结构不一致的 dataframe 时,自动保留目标列(如 usd/eur/gbp),对缺失列填充 nan,避免因列缺失导致数据丢失或报错。
在实际数据分析中,我们常需将一个“模板 DataFrame”(含预定义列但值为空)与多个来源各异的“数据 DataFrame”进行整合——这些数据源可能只包含部分目标货币列(如仅有 USD 和 EUR,缺少 GBP)。若直接使用 pd.merge() 默认左连接或内连接,不仅无法补全缺失列,还可能导致行对齐错误或列意外丢弃。
正确解法并非依赖传统基于键的合并,而是采用 pd.concat() 配合 reindex() 或 DataFrame.combine_first() 等更灵活的对齐策略。但根据问题本质(模板驱动、列名已知、需严格保列),最简洁、健壮且语义清晰的方式是:以模板 DataFrame 为基准,通过 reindex() 强制对齐列,并用 combine_first() 实现安全覆盖。
✅ 推荐方案:reindex() + combine_first()
该方法确保:
- 目标列(USD/EUR/GBP)始终存在;
- 数据源中未提供的列自动填充 NaN;
- 相同 group 行按索引对齐,避免错位;
- 支持任意数量、任意子集的数据源。
import pandas as pd
import numpy as np
# 步骤1:构建模板 DataFrame(含 group 列 + 所有目标货币列)
template = pd.DataFrame({
'group': ['A', 'B', 'C'],
'USD': [np.nan, np.nan, np.nan],
'EUR': [np.nan, np.nan, np.nan],
'GBP': [np.nan, np.nan, np.nan]
}).set_index('group') # 设 group 为索引,便于对齐
# 步骤2:准备不同结构的数据源(均以 group 为索引)
data_1 = pd.DataFrame({
'group': ['A', 'B', 'C'],
'USD': [np.nan, 0.04, 0.02],
'EUR': [0.05, np.nan, np.nan],
'GBP': [0.04, 0.03, 0.01]
}).set_index('group')
data_2 = pd.DataFrame({
'group': ['A', 'B', 'C'],
'USD': [np.nan, 0.04, 0.02],
'GBP': [0.04, 0.03, 0.01]
}).set_index('group')
# 步骤3:对数据源强制重索引至模板列,并与模板合并
def fill_template(template_df, data_df):
# 确保 data_df 包含 template_df 的全部列(缺失列自动补 NaN)
aligned = data_df.reindex(columns=template_df.columns)
# 使用 combine_first:template 中的 NaN 被 data 中的非空值覆盖,其余保持 NaN
return template_df.combine_first(aligned)
result_1 = fill_template(template, data_1).reset_index()
result_2 = fill_template(template, data_2).reset_index()
print("使用 data_1(含 USD/EUR/GBP):")
print(result_1)
print("\n使用 data_2(仅含 USD/GBP):")
print(result_2)输出结果:
使用 data_1(含 USD/EUR/GBP): group USD EUR GBP 0 A NaN 0.05 0.04 1 B 0.04 NaN 0.03 2 C 0.02 NaN 0.01 使用 data_2(仅含 USD/GBP): group USD EUR GBP 0 A NaN NaN 0.04 1 B 0.04 NaN 0.03 2 C 0.02 NaN 0.01
⚠️ 注意事项:
- combine_first() 是按位置(索引+列)逐元素取非空优先,因此务必确保 group 已设为索引或两表索引完全一致;
- 若原始数据未排序或索引不匹配,请先调用 .sort_index();
- 不推荐仅用 merge(how='outer')(如原答案所提),因其会生成笛卡尔积式冗余行,且无法保证列完整性(例如 df_value_base.merge(df_value_2) 因无共同列会报错);
- 若需批量处理多个数据源,可将 data_dfs 列表传入循环,连续调用 combine_first() 即可实现多源叠加。
此方案兼具可读性、鲁棒性与扩展性,是 Pandas 中处理“模板填充型合并”的标准实践。










