Python实现字符串子串字典匹配及pandas DataFrame批量赋值优化
基于Pandas的字典子串批量匹配方案优化
业务场景说明
核心处理逻辑规则:
- 存在固定映射字典
substrings,字典键为待匹配的目标子串,值为子串对应的关联数值 - 待测数据集为pandas DataFrame
df,其中string_to_check列存储全量待校验字符串,根据业务约定,每个字符串仅会包含字典中唯一一个目标子串 - 需为DataFrame新增
result列,存储每行字符串匹配到的子串对应的映射值,最终输出效果如下:
| string_to_check | result |
|---|---|
| 'TEST13-872B-A22E' | 0 |
| 'CORONA1-241-22E' | 2 |
| 'TEST32-33A-442' | 0 |
| 'WORLD4-BB2-A343' | 1 |
现有基础实现
最初的草稿函数存在细节疏漏:直接引用substrings.keys、substrings.values时未加括号,导致实际遍历的是字典方法对象而非对应的键值集合,修正括号语法后可正常运行的版本如下:
substrings = {'TEST': 0, 'WORLD': 1, 'CORONA': 2} def check_string(string_to_check): for stri, val in zip(substrings.keys(), substrings.values()): if stri in string_to_check: return val df['result'] = df['string_to_check'].apply(check_string)
这类实现虽然能跑通,但逐行循环的模式可读性、运行效率都有优化空间。
更简洁高效的Pythonic实现
依托pandas原生的向量化字符串操作能力,完全可以摒弃逐行apply的模式,写出更短、更快、逻辑更清晰的代码:
方案1:逐键批量填充匹配结果
逻辑为遍历映射字典的每一组键值对,通过向量化的字符串判断批量筛选匹配行、直接赋值对应的值,不需要编写自定义函数:
# 初始化result列存储结果 df['result'] = pd.NA for sub_str, val in substrings.items(): # 对包含当前子串的行批量赋值,regex=False关闭正则解析进一步提速 mask = df['string_to_check'].str.contains(sub_str, regex=False) df.loc[mask, 'result'] = val
- 优势:逻辑直白易懂,向量化判断底层基于C语言实现,在万级以上数据量的场景下,运行速度通常是逐行apply的10~100倍
- 注意:匹配固定子串时一定要加
regex=False,避免因为子串包含正则特殊字符导致匹配错误,同时减少正则解析的性能开销
方案2:预编译正则一次性完成匹配
将所有目标子串拼接为正则匹配模式,一次性扫描全列提取匹配到的子串,再通过字典映射得到对应数值,是所有方案中速度最快的选择:
import re # 预编译正则:按子串长度倒序拼接,避免短子串优先匹配的边界问题 pattern = re.compile('|'.join(sorted(substrings.keys(), key=len, reverse=True))) # 一次性提取匹配子串,通过字典映射得到结果值 df['result'] = df['string_to_check'].str.extract(pattern, expand=False).map(substrings)
- 优势:仅需一次全列字符串扫描即可完成所有匹配,特别适合字典条目多、数据量大的生产场景
- 注意:业务约定每个字符串仅匹配一个目标子串,因此不会出现多个子串同时命中的冲突,倒序拼接的处理是通用兜底逻辑,能覆盖潜在的子串包含边界问题(比如字典同时存在
TEST和TEST12两个键时,避免短键优先匹配长键的内容)
内容的提问来源于stack exchange,提问作者flurble
相关产品推荐
相关产品推荐

