如何用Python匹配两个DataFrame首列并对比对应列值(去重)
解决DataFrame合并去重并对比列值的方法
问题核心
你需要合并两个列名完全一致的3列DataFrame,基于第一列(Fruit)匹配后,只保留首列匹配成功的第二、第三列数据,同时避免合并后出现重复行。之前用pd.merge的各类join方法虽然结果逻辑正确,但存在重复行问题。
解决方案
方法1:先去重再Inner Join(针对Fruit列有重复值的场景)
重复行的根源通常是原DataFrame中Fruit列存在重复项,合并时会生成笛卡尔积导致重复。先对两个表按Fruit去重,再做Inner Join就能解决:
# 对两个DataFrame按Fruit列去重,保留第一条匹配记录 dfA_unique = dfA.drop_duplicates(subset='Fruit', keep='first') dfB_unique = dfB.drop_duplicates(subset='Fruit', keep='first') # 用Inner Join合并,仅保留两个表中Fruit都存在的行 merged_table = pd.merge(dfA_unique, dfB_unique, on='Fruit', how='inner', suffixes=('_from dfA', '_from dfB')) # 按日期排序 merged_table = merged_table.sort_values('Date_from dfA') print(merged_table)
方法2:Concat + Groupby(保留同Fruit下多记录对比)
如果Fruit列有重复但你需要保留同Fruit对应的多组记录对比,可以用这种方式:
# 给两个DataFrame添加来源标识 dfA['source'] = 'dfA' dfB['source'] = 'dfB' # 合并两个表 combined = pd.concat([dfA, dfB]) # 按Fruit分组,整理出对应来源的Date和Price列 merged_table = combined.groupby('Fruit').agg( Date_from_dfA=('Date', lambda x: x[combined['source'] == 'dfA'].values[0] if any(combined['source'] == 'dfA') else None), Price_from_dfA=('Price', lambda x: x[combined['source'] == 'dfA'].values[0] if any(combined['source'] == 'dfA') else None), Date_from_dfB=('Date', lambda x: x[combined['source'] == 'dfB'].values[0] if any(combined['source'] == 'dfB') else None), Price_from_dfB=('Price', lambda x: x[combined['source'] == 'dfB'].values[0] if any(combined['source'] == 'dfB') else None) ).reset_index() # 过滤掉仅在单个表中存在的Fruit行 merged_table = merged_table.dropna(subset=['Date_from_dfA', 'Date_from_dfB']) # 按日期排序 merged_table = merged_table.sort_values('Date_from_dfA') print(merged_table)
关键说明
- Inner Join本身就会只保留两个表中
Fruit匹配成功的行,完全符合你"仅保留首列匹配成功数据"的需求。 - 先去重是解决重复行的核心操作,避免了合并时的笛卡尔积问题。
内容的提问来源于stack exchange,提问作者Est
相关产品推荐
相关产品推荐

