You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于文件名分组合并文件时,循环拼接DataFrame速度极慢求优化

提速优化方案与代码修正

先修正你的生成器问题

你第二段代码生成generator是因为没给列表推导式加方括号,导致pd.read_csv(...) for fn in v是生成器表达式,而非DataFrame列表。如果要沿用这个思路,应改成:

dict_df2 = {}
for k, v in dd.items():
    # 把生成器改为列表推导式,收集所有子DataFrame
    df_list = [pd.read_csv(fn
                           , parse_dates=['time']
                           , dayfirst=True
                           , skiprows=4
                           , sep="\t"
                           , decimal=','
                    ).assign(Path=fn) for fn in v]
    dict_df2[k] = pd.concat(df_list, ignore_index=True)

这和你最初的逻辑一致,但写法更清晰。

提速优化方法

1. 预定义read_csv参数,减少重复开销

把read_csv的参数打包成字典,避免每次调用重复编写,同时减少参数对象的重复创建:

read_params = {
    'parse_dates': ['time'],
    'dayfirst': True,
    'skiprows': 4,
    'sep': '\t',
    'decimal': ','
}

dict_df = {}
for k, v in dd.items():
    df_list = [pd.read_csv(fn, **read_params).assign(Path=fn) for fn in v]
    dict_df[k] = pd.concat(df_list, ignore_index=True)

2. 指定数据类型(dtype),避免自动推断

pandas自动推断列类型会消耗大量时间,提前指定非日期列的dtype可大幅提速:
比如假设数据里有value列是浮点型、id列是字符串:

read_params = {
    'parse_dates': ['time'],
    'dayfirst': True,
    'skiprows': 4,
    'sep': '\t',
    'decimal': ',',
    'dtype': {'value': float, 'id': str}  # 按需添加你的列类型
}

3. 并行读取文件(IO密集型任务最优解)

读取文件属于IO密集型操作,用多进程并行处理可充分利用资源,大幅缩短时间。示例用concurrent.futures:

from concurrent.futures import ProcessPoolExecutor
import pandas as pd
import os
from glob import glob
from collections import defaultdict

read_params = {
    'parse_dates': ['time'],
    'dayfirst': True,
    'skiprows': 4,
    'sep': '\t',
    'decimal': ','
}

def read_single_file(fn):
    return pd.read_csv(fn, **read_params).assign(Path=fn)

# 先完成文件分组
path = "你的文件路径"
filenames = glob(os.path.join(path, "*.xls"))
dd = defaultdict(list)
for fn in filenames:
    dd[fn.split('_202')[0]].append(fn)

# 并行处理每个分组内的文件
dict_df = {}
with ProcessPoolExecutor() as executor:
    for k, v in dd.items():
        df_list = list(executor.map(read_single_file, v))
        dict_df[k] = pd.concat(df_list, ignore_index=True)

注意:Windows系统下,ProcessPoolExecutor需要把代码放在if __name__ == '__main__':块内运行。

4. 只读取需要的列

如果不需要所有列,用usecols指定目标列,减少内存占用和读取时间:

read_params = {
    # 其他参数不变
    'usecols': ['time', 'value', 'id']  # 仅读取所需列
}

5. 纠正append的误区

你听说的"append更快"是错误的——pandas的DataFrame.append()效率极低,每次调用都会创建新的DataFrame对象,反而不如收集所有DF到列表后一次性pd.concat高效,这也是你最初代码的核心思路,只是可通过上述方法进一步优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:18:07