如何高效基于另一列替换DataFrame单元格值?解决循环耗时问题
Pandas大DataFrame批量处理的高效优化方案
问题背景
需要处理100000行×27列的DataFrame:提取Package ID和Status ID的前6位对比,若不等则将该行Status ID设为NaN,最后去重。原逐行循环+反复拼接的方法处理9000行耗时超30秒,急需优化。
原代码的性能瓶颈
- 使用
iterrows()逐行遍历:Pandas的逐行操作是Python层面的循环,远慢于底层C实现的向量化操作 - 反复调用
_append():每次拼接都会创建新的DataFrame对象,时间复杂度为O(n²),数据量越大性能下降越明显
优化方案(向量化实现)
利用Pandas的向量化特性,一次性完成所有列操作,避免逐行处理和反复拼接:
import pandas as pd import numpy as np # 1. 向量化提取两列的前6位,生成对比掩码 pkg_prefix = pr_compliant['Package ID'].str[:6] status_prefix = pr_compliant['Status ID'].str[:6] # 标记需要将Status ID设为NaN的行 mask = pkg_prefix != status_prefix # 2. 复制原DataFrame,批量修改目标列 new_dr = pr_compliant.copy() new_dr.loc[mask, 'Status ID'] = np.nan # 3. 执行去重 new_dr = new_dr.drop_duplicates() print(new_dr)
性能提升原因
- 向量化操作:所有列处理都是Pandas底层C实现的批量操作,比Python循环快100~1000倍
- 避免重复拼接:直接复制原DataFrame后批量修改,仅需一次内存分配,时间复杂度为O(n)
- 去重操作也是向量化处理:Pandas的
drop_duplicates()基于底层优化,比自定义逐行去重高效得多
额外优化建议
- 如果
Package ID或Status ID包含非字符串类型,先统一转成字符串:pr_compliant['Package ID'] = pr_compliant['Package ID'].astype(str) pr_compliant['Status ID'] = pr_compliant['Status ID'].astype(str) - 去重时可指定子集列,减少计算量(如果不需要基于所有列去重):
new_dr = new_dr.drop_duplicates(subset=['Package ID', 'Status ID']) - 内存紧张时,可使用浅拷贝(需确保原DataFrame后续不会被修改):
new_dr = pr_compliant.copy(deep=False)
内容的提问来源于stack exchange,提问作者RohitM
相关产品推荐
相关产品推荐

