You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效从Pandas的df2中筛选与df1指定列不匹配的行生成df3

问题描述

现有两个Pandas DataFrame df1 和 df2,定义如下:

import pandas as pd

df1 = pd.DataFrame({'num': [0, 2, 3, 4, 5, 7, 9],
                   'lower': ['a', 'b', 'd', 'c', 'f', 'f', 'j'],
                   'char': ['!', '(', '$', '+', '^', '^', ')'],
                   'upper': ['Z', 'Y', 'X', 'W', 'V', 'U', 'T']})

df2 = pd.DataFrame({'num': range(0,10),
                   'lower': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
                   'char': ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')'],
                   'upper': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']})

需要生成df3,要求包含df2中在num、lower、char三列上均不与df1任意行匹配的行,upper列不参与筛选但需保留在结果中。

原实现通过嵌套遍历itertuples()找出匹配行的索引,再筛选df2中不在该索引列表的行,代码如下:

commonEntries = []
for row in df1.itertuples():
    for line in df2.itertuples():
        if row[df1.columns.get_loc('num')+1] == line[df2.columns.get_loc('num')+1] and row[df1.columns.get_loc('lower')+1] == line[df2.columns.get_loc('lower')+1] and row[df1.columns.get_loc('char')+1] == line[df2.columns.get_loc('char')+1]:
            commonEntries.append(line[0])

goodGuys = [x for x in df2.index if x not in commonEntries]
goodEntries = df2.loc[goodGuys]

该方法在处理大数据量时效率极低,希望找到基于concat、join或merge等Pandas原生高效操作的解决方案。

高效解决方案

以下几种方法均利用Pandas的向量化操作替代循环,大幅提升处理效率:

方法1:使用merge结合indicator参数

通过合并两个DataFrame,利用indicator标记行的来源,筛选出仅存在于df2的行:

# 仅合并用于匹配的三列,保留df2的所有列
merged = df2.merge(df1[['num', 'lower', 'char']], 
                   on=['num', 'lower', 'char'], 
                   how='left', 
                   indicator=True)
# 筛选仅来自df2的行,去掉indicator列
df3 = merged[merged['_merge'] == 'left_only'].drop('_merge', axis=1)

方法2:使用isin结合元组

将df1的匹配列转换为元组集合,利用isin快速判断df2的行是否匹配:

# 提取df1中用于匹配的三列组成元组集合
match_set = set(df1[['num', 'lower', 'char']].itertuples(index=False))
# 筛选df2中不在匹配集合的行
df3 = df2[~df2[['num', 'lower', 'char']].itertuples(index=False).isin(match_set)]

方法3:使用concat结合drop_duplicates

将两个DataFrame的匹配列合并后去重,找出仅属于df2的行:

# 合并两个DataFrame的匹配列,添加来源标记
temp = pd.concat([
    df1[['num', 'lower', 'char']].assign(source='df1'),
    df2[['num', 'lower', 'char']].assign(source='df2')
])
# 找出仅在df2中出现的匹配组合
unique_to_df2 = temp.drop_duplicates(subset=['num', 'lower', 'char'], keep=False)
unique_to_df2 = unique_to_df2[unique_to_df2['source'] == 'df2']
# 从df2中筛选出符合条件的行
df3 = df2.merge(unique_to_df2[['num', 'lower', 'char']], on=['num', 'lower', 'char'])

内容的提问来源于stack exchange,提问作者BigHeadEd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:55:01