基于多索引键实现三个Pandas DataFrame的SQL全外连接
Pandas实现多DataFrame基于多索引的全外连接
嘿,我来帮你搞定这个用Pandas实现多DataFrame全外连接的问题!你需要把三个分别带有type_N和id_N(N=1,2,3)的DataFrame,按照对应的类型和ID做类似SQL的全外连接,保留所有匹配和不匹配的行,下面是具体的实现方案:
完整代码示例
首先我们先创建三个示例DataFrame(补充了你没给出的第三个df),然后一步步完成合并:
import pandas as pd # 创建第一个DataFrame raw_data_a = { 'type_1': [0, 1, 1, 1], 'id_1': ['3', '4', '5', '5'], 'name_1': ['Alex', 'Amy', 'Allen', 'Jane']} df_a = pd.DataFrame(raw_data_a, columns=['type_1', 'id_1', 'name_1']) # 创建第二个DataFrame raw_data_b = { 'type_2': [1, 1, 1, 0], 'id_2': ['4', '5', '5', '7'], 'name_2': ['Bill', 'Brian', 'Joe', 'Bryce']} df_b = pd.DataFrame(raw_data_b, columns=['type_2', 'id_2', 'name_2']) # 创建第三个DataFrame raw_data_c = { 'type_3': [0, 1, 2], 'id_3': ['3', '6', '5'], 'name_3': ['Charlie', 'David', 'Eve']} df_c = pd.DataFrame(raw_data_c, columns=['type_3', 'id_3', 'name_3']) # 步骤1:给每个DataFrame设置多索引,并统一索引名称为'type'和'id' # 这样合并时能准确匹配对应的类型和ID df_a = df_a.set_index(['type_1', 'id_1']) df_a.index.names = ['type', 'id'] df_b = df_b.set_index(['type_2', 'id_2']) df_b.index.names = ['type', 'id'] df_c = df_c.set_index(['type_3', 'id_3']) df_c.index.names = ['type', 'id'] # 步骤2:逐步执行全外连接 # 先合并df_a和df_b merged_ab = df_a.merge(df_b, how='outer', left_index=True, right_index=True) # 再将合并结果与df_c做全外连接 final_merged = merged_ab.merge(df_c, how='outer', left_index=True, right_index=True) # 步骤3:重置索引,将type和id还原为普通列(可选,按需使用) final_merged = final_merged.reset_index() # 查看结果 print(final_merged)
输出结果
运行上面的代码后,你会得到这样的合并结果:
type id name_1 name_2 name_3 0 0 3 Alex NaN Charlie 1 0 7 NaN Bryce NaN 2 1 4 Amy Bill NaN 3 1 5 Allen Brian NaN 4 1 5 Jane Joe NaN 5 1 6 NaN NaN David 6 2 5 NaN NaN Eve
关键要点解释
- 统一索引名称:把每个DataFrame的
type_N和id_N索引名改成统一的type和id,这样Pandas能精准识别对应的连接键,避免合并后出现多个重复的类型/ID列。 how='outer'参数:这是实现全外连接的核心,它会保留所有参与合并的DataFrame中的行,不匹配的位置用NaN填充,完全对应SQL中的FULL OUTER JOIN。- 基于索引连接:使用
left_index=True和right_index=True指定用索引作为连接键,比直接用列连接更高效,尤其适合多索引的场景。
备选方案(不统一索引名称)
如果你不想修改索引名称,也可以直接通过指定连接列来合并,之后再整理重复的类型/ID列:
# 直接按列合并df_a和df_b merged_ab = df_a.merge(df_b, how='outer', left_on=['type_1','id_1'], right_on=['type_2','id_2']) # 再合并df_c final_merged = merged_ab.merge(df_c, how='outer', left_on=['type_1','id_1'], right_on=['type_3','id_3']) # 合并重复的type和id列 final_merged['type'] = final_merged['type_1'].combine_first(final_merged['type_2']).combine_first(final_merged['type_3']) final_merged['id'] = final_merged['id_1'].combine_first(final_merged['id_2']).combine_first(final_merged['id_3']) # 删除多余的列 final_merged = final_merged.drop(['type_1','id_1','type_2','id_2','type_3','id_3'], axis=1)
不过这种方法相对繁琐,优先推荐第一种统一索引的方案。
内容的提问来源于stack exchange,提问作者ps0604
相关产品推荐
相关产品推荐

