如何优化基于列表筛选40万行数据库的效率?
优化40万行DataFrame关键词筛选的方法
针对你用str.contains处理大正则导致的性能问题,分两种匹配场景给出优化方案:
场景1:匹配完整单词(精确匹配)
如果你的需求是匹配description中的完整单词(而非子字符串),用集合查找的效率远高于正则,步骤如下:
- 将搜索列表转为集合(集合查找时间复杂度为O(1))
- 拆分文本为单词后,通过分组判断是否存在匹配词
示例代码:
import pandas as pd # 转换搜索列表为集合 search_set = set(search_list) # 拆分文本、展开匹配、聚合判断 matches = ( df['description'] .str.split(r'\W+', expand=True) # 按非单词字符(空格、标点等)拆分文本 .stack() # 将拆分后的单词展开为多行 .isin(search_set) # 判断单词是否在搜索集合中 .groupby(level=0).any() # 按原行索引分组,只要有一个匹配就标记为True ) # 筛选结果 filtered_df = df[matches]
场景2:匹配子字符串(模糊包含)
如果需要匹配任意子字符串(比如搜索"cat"要匹配"category"),可以通过以下方式优化正则匹配:
方法1:预编译正则表达式
预编译正则可以避免重复解析长正则,提升匹配效率:
import re # 预编译正则,忽略大小写 pattern = re.compile('|'.join(search_list), flags=re.IGNORECASE) filtered_df = df[df['description'].str.contains(pattern, na=False)]
方法2:拆分搜索词为小批次匹配
过长的正则表达式会降低引擎效率,拆分批次后合并结果:
import re batch_size = 100 # 每批次处理100个搜索词 matches = pd.Series([False] * len(df), index=df.index) for i in range(0, len(search_list), batch_size): # 截取当前批次的搜索词 batch_words = search_list[i:i+batch_size] # 编译当前批次的正则 batch_pattern = re.compile('|'.join(batch_words), flags=re.IGNORECASE) # 合并匹配结果 matches |= df['description'].str.contains(batch_pattern, na=False) filtered_df = df[matches]
方法3:用Numba加速循环匹配
通过Numba编译匹配函数,加速逐行判断:
import numpy as np from numba import jit # 用Numba编译匹配函数 @jit(nopython=True) def has_substring_match(text, words): text_lower = text.lower() for word in words: if word.lower() in text_lower: return True return False # 转换搜索列表为NumPy数组,提升Numba处理效率 words_np = np.array(search_list) # 逐行判断匹配 matches = df['description'].apply(lambda x: has_substring_match(x, words_np)) filtered_df = df[matches]
通用优化技巧
- 提前清理
description列:去掉多余空格、特殊字符,减少文本处理长度 - 处理NaN值:在
str.contains中加入na=False,避免额外的空值处理开销 - 大数据量可选Dask:如果数据集超过内存承载,用Dask进行并行处理
内容的提问来源于stack exchange,提问作者Akram H
相关产品推荐
相关产品推荐

