如何用Pandas匹配两个DataFrame字符串并提取匹配行至新DataFrame
嘿,我来帮你搞定这个需求!你的目标是从df1里找出那些任意单元格内容出现在df2任意位置的行,然后把这些行整理成规范的新DataFrame对吧?先看看你现有代码里的几个小问题,再给你两个高效靠谱的实现方案。
先说说原代码里的问题(帮你避坑)
- 变量逻辑混乱:比如
string = df1.iloc[[z]]里的z是df2的行索引,明显应该取df1的当前行;而且收集行的方式会导致最终的Registered是一堆小DataFrame的列表,没法直接转成规范的df3。 - 循环嵌套冗余:多层for+while循环完全没必要,而且
found = repr(key) in repr(data)里的key和data都没定义,直接运行会报错。 - 大小写处理无效:
repr(cell).lower()没有赋值给变量,等于白做,没法实现大小写不敏感的匹配。
方案一:用Pandas向量化操作(高效首选)
Pandas最擅长的就是向量化处理,比手动循环快N倍,尤其适合大数据量的情况。核心思路是先把df2的所有内容转成一个快速查找的集合,再批量检查df1的每一行:
import pandas as pd # 先读取你的两个CSV文件 df1 = pd.read_csv("你的第一个CSV文件路径.csv") df2 = pd.read_csv("你的第二个CSV文件路径.csv") # 把df2的所有非空值转成小写集合(集合查找是O(1)速度) df2_all_values = set(df2.stack().dropna().str.lower()) # 生成筛选掩码:检查df1每一行是否有任意单元格(转小写)在df2的集合里 match_mask = df1.apply( lambda row: row.astype(str).str.lower().isin(df2_all_values).any(), axis=1 # axis=1表示按行处理 ) # 筛选出匹配的行,重置索引让格式更规范 df3 = df1[match_mask].reset_index(drop=True)
关键细节说明:
stack()把df2转换成一维序列,方便一次性提取所有值dropna()跳过空值,避免把空单元格误判为匹配项str.lower()统一大小写,实现不区分大小写的匹配(如果需要严格区分,去掉这个就行)reset_index(drop=True)让df3的索引从0开始,格式更整洁
方案二:手动循环实现(适合理解逻辑)
如果你想更直观地理解每一步的逻辑,这个修正后的循环版本更清晰:
import pandas as pd df1 = pd.read_csv("你的第一个CSV文件路径.csv") df2 = pd.read_csv("你的第二个CSV文件路径.csv") # 先预处理df2的所有值,存到小写集合里(避免每次循环都遍历df2,提升效率) df2_values = set() for column in df2.columns: for value in df2[column].dropna(): df2_values.add(str(value).lower()) # 用来存储匹配到的行 matched_rows = [] # 遍历df1的每一行 for _, row in df1.iterrows(): # 检查当前行的每个单元格 for cell in row: cell_str = str(cell).lower() if cell_str in df2_values: # 找到匹配,把整行加入列表,然后跳出当前行的检查 matched_rows.append(row) break # 把列表转成规范的DataFrame,重置索引 df3 = pd.DataFrame(matched_rows).reset_index(drop=True)
最后验证一下
运行完代码后,你可以用df3.head()或者print(df3)查看结果,确保是你想要的格式:所有从df1里筛选出来的、任意单元格内容在df2里出现过的行,索引连续,结构和df1一致。
内容的提问来源于stack exchange,提问作者Nataliya Solhan
相关产品推荐
相关产品推荐

