对比两个DataFrame并筛选dfA中与dfB匹配/不匹配的行(含索引)
对比两个DataFrame并筛选dfA中与dfB匹配/不匹配的行(含索引)
嘿,我完全get到你的需求了——就是要把dfA里的每一行,不管列的顺序如何,只要整行的所有元素(作为一个整体)能在dfB里找到对应的行,就把它(带着dfA的索引)放到匹配列表;剩下那些在dfB里找不到的,就放到不匹配列表对吧?
咱们用Python的pandas来实现这个逻辑特别方便,思路是这样的:因为列顺序不影响匹配,所以我们可以把每一行的元素排序后转成元组,这样不管列怎么打乱,相同元素的行都会变成一模一样的元组,然后就可以快速对比了。
下面是具体的代码实现,我直接用你给的示例数据来演示:
import pandas as pd # 构造你给出的示例dfA data_a = { 'Column 1': ['Albuquerque', 'New York', 'Miami'], 'Column 2': ['NM', 'NY', 'FL'], 'Column 3': ['87101', '10009', '33101'] } dfA = pd.DataFrame(data_a) # 构造你给出的示例dfB data_b = { 'Column 1': ['NM', 'Atlanta', 'San Francisco', '10009'], 'Column 2': ['Albuquerque', 'GA', 'CA', 'NY'], 'Column 3': ['87101', '30033', '94016', 'New York'] } dfB = pd.DataFrame(data_b) # 先把dfB的所有行转换成排序后的元组,存成集合(集合的查找速度超快,数据量大的时候特别有用) dfB_matched_rows = set(tuple(sorted(row)) for _, row in dfB.iterrows()) # 初始化两个空列表,分别存匹配和不匹配的结果 matched_list = [] not_matched_list = [] # 遍历dfA的每一行,同时保留它的索引 for idx, row in dfA.iterrows(): # 把当前行也转换成排序后的元组 current_row_tuple = tuple(sorted(row)) # 检查是否在dfB的匹配集合里 if current_row_tuple in dfB_matched_rows: matched_list.append(f"Index {idx}: {row.tolist()}") else: not_matched_list.append(f"Index {idx}: {row.tolist()}") # 输出结果 print("✅ dfA中与dfB匹配的行:") for item in matched_list: print(item) print("\n❌ dfA中与dfB不匹配的行:") for item in not_matched_list: print(item)
运行这段代码后,你会得到这样的结果:
✅ dfA中与dfB匹配的行: Index 0: ['Albuquerque', 'NM', '87101'] Index 1: ['New York', 'NY', '10009'] ❌ dfA中与dfB不匹配的行: Index 2: ['Miami', 'FL', '33101']
小说明:
- 为什么用排序后的元组而不是集合?因为如果你的行里有重复元素(比如某一行有两个相同的值),用集合会自动去重,导致判断错误;而排序后的元组会保留所有元素的数量和顺序(排序后的统一顺序),能准确判断两行的元素是否完全一致。
- 把dfB的行存成集合是为了提高查找效率,尤其是当你的DataFrame有上万行的时候,集合的查找速度比逐行对比快太多了。
备注:内容来源于stack exchange,提问作者
相关产品推荐
相关产品推荐

