如何更快地基于字符串筛选Pandas DataFrame的行?
如何在Pandas中高效重复筛选字符串匹配的行?
我需要反复从Pandas DataFrame中筛选出字符串匹配特定值的行,目前已经尝试了将字符串哈希后通过哈希值筛选的方式,发现速度比直接文本匹配快50-60倍。想请教有没有性能更优的实现方案?
以下是我的测试代码:
import pandas as pd import random from string import ascii_letters from timeit import default_timer as timer # 创建测试数据集 df = pd.DataFrame(data=list(range(100000000)), columns=["id"]) df['searchtext'] = [''.join(random.choice(ascii_letters) for x in range(3)) for _ in range(len(df))] df['hash'] = df.searchtext.transform(hash) print(df) # 普通文本匹配筛选 start = timer() df[df.searchtext == 'aaa'] end = timer() print(f'文本匹配耗时 {end-start} 秒') # 哈希值匹配筛选 start = timer() df[df.hash == hash('aaa')] end = timer() print(f'哈希匹配耗时 {end-start} 秒')
更优性能方案推荐
1. 将字符串列转为Categorical类型
如果searchtext列存在大量重复值(比如测试代码里的3位随机字母),转为分类类型能极大提升匹配速度。分类类型会自动把字符串映射为整数编码,匹配时直接对比整数,性能和哈希方案相当甚至更优,还能大幅节省内存。
实现代码:
# 转换为分类类型 df['searchtext_cat'] = df['searchtext'].astype('category') # 分类类型筛选 start = timer() df[df.searchtext_cat == 'aaa'] end = timer() print(f'分类类型匹配耗时 {end-start} 秒')
- 核心优势:无需额外计算哈希值,Pandas内部完成编码映射,重复筛选时直接复用编码,内存占用远低于原字符串列和哈希列。
2. 提前构建字符串到行索引的映射表
如果需要频繁针对不同字符串值筛选,提前构建字典映射每个字符串对应的行索引列表,后续筛选直接通过字典取值获取结果,这是重复筛选场景下最快的方案。
实现代码:
from collections import defaultdict # 构建字符串到行索引的映射 str_to_indices = defaultdict(list) for idx, s in enumerate(df['searchtext']): str_to_indices[s].append(idx) # 通过映射表筛选 start = timer() df.loc[str_to_indices['aaa']] end = timer() print(f'映射表筛选耗时 {end-start} 秒')
- 核心优势:映射表只需构建一次,每次筛选都是O(1)的字典查询速度,性能远超哈希和分类类型方案;
- 注意事项:若DataFrame后续有行的增删改操作,需同步更新映射表。
3. 对哈希列或分类列建立索引
不管是哈希列还是分类列,为其建立Pandas索引后,筛选时会利用索引的快速查找特性,进一步提升性能:
# 给哈希列建立索引 df.set_index('hash', inplace=True) # 索引查找 start = timer() df.loc[hash('aaa')] end = timer() print(f'哈希索引查找耗时 {end-start} 秒') # 或者给分类列建立索引 df.set_index('searchtext_cat', inplace=True) start = timer() df.loc['aaa'] end = timer() print(f'分类索引查找耗时 {end-start} 秒')
- 核心优势:索引基于树结构实现快速定位,比普通列的布尔索引更快,适合大规模数据集的重复筛选。
各方案性能对比总结
在1亿行、3位重复字符串的测试场景下,性能排序大致为:
映射表筛选 > 索引化哈希/分类列 > 分类列筛选 > 哈希列筛选 > 普通文本筛选
可根据实际场景选择:
- 筛选频率极高:优先选映射表方案;
- 数据集稳定且需兼顾内存:优先选分类类型方案;
- 字符串重复率较低:哈希列+索引的方案更合适。
内容的提问来源于stack exchange,提问作者user2699676
相关产品推荐
相关产品推荐

