如何用Regex优化避免嵌套循环,实现数据集L1/L2标签匹配?
优化关键词规则文本分类的性能(解决嵌套循环耗时问题)
核心问题分析
原代码的性能瓶颈集中在三点:
- 双重嵌套循环遍历文本与规则,时间复杂度为O(N*M)(N为文本行数,M为规则数),大数据量下会指数级增加耗时
- 每次匹配成功后调用
pd.concat和drop_duplicates,这两个是高开销的IO密集型操作,频繁调用会大幅拖慢速度 - 重复编译正则表达式,每次匹配都重新生成正则,没有复用编译后的对象
优化方案
通过预编译正则、批量收集结果、高效匹配逻辑三个核心手段,将运行时间从小时级压缩到分钟/秒级:
- 预编译所有规则的正则表达式:提前把每个关键词规则转换成编译后的正则对象,避免重复编译的开销
- 用列表收集匹配结果:先将所有匹配成功的行数据存入列表,最后一次性转换为DataFrame,替代频繁的
pd.concat - 高效多关键词匹配:用正则正向预查实现"同时包含两个关键词"的匹配,一次搜索完成判断,比两次
re.search更高效
优化后代码
import pandas as pd import re # 读取数据集 tag_l1l2 = pd.read_excel('/content/L1L2 Tagging.xlsx') mydata = pd.read_excel('/content/mydata.xlsx') # 预处理规则:生成编译后的正则表达式与对应分类信息 rule_collection = [] for _, rule_row in tag_l1l2.iterrows(): keyword1 = str(rule_row['Keyword1']).strip() keyword2 = rule_row['Keyword2'] # 构建正则模式 if pd.isna(keyword2): # 单关键词规则:匹配单词边界,忽略大小写 regex_pattern = re.compile(r'\b' + re.escape(keyword1) + r'\b', flags=re.IGNORECASE) else: keyword2 = str(keyword2).strip() # 双关键词规则:用正向预查确保两个关键词同时存在 regex_pattern = re.compile( r'(?=.*\b' + re.escape(keyword1) + r'\b)(?=.*\b' + re.escape(keyword2) + r'\b)', flags=re.IGNORECASE ) rule_collection.append({ 'pattern': regex_pattern, 'L1_Category': rule_row['L1 Category'], 'L2_Category': rule_row['L2 Category'] }) # 收集所有匹配结果 matched_results = [] for _, text_row in mydata.iterrows(): text_content = str(text_row['Text']) # 遍历所有规则,检查匹配 for rule in rule_collection: if rule['pattern'].search(text_content): # 复制原行数据并添加分类标签 result_row = text_row.copy() result_row['L1 Category'] = rule['L1_Category'] result_row['L2 Category'] = rule['L2_Category'] matched_results.append(result_row) # 转换为DataFrame并去重(按需保留) final_output = pd.DataFrame(matched_results).drop_duplicates().reset_index(drop=True)
进一步性能提升建议
如果数据集规模达到百万级以上,可以尝试:
- 使用Dask进行并行处理,将文本拆分后多进程匹配
- 改用spaCy的PhraseMatcher,针对多词关键词的匹配效率更高
- 对文本进行预处理(如统一小写、去除特殊字符),避免正则的
IGNORECASE开销
内容的提问来源于stack exchange,提问作者Lacri Mosa
相关产品推荐
相关产品推荐

