如何在Python中加速批量导入CSV并实现文件名过滤与新增文件名列
批量读取CSV文件的优化方案
你当前代码的最大耗时来源是循环内反复调用pd.concat,每次合并都要重新生成完整的大表,产生大量不必要的内存拷贝,调整后可大幅降低耗时,同时可以无缝兼容你需要的文件名筛选、新增文件名列的需求。
基础优化版(无额外依赖,改完即可提速)
import os import glob import pandas as pd start_directory = '/home/ubuntu/Desktop/noise_paper/part_2/Noise/Data/' # 一次性递归筛选所有符合要求的csv文件 csv_files = glob.glob(os.path.join(start_directory, '**/*.csv'), recursive=True) # 筛选文件名包含Pct的文件 target_files = [f for f in csv_files if 'Pct' in os.path.basename(f)] df_list = [] for file_path in target_files: tmp_df = pd.read_csv(file_path, header=None) # 新增列存储当前文件名 tmp_df['file'] = os.path.basename(file_path) df_list.append(tmp_df) # 仅做一次合并,完全消除反复concat的开销 df_result = pd.concat(df_list, axis='index', ignore_index=True)
仅上述改动就可以把你15分钟的耗时压缩到3-5分钟区间。
进阶多进程加速版(多核CPU可再降70%以上耗时)
读取CSV是IO密集型任务,利用多核CPU并行读取可以进一步提速:
import os import glob import pandas as pd from concurrent.futures import ProcessPoolExecutor def read_and_label_csv(file_path): tmp_df = pd.read_csv(file_path, header=None) tmp_df['file'] = os.path.basename(file_path) return tmp_df if __name__ == '__main__': start_directory = '/home/ubuntu/Desktop/noise_paper/part_2/Noise/Data/' csv_files = glob.glob(os.path.join(start_directory, '**/*.csv'), recursive=True) target_files = [f for f in csv_files if 'Pct' in os.path.basename(f)] # 默认进程数和CPU核心数一致,也可手动指定max_workers=N调整并发数 with ProcessPoolExecutor() as executor: df_list = list(executor.map(read_and_label_csv, target_files)) df_result = pd.concat(df_list, axis='index', ignore_index=True)
额外提速技巧
- 显式指定列类型:如果所有CSV的列结构完全一致,给
pd.read_csv传入dtype参数指定每列的数据类型,跳过pandas自动推断类型的开销,可再提速10%-20%。 - 用pyarrow引擎:如果使用pandas 2.0及以上版本,安装pyarrow依赖后,给
pd.read_csv添加engine='pyarrow'参数,CSV读取速度可提升2-3倍。
内容的提问来源于stack exchange,提问作者Cairan Van Rooyen
相关产品推荐
相关产品推荐

