如何高效在Pandas列中从指定列表搜索子字符串?
高效在Pandas DataFrame列中搜索子字符串的优化方案
问题背景
处理百万行级Pandas DataFrame时,使用str.contains()进行子字符串搜索速度极慢,仅适用于小数据集。现有示例代码如下:
frame = pd.DataFrame({'a' : ['111,222,333,444', '11,44', '222,333,444','666,777','555']}) mylist = ['111', '222', '444','555'] pattern = '|'.join(mylist) frame.loc[frame.a.str.contains(pattern)]
优化方案
以下是针对不同场景的更快搜索方法:
1. 针对逗号分隔的结构化数据(最优选择)
如果字符串是类似示例的逗号分隔格式,可借助集合精确匹配+行内聚合判断,完全避开正则开销:
import pandas as pd frame = pd.DataFrame({'a' : ['111,222,333,444', '11,44', '222,333,444','666,777','555']}) mylist = ['111', '222', '444','555'] target_set = set(mylist) # 拆分字符串后检查每行是否有元素在目标集合中 matches = frame['a'].str.split(',', expand=True).isin(target_set).any(axis=1) result = frame[matches]
这种方法利用集合查询的O(1)特性,速度远快于正则匹配,适合结构化分隔数据场景。
2. 针对非结构化自由文本(通用高效方案)
使用Google的re2正则引擎替代Python默认的re库,它采用非回溯式匹配,避免正则性能陷阱,在大数据集上速度提升明显:
- 安装依赖:
pip install re2 - 示例代码:
import re2 import pandas as pd frame = pd.DataFrame({'a' : ['111,222,333,444', '11,44', '222,333,444','666,777','555']}) mylist = ['111', '222', '444','555'] pattern = re2.compile('|'.join(mylist)) matches = frame['a'].apply(lambda x: bool(pattern.search(x))) result = frame[matches]
3. 预编译正则表达式(小幅提升)
如果暂时无法引入外部库,可预编译正则表达式减少重复编译开销,比直接使用str.contains()有小幅性能提升:
import re import pandas as pd import numpy as np frame = pd.DataFrame({'a' : ['111,222,333,444', '11,44', '222,333,444','666,777','555']}) mylist = ['111', '222', '444','555'] pattern = re.compile('|'.join(mylist)) # 用numpy矢量化函数批量匹配 matches = np.vectorize(lambda x: bool(pattern.search(x)))(frame['a']) result = frame[matches]
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

