You need to enable JavaScript to run this app. Python中高效拼接数千个DataFrame的最优方法是什么?
优惠活动
大模型
产品
解决方案
定价
更多

Python中高效拼接数千个DataFrame的最优方法是什么?

原实现的核心性能问题

你当前写法运行越来越慢的根本原因,是把concat合并逻辑放到了循环内部:
每读一个小CSV,就会把之前已经累计的所有DataFrame和新读的文件重新拼接一次,而pandas的concat每次执行都会重新申请连续内存,把全量已有数据完整拷贝一遍。30000次循环下来,光冗余的数据拷贝操作就占了90%以上的运行时间,整体时间复杂度是O(n²),自然越到后面跑得越慢。

可落地的高效优化方案

方案1:最小改动的快速优化(90%的场景适用)

只需要把原来循环里反复合并的逻辑改掉,先把所有读到的DataFrame存在一个列表里,等所有文件都读完了,最后一次性做一次concat就行。整个流程只需要做1次全量内存分配和数据拷贝,相比原来的写法,性能能提升10-20倍,改起来只需要动几行代码。
示例代码:

# 初始化空列表,专门存读到的每个小DataFrame
df_pool = []
for file in onlyfiles:
    # 读文件时可以加两个实用参数,进一步提速、降内存
    # 1. usecols:只读你需要的两列,不用加载CSV里其他无关的列
    # 2. dtype:提前指定列的数据类型,避免pandas自动推断类型带来的额外开销
    current_df = pd.read_csv(
        file,
        usecols=["product_id", "price"],
        dtype={"product_id": str, "price": "float32"}
    )
    df_pool.append(current_df)

# 所有文件都读完了,最后一次性合并
final_df = pd.concat(df_pool, ignore_index=True, copy=False)

小提示:因为所有CSV都是你自己爬的,列结构肯定是统一的,加usecols和dtype这两个参数,读文件的速度还能再提30%左右,内存占用也会降一半以上。

方案2:低内存占用的无全量加载方案

如果30000个CSV总大小特别大(比如总共有几十GB),你的设备可用内存扛不住把所有DataFrame都存在列表里,可以直接跳过内存合并的步骤,逐文件往最终的合并CSV里追加内容,全程同一时间只需要加载单个小文件的内容,内存占用几乎可以忽略,哪怕10万个文件也不会爆内存。
示例代码:

merged_output = "all_products_merged.csv"
for idx, file in enumerate(onlyfiles):
    try:
        current_df = pd.read_csv(file)
        # 第一个文件正常写,带上表头
        if idx == 0:
            current_df.to_csv(merged_output, index=False, mode="w")
        # 从第二个文件开始,跳过表头,用追加模式写进去
        else:
            current_df.to_csv(merged_output, index=False, mode="a", header=False)
    except Exception as e:
        # 遇到空文件、损坏的坏文件直接跳过,记录下来就行,不要让整个循环崩掉
        print(f"读取{file}失败,已跳过")

方案3:追求极致速度的并行读取方案

合并大量小CSV的操作本质是磁盘IO密集型任务,单线程读文件没法把SSD/机械硬盘的读写带宽吃满,可以用多进程并行读文件,再把结果汇总合并,相比单线程读取还能再快2-5倍。
实现逻辑很简单:开和磁盘IO能力匹配的固定数量进程(一般开4-8个进程就够,不要开太多挤占内存),每个进程负责读取一个CSV并返回DataFrame,等所有进程都把文件读完,主线程再一次性执行concat汇总结果就行。对新手来说如果觉得配置多进程麻烦,用前两个方案基本就足够覆盖30000个文件的合并需求了。

常见避坑提醒
  • 千万不要在循环里反复写df = pd.concat([df, new_df]),这是合并大量小文件时最慢的写法,没有之一
  • 如果不需要保留原来每个小文件的行索引,concat的时候一定要加ignore_index=True,避免pandas做多余的索引对齐计算
  • 读文件的时候尽量用dtype指定列类型,不要让pandas自动推断类型,否则3万个文件的类型推断开销也会占不少时间

内容的提问来源于stack exchange,提问作者Jauhnax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.09 05:15:03