Pandas高效拆分超1亿行大CSV并写入数千小文件的技术问询
高效拆分1亿行大型CSV文件的优化方案
嘿,处理1亿行的超大CSV拆分确实是个棘手的活儿,我之前在处理日志导出文件时踩过不少坑,结合你的现有方案,给你几个能显著提升效率的思路:
一、用原生Python csv 模块替代pandas(轻量无冗余开销)
pandas的DataFrame虽然方便,但对于纯拆分场景来说,额外的内存和CPU开销其实没必要。原生csv模块更轻量,能直接操作行数据,速度会快不少。
示例代码:
import csv def split_large_csv(input_file, output_prefix, rows_per_file=1000000): with open(input_file, 'r', newline='', encoding='utf-8') as infile: reader = csv.reader(infile) header = next(reader) # 读取表头 file_index = 1 current_writer = None current_row_count = 0 for row in reader: if current_row_count == 0: # 新建输出文件并写入表头 output_file = f"{output_prefix}_{file_index:03d}.csv" current_writer = csv.writer(open(output_file, 'w', newline='', encoding='utf-8')) current_writer.writerow(header) current_row_count = 1 else: current_writer.writerow(row) current_row_count += 1 if current_row_count > rows_per_file: current_writer = None # 自动关闭文件句柄 file_index += 1 current_row_count = 0 # 调用示例:每100万行拆一个文件 split_large_csv("large.csv", "output", 1000000)
这个方案避免了pandas的DataFrame构造开销,纯行级操作,内存占用极低,适合超大规模文件。
二、优化pandas现有方案(如果必须用pandas处理数据)
如果拆分过程中需要做数据清洗、转换,不得不保留pandas,那可以从这几点优化:
增大分块大小,减少IO次数
把chunksize设得更大(比如100万行,根据你的内存调整),减少循环迭代的次数,降低文件打开/关闭的开销。避免追加模式,直接写入独立文件
不要每次用mode='a'追加,而是每个分块直接写入新文件,避免文件指针移动的额外开销:import pandas as pd def split_with_pandas(input_file, output_prefix, chunksize=1000000): chunk_iter = pd.read_csv(input_file, chunksize=chunksize) file_index = 1 for chunk in chunk_iter: output_file = f"{output_prefix}_{file_index:03d}.csv" # 仅第一个文件写入表头,后续只写数据 chunk.to_csv( output_file, float_format='%.8f', index=False, header=(file_index == 1), mode='w' ) file_index += 1 split_with_pandas("large.csv", "output_pd", 1000000)使用更快的IO引擎
如果安装了pyarrow,可以指定engine='pyarrow',pandas的CSV读写速度会大幅提升:chunk_iter = pd.read_csv(input_file, chunksize=chunksize, engine='pyarrow') # 写入时也指定engine chunk.to_csv(output_file, ..., engine='pyarrow')
三、用系统级命令行工具(最快的纯拆分方案)
如果不需要对数据做任何处理,只是单纯拆分,系统级工具是最快的选择,因为它们绕过了Python解释器的开销,直接操作文件系统。
方案1:用awk(支持复杂CSV格式,比如字段含换行/引号)
awk能正确识别CSV的字段边界,不会把字段内的换行当成行分隔符,适合复杂格式的CSV:
# 每100万行拆一个文件,自动添加表头 awk -v lines=1000000 ' NR==1 {header=$0; next} (NR-1)%lines==1 { close(outfile) outfile="split_"sprintf("%03d", (NR-1)/lines+1)".csv" print header > outfile } {print > outfile} ' large.csv
方案2:用split(简单场景下最快,但不支持复杂CSV)
如果你的CSV没有特殊格式(字段不含换行/引号),split命令是最快的:
# 1. 先提取表头 head -n 1 large.csv > header.csv # 2. 拆分数据部分(跳过第一行),每100万行一个文件 tail -n +2 large.csv | split -l 1000000 - split_temp_ # 3. 给每个拆分后的文件添加表头 for file in split_temp_*; do cat header.csv "$file" > "${file%.temp}.csv" rm "$file" done
总结
- 纯拆分无数据处理:优先用
awk(复杂CSV)或split(简单CSV),速度比Python快数倍。 - 需要数据处理:用原生
csv模块比pandas高效;如果必须用pandas,优化分块大小和写入逻辑,配合pyarrow引擎。
内容的提问来源于stack exchange,提问作者Ale
相关产品推荐
相关产品推荐

