350万行DataFrame用loc过滤耗时久,求高效过滤方案
针对大型Pandas DataFrame的快速过滤方案
哇,350万行的员工数据集确实会让普通的loc过滤慢到让人头疼!我来分享几个亲测有效的提速技巧,从简单调整到进阶工具都有,你可以根据自己的使用场景选择:
1. 优化列的数据类型
首先检查Emp_Name列的类型,如果它是默认的object类型,转换成category类型能大幅降低内存占用,同时加速比较操作:
# 转换为category类型 Emp['Emp_Name'] = Emp['Emp_Name'].astype('category') # 再执行过滤 Emp_subset = Emp.loc[Emp['Emp_Name'] == "John"]
原理:category类型会把重复的字符串映射成整数,比较时是整数间的运算,比字符串直接对比快得多,内存占用也能减少70%以上(视重复率而定)。
2. 使用query()方法
Pandas的query()方法底层依赖numexpr库,专门针对大型数组的表达式做了优化,执行效率比普通的布尔索引更高:
Emp_subset = Emp.query('Emp_Name == "John"')
如果你的过滤条件更复杂(比如多条件组合),query()的优势会更明显,写法也更简洁。
3. 直接操作Numpy数组
绕过Pandas的Series包装,直接用底层的Numpy数组生成过滤掩码,有时候能获得额外的速度提升:
# 生成numpy布尔掩码 mask = Emp['Emp_Name'].values == "John" # 应用掩码过滤 Emp_subset = Emp[mask]
原理:Pandas的Series在做比较时会有一些额外的开销,直接操作numpy数组能减少这些 overhead。
4. 提前建立索引(适合重复查询场景)
如果需要频繁按Emp_Name进行过滤,给该列建立索引是一劳永逸的方案:
# 给Emp_Name列设置索引(可以选择inplace=True直接修改原DataFrame) Emp = Emp.set_index('Emp_Name') # 后续过滤直接通过索引取值,速度极快 Emp_subset = Emp.loc['John']
注意:如果后续需要修改Emp_Name列的值,索引可能会失效,所以这个方案更适合以查询为主的静态数据集。
5. 用大数据工具处理(进阶方案)
如果数据集大到内存吃紧,或者以上方法还是不够快,可以试试专门的大数据处理库:
- Dask:支持分块处理Pandas DataFrame,自动利用多核CPU,语法和Pandas几乎一致,无需大幅修改代码。
- Vaex:采用延迟计算和内存映射技术,即使是远超内存的数据集也能快速处理,过滤操作几乎瞬间完成。
举个Vaex的简单例子:
import vaex # 加载数据(无需全量加载到内存) Emp = vaex.read_csv('your_emp_data.csv') # 执行过滤 Emp_subset = Emp[Emp.Emp_Name == "John"]
额外小贴士
- 先优化整个DataFrame的内存占用:比如把不需要高精度的数值列从
int64/float64改成int32/float32,能大幅减少内存压力,间接提升所有操作的速度。 - 确保你的Pandas和依赖库(比如numexpr、numpy)都是最新版本,新版本通常会有性能优化。
内容的提问来源于stack exchange,提问作者ASING
相关产品推荐
相关产品推荐

