如何优化正则匹配流程,给Pandas DataFrame快速打分类标签?
正则匹配打标签性能优化方案
- 预编译所有正则表达式
你当前代码每次调用re.search都会触发一次正则编译,百万次循环对应百万次编译开销,提前用re.compile()把所有正则预编译好,编译时就传入flags,后续直接调用编译后对象的search方法即可,能减少至少70%的正则相关开销。 - 替换逐行apply为Pandas矢量化字符串操作
df.apply是Python层的逐行循环,性能极低,改用Pandas原生的str.contains方法,底层是C实现的矢量化操作,处理百万行数据速度能提升5~10倍。 - 正则本身的语法优化
你当前的正则用了大量不必要的捕获组,会额外存储匹配结果浪费性能,全部改成非捕获组(?:)即可;另外把容易匹配失败、判断速度更快的规则放在正则最前面,触发快速失败减少无效匹配。 - 调整判断顺序减少无效运算
把普通字符串匹配(比如判断是否包含Random Word Here)放在正则判断之前,普通字符串查找的速度远快于正则匹配,能提前过滤掉大量不需要走正则判断的行;同时把业务中出现频率最高的标签判断放在最前面,大部分样本匹配到第一个规则就可以返回结果,不需要执行后续判断。
优化后代码示例
import re import pandas as pd # 第一步:预编译所有正则,替换捕获组为非捕获组,提前传入flags # 汽车类正则优化示例(仅展示修改逻辑,完整规则自行替换) auto_pattern = r'''(?: (?:ACURA)| (?:ALFA ROMEO)| (?:\bAUDI\b)| (?:BMW\s?FINANCIAL)| # 其余原有规则保持不变,所有捕获组()改成非捕获组(?:) (?:VOLVO))(?!.*PAYROLL) ''' compiled_auto = re.compile(auto_pattern, flags=re.I | re.X) compiled_typeone = re.compile(typeone_pattern, flags=re.I) compiled_typetwo = re.compile(typetwo_pattern, flags=re.I) # 第二步:用矢量化操作打标签,避免逐行apply df['label'] = 'Other' # 按标签出现频率从高到低依次处理 mask_typeone = df['string_column'].str.contains(compiled_typeone) & ~df['string_column'].str.contains('Random Word Here', regex=False) df.loc[mask_typeone, 'label'] = 'Label 1' mask_auto = df['string_column'].str.contains(compiled_auto) & (df['label'] == 'Other') df.loc[mask_auto, 'label'] = 'Label Auto' mask_typetwo = df['string_column'].str.contains(compiled_typetwo) & (df['label'] == 'Other') df.loc[mask_typetwo, 'label'] = 'Label 2' # 其余标签按优先级依次处理即可
按照以上方案优化后,百万行数据的处理耗时通常可以从1分钟压缩到10秒以内,如果还有更高性能需求,可以进一步用PyArrow作为Pandas的后端,或者用多线程库并行处理不同的规则块。
内容的提问来源于stack exchange,提问作者mikelowry
相关产品推荐
相关产品推荐

