Pandas处理CSV数据时10000行后速度骤降问题求助
Pandas处理大CSV速度骤降的原因分析与优化方案
核心问题根源
你的代码性能骤降主要来自以下几个反模式操作:
- 逐行遍历
iterrows():Pandas是为向量化操作设计的,逐行处理会完全抛弃底层优化,随着数据量增大,性能开销呈线性累积。 - 频繁的
inplace=True修改:每次charges.drop(index, inplace=True)都会触发原DataFrame的内存重排和复制,数据量越大,单次操作的相对开销越高。 - 无效的逐行修改:
iterrows()返回的是行数据的副本,修改charge['TotalBalance']等操作不会同步到原DataFrame,等于做了大量无用功。 - 跨DataFrame索引混乱:拆分后的子DataFrame与原DataFrame共享索引,遍历子DataFrame时修改原DataFrame,会导致后续遍历的子数据与原数据脱节,增加额外的索引校验开销。
优化后的实现方案
以下是完全基于向量化操作的优化代码,性能可提升数个数量级:
import pandas as pd import numpy as np from datetime import datetime def clean_charges(conn, cur): # 读取CSV并解析日期字段 charges = pd.read_csv( 'csv/all_charges.csv', parse_dates=[ 'CreatedDate', 'PostingDate', 'PrimaryInsurancePaymentPostingDate', 'SecondaryInsurancePaymentPostingDate', 'TertiaryInsurancePaymentPostingDate' ] ) cur_month = datetime.combine(datetime.now().date().replace(day=1), datetime.min.time()) # 1. 批量过滤当前月份的记录 mask_current_month = charges['PostingDate'] >= cur_month removed_count = mask_current_month.sum() charges = charges[~mask_current_month].copy() # 2. 批量处理当前月份的保险支付回滚 # 主保险支付回滚 mask_primary_pay = charges['PrimaryInsurancePaymentPostingDate'] >= cur_month charges.loc[mask_primary_pay, 'TotalBalance'] += charges.loc[mask_primary_pay, 'PrimaryInsuranceInsurancePayment'] charges.loc[mask_primary_pay, 'PrimaryInsurancePayment'] = 0 # 次保险支付回滚 mask_secondary_pay = charges['SecondaryInsurancePaymentPostingDate'] >= cur_month charges.loc[mask_secondary_pay, 'TotalBalance'] += charges.loc[mask_secondary_pay, 'SecondaryInsuranceInsurancePayment'] charges.loc[mask_secondary_pay, 'SecondaryInsurancePayment'] = 0 # 三级保险支付回滚 mask_tertiary_pay = charges['TertiaryInsurancePaymentPostingDate'] >= cur_month charges.loc[mask_tertiary_pay, 'TotalBalance'] += charges.loc[mask_tertiary_pay, 'TertiaryInsuranceInsurancePayment'] charges.loc[mask_tertiary_pay, 'TertiaryInsurancePayment'] = 0 # 3. 批量校验余额并修正 calculated_balance = ( charges['AdjustedCharges'] - charges['PrimaryInsuranceInsurancePayment'] - charges['SecondaryInsuranceInsurancePayment'] - charges['TertiaryInsuranceInsurancePayment'] - charges['PatientPaymentAmount'] ) mask_balance_error = calculated_balance != charges['TotalBalance'] charges.loc[mask_balance_error, 'SecondaryInsurancePayment'] = 0 # 保存处理结果 charges.to_csv('csv/updated_charges.csv', index=False) print(f"处理完成,共移除{removed_count}条当前月份记录")
优化点说明
- 向量化操作替代逐行遍历:所有条件判断和数据修改都通过布尔索引和
loc批量完成,充分利用Pandas底层的C级优化。 - 批量过滤替代逐行删除:直接通过
charges[~mask_current_month]过滤数据,避免了多次drop操作带来的内存开销。 - 避免无效修改:使用
loc直接修改原DataFrame的对应行,确保操作生效,消除无用的副本修改。 - 移除不必要的DataFrame拆分:拆分操作不仅没有提升性能,反而引入了索引混乱,直接处理完整DataFrame更高效。
内容的提问来源于stack exchange,提问作者Alex Childs
相关产品推荐
相关产品推荐

