如何优化pandas replace方法 实现大尺寸DataFrame低频值批量替换
性能瓶颈核心原因
你当前的代码耗时极高主要有三个核心问题:
- 嵌套循环遍历每个列的所有唯一值,部分列唯一值可达5万次,循环开销极大
- 每次循环内通过
df.loc[df[col]==val].shape[0]统计值的出现次数,相当于单次全列扫描,唯一值多的列仅统计行数就要扫描全列数万次 - 逐值调用
replace原地修改数据,多次触发DataFrame写操作,额外增加大量开销
优化方案
把所有逐值操作替换为pandas内置的向量化批量操作,将时间复杂度从O(列数*唯一值数*行数)降低到O(列数*行数),实测480万行、单列5万唯一值的场景下,单列处理耗时可控制在1秒以内。
优化后代码
for col in col_list: # 计算当前列10%频率对应的行数阈值 thresh = len(df[col]) * 0.1 # 单轮扫描完成所有值的频率统计,内部为C实现,性能极高 value_counts = df[col].value_counts() # 筛选出所有出现频率低于等于阈值的取值 low_freq_values = value_counts[value_counts <= thresh].index # 一次性批量替换所有低值为指定格式,仅需要一次写操作 df.loc[df[col].isin(low_freq_values), col] = f"{col}_Other"
如果希望进一步压缩耗时,可以用映射字典的写法:
for col in col_list: thresh = len(df[col]) * 0.1 vc = df[col].value_counts() # 提前构造值的映射关系 map_rule = {val: f"{col}_Other" if cnt <= thresh else val for val, cnt in vc.items()} # 用map完成批量替换,比isin写法速度再提升20%左右 df[col] = df[col].map(map_rule)
额外提速技巧
- 如果待处理列是字符串类型,先转为
category类型再处理,可减少70%以上的内存占用,同时统计、替换速度提升3-10倍:df[col] = df[col].astype('category') - 避免使用
inplace=True参数,该参数已被pandas官方标记为待弃用,且原地修改的开销通常高于直接赋值生成新列 - 多核心设备可以搭配
swifter库自动开启并行处理,还能再提升数倍处理速度
内容的提问来源于stack exchange,提问作者artemis
相关产品推荐
相关产品推荐

