如何在Python中识别df1中元素存在于df2字符串中的行?
判断DataFrame元素是否作为子串存在于另一个DataFrame中
问题场景
有两个需要对比的DataFrame:df1中的是短字符串,df2中的字符串包含额外路径/后缀信息,需要判断df1的每个元素是否是df2中任意字符串的子串,并在df1新增一列标记结果。
示例数据
import pandas as pd df1 = pd.DataFrame(data = {'data1' : ['S10321Nr1.1', 'S10321Nr2.1', 'S10321Nr3.1', 'S10321Nr4.1']}) df2 = pd.DataFrame(data = {'data2' : ['HPAFII/Counts/S10323Nr1/HPAFII.S10323Nr1.1.genes.raw.csv.gz', 'HPAFII/Counts/S10323Nr1/HPAFII.S10323Nr1.2.genes.raw.csv.gz.md5sum', 'HPAFII/Counts/S10323Nr10/HPAFII.S10323Nr1.3.genes.raw.csv.gz', 'HPAFII/Counts/S10323Nr10/HPAFII.S10323Nr4.1.genes.raw.csv.gz.md5sum']})
预期结果
在df1中新增一列true-false,标记每个data1元素是否存在于df2的任意字符串中:
data1 true-false 0 S10321Nr1.1 True 1 S10321Nr2.1 False 2 S10321Nr3.1 False 3 S10321Nr4.1 True
之前尝试的问题分析
你之前的代码存在两个核心问题:
- 第一个方法中,
df2['data_name']是错误列名(应为df2['data2']),且遍历对象错误——你是用df2的元素去匹配整个df1,而非df1['data1']的单个元素;同时逻辑方向颠倒,应该检查df1的元素是否在df2的字符串中。 - 第二个方法中,
isin()是检查完全匹配,但df2的字符串包含额外信息,不可能和df1的短字符串完全相等,因此结果全为False,后续赋值逻辑也不成立。
可行解决方案
方法1:apply结合any遍历检查(直观易读)
直接对df1['data1']的每个元素,检查是否在df2['data2']的任意字符串中:
df1['true-false'] = df1['data1'].apply(lambda x: any(x in s for s in df2['data2']))
适合数据量较小的场景,逻辑清晰易懂。
方法2:正则表达式批量匹配(高效)
先将df1['data1']的元素拼接成正则表达式,一次性匹配df2的所有字符串,再统计匹配结果:
# 生成匹配所有df1元素的正则表达式 pattern = '|'.join(df1['data1']) # 提取df2中包含df1元素的内容并去重 matched_items = df2['data2'].str.extract(f'({pattern})', expand=False).dropna().unique() # 标记df1元素是否在匹配结果中 df1['true-false'] = df1['data1'].isin(matched_items)
减少循环次数,数据量大时比方法1更高效。
方法3:numpy向量化操作(性能最优)
利用numpy的广播特性,一次性完成所有元素的匹配检查:
import numpy as np # 转换为numpy数组 arr1 = df1['data1'].to_numpy() arr2 = df2['data2'].to_numpy() # 广播后检查每个arr1元素是否在arr2的任意字符串中 match_results = np.any(np.char.find(arr2[:, None], arr1) != -1, axis=0) # 赋值回df1 df1['true-false'] = match_results
完全向量化计算,适合超大规模数据场景。
验证结果
运行上述任意方法后,df1都会生成符合预期的标记列。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

