应避免在循环中反复调用pd.concat,因其每次都会分配新内存并深拷贝数据,导致时间复杂度趋近o(n²)、内存峰值膨胀3–5倍;正确做法是先将各dataframe存入列表,再一次性合并。

循环中反复调用 pd.concat 会触发多次内存复制
每次执行 pd.concat([old_df, new_df], axis=0),Pandas 都必须分配一块**全新内存**,把 old_df 和 new_df 的所有数据拷贝进去。这不是“追加”,而是“重建”。随着 old_df 行数增长,单次 concat 的拷贝量呈线性上升,总耗时接近 O(n²) —— 1000 个文件可能花 10 分钟,2000 个就可能奔向 40 分钟。
pd.concat 在循环里无法复用底层 NumPy 数组视图
即使你只读取小 CSV 并转置,pd.read_csv + set_index().T 生成的 DataFrame 内部仍是独立数组。循环中拼接时,Pandas 不会尝试共享内存或复用视图,而是强制深拷贝。实测显示:对两个 1000×1000 的 DataFrame 做一次 concat,新增内存 ≈ 原始数据总和;而循环调用 100 次,峰值内存可能膨胀 3–5 倍。
替代方案不是“换函数”,而是“换结构”
关键不在怎么调 concat,而在**避免在循环中调它**:
- 把每个文件读出的
DataFrame存进列表(dfs.append(df_one)),最后一次性pd.concat(dfs, axis=0, ignore_index=True) - 如果内存吃紧,改用生成器 +
pd.concat分批合并(比如每 50 个文件合并一次) - 读取阶段就并行化:用
concurrent.futures.ThreadPoolExecutor并发读 CSV,结果仍存列表,最后单次concat
注意:copy=False 参数对循环内 concat 几乎无效 —— 它只影响输入对象是否被浅拷贝,不改变拼接过程本身的内存分配逻辑。
容易被忽略的隐性开销:索引重置与列对齐
循环中 pd.concat 默认会重排索引、校验列名一致性。哪怕所有文件结构完全一致,Pandas 仍逐字段比对、自动填充缺失列(变成 object 类型),这额外消耗 CPU。一次性合并时,这些校验只做一次;循环里则重复执行 1000 次。
真正卡住的往往不是磁盘 I/O,而是内存分配器在频繁 malloc/free 时的锁竞争,以及 Python GC 对大量临时 DataFrame 对象的扫描压力。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











