如何在Pandas中行向合并两个DataFrame并标记数据来源?
Pandas 实现指定规则的DataFrame行合并
需求说明
现有两个DataFrame:df1和df2,需按以下规则行向合并:
- 当行在两个DataFrame中同时存在(匹配
altshortname、Code、Type三个字段),保留df1的数据,并为该行的alt列赋值1; - 仅来自df1的行,
common列值为1; - 仅来自df2的行,
alt列值为1。
解决方案
方法一:外连接合并后处理列
利用merge外连接合并数据集,再通过列值填充调整得到目标结果,适合数据量较大的场景:
import pandas as pd # 定义df1(修正原数据语法错误) data1 = { 'commonshortname': ['SNX.US', '002400.CH', 'CDW.US', 'CEC.GR', '300002.CH'], 'altshortname': ['SNX.US', '002400.SHE', 'CDW.US', 'CEC.XETRA', '300002.SHE'], 'Code': ['SNX', '002400', 'CDW', 'CEC', '300002'], 'Type': ['Common Stock'] * 5, 'common': [1] * 5 } df1 = pd.DataFrame(data1) # 定义df2 data2 = { 'altshortname': ['SEDG.US', 'MHLD.US', 'CDW.US', 'POLA.US', 'PHASQ.US'], 'Code': ['SEDG', 'MHLD', 'CDW', 'POLA', 'PHASQ'], 'Type': ['Common Stock'] * 5, 'alt': [1] * 5 } df2 = pd.DataFrame(data2) # 按指定字段外连接合并 merged = pd.merge(df1, df2, on=['altshortname', 'Code', 'Type'], how='outer') # 调整列值:仅保留符合规则的标记,其余设为空 merged['common'] = merged['common'].fillna(pd.NA) merged['alt'] = merged['alt'].fillna(pd.NA) # 调整列顺序为需求格式 result = merged[['commonshortname', 'altshortname', 'Code', 'Type', 'common', 'alt']] print(result)
方法二:合并后分组处理
先合并所有行,再按匹配字段分组,对每组数据按规则筛选,逻辑更直观,便于自定义扩展:
import pandas as pd # 定义df1和df2(同方法一) data1 = { 'commonshortname': ['SNX.US', '002400.CH', 'CDW.US', 'CEC.GR', '300002.CH'], 'altshortname': ['SNX.US', '002400.SHE', 'CDW.US', 'CEC.XETRA', '300002.SHE'], 'Code': ['SNX', '002400', 'CDW', 'CEC', '300002'], 'Type': ['Common Stock'] * 5, 'common': [1] * 5 } df1 = pd.DataFrame(data1) data2 = { 'altshortname': ['SEDG.US', 'MHLD.US', 'CDW.US', 'POLA.US', 'PHASQ.US'], 'Code': ['SEDG', 'MHLD', 'CDW', 'POLA', 'PHASQ'], 'Type': ['Common Stock'] * 5, 'alt': [1] * 5 } df2 = pd.DataFrame(data2) # 给df2添加缺失的commonshortname列,保证列结构一致 df2['commonshortname'] = pd.NA # 合并所有行并重置索引 combined = pd.concat([df1, df2], ignore_index=True) # 定义分组处理函数 def process_group(group): has_df1 = group['common'].notna().any() has_df2 = group['alt'].notna().any() if has_df1 and has_df2: # 交集行:保留df1数据并设置alt=1 df1_row = group[group['common'] == 1].iloc[0].copy() df1_row['alt'] = 1 return pd.DataFrame([df1_row]) elif has_df1: # 仅df1的行:直接保留 return group[group['common'] == 1] else: # 仅df2的行:直接保留 return group[group['alt'] == 1] # 分组处理并清理索引 result = combined.groupby(['altshortname', 'Code', 'Type'], as_index=False).apply(process_group).reset_index(drop=True) print(result)
结果说明
两种方法均可生成符合需求的结果,可根据数据规模和扩展需求选择使用。
内容的提问来源于stack exchange,提问作者anarchy
相关产品推荐
相关产品推荐

