应分块读取+流式去重:用chunksize=50000逐块读CSV,统一列名和dtype后累加concat并立即按业务主键drop_duplicates(subset=['order_id'], keep='first'),最终用csv.writer边处理边写入避免内存膨胀。

用 pandas.concat 合并大CSV,但别直接全读进内存
单个CSV超500MB就容易OOM,pandas.read_csv 默认把整个文件加载成DataFrame,多个一起concat等于内存翻倍再翻倍。必须分块读取+流式去重。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
chunksize=50000(根据内存调,16GB机器建议≤10万)逐块读,每块转为DataFrame后立刻处理 - 合并前统一列名和dtype,否则
concat会隐式转换导致后续去重失效(比如字符串列混入nan变成float) - 不要用
pd.concat([df1, df2, ...])一次性拼接所有块——改用累加:先初始化一个空result_df,每读一块就pd.concat([result_df, chunk], ignore_index=True),并立即drop_duplicates
去重必须指定 subset,且优先用 keep='first'
全字段去重(df.drop_duplicates())在大数据量下极慢,因为要哈希整行;更糟的是,如果某列含nan,drop_duplicates默认把所有nan视为相同值,可能误删有效行。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 明确业务主键字段,例如订单号
'order_id'或用户ID'user_id',传给subset=['order_id'] -
keep='first'比'last'快约15%(底层跳过重复项扫描),且语义清晰:保留首次出现的记录 - 如果需按时间保留最新记录,先
sort_values('update_time', ascending=False)再drop_duplicates(subset=['order_id'], keep='first'),别反过来
用 csv.writer 直接写入避免中间DataFrame膨胀
最终结果DataFrame仍可能很大,再用to_csv输出会二次内存占用。绕过DataFrame,用Python原生csv模块边处理边写入更稳。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 提前打开输出文件句柄:
with open('merged_unique.csv', 'w', newline='') as f: - 用
csv.writer(f)写表头(从第一块chunk取chunk.columns.tolist()) - 每处理完一块,用
writer.writerows(chunk.values.tolist())直接写入——不经过DataFrame序列化 - 注意:此方式要求所有chunk列顺序、类型一致,务必在读取时用
usecols和dtype强制对齐
遇到 MemoryError 或 UnicodeDecodeError 怎么办
前者是内存真爆了,后者常因混合编码(如部分文件是gbk,部分是utf-8-sig)。这两个错误在自动化脚本里必须显式捕获,不能让整个流程中断。
实操建议:
立即学习“Python免费学习笔记(深入)”;
-
MemoryError:降chunksize到10000,或改用dask.dataframe(但要注意dask的drop_duplicates不支持subset参数,得用map_partitions手动实现) -
UnicodeDecodeError:读取时加encoding='utf-8',失败则回退encoding='gb18030'(中文Windows常见),用try/except包裹read_csv - 加日志:每完成一个文件打印
f"Processed {file_path}: {len(chunk)} rows",方便定位卡在哪一步
真正难的不是语法,是chunksize设多少、编码怎么试、主键字段有没有空值——这些得看数据本身,脚本跑起来之前先抽样检查三个文件的结构和内容。


















