如何高效移除35GB CSV文件中text列单词数不足10的行?
处理大体积CSV文件:快速移除text列单词数不足10的行
我有一个35GB的大型CSV文件,格式示例如下:
"id","text","other_info" "1","this is some text, a news report citing more than 30 sources, including investors","some other info" "11","this is some text","sme other info" "111","","sme other info" "21","this is some real text Language models with hundreds of billions of parameters","sme other info"
期望处理后得到仅保留text列单词数≥10的行:
"id","text","other_info" "1","this is some text, a news report citing more than 30 sources, including investors","some other info" "21","this is some real text Language models with hundreds of billions of parameters","sme other info"
之前尝试用Python循环处理,但速度极慢,代码如下:
lst=[] for item in row: if len(row[1])>10: lst.append(row[1])
快速解决方案
1. 优化Python逐行处理(内存友好)
原代码逻辑有问题,且未正确处理CSV格式。改用csv模块逐行读取,不加载整个文件到内存,同时准确计算单词数:
import csv input_path = "input.csv" output_path = "output.csv" with open(input_path, "r", encoding="utf-8") as infile, open(output_path, "w", encoding="utf-8", newline="") as outfile: reader = csv.reader(infile) writer = csv.writer(outfile) # 写入表头 header = next(reader) writer.writerow(header) for row in reader: text = row[1].strip() if not text: continue # 按空格分割单词,自动忽略连续空格 word_count = len(text.split()) if word_count >= 10: writer.writerow(row)
这个方法避免了内存溢出,且处理逻辑准确,比原代码效率高很多。
2. Pandas分块处理(适合熟悉数据分析的场景)
利用Pandas的分块读取功能,每次处理一小部分数据,平衡内存占用和处理速度:
import pandas as pd chunk_size = 100000 # 可根据内存大小调整,比如200000 input_path = "input.csv" output_path = "output.csv" # 先写入表头 header = pd.read_csv(input_path, nrows=0).columns header.to_csv(output_path, index=False) # 分块读取并处理 for chunk in pd.read_csv(input_path, chunksize=chunk_size): # 计算text列单词数,处理空值 chunk["word_count"] = chunk["text"].fillna("").str.strip().str.split().str.len() # 筛选符合条件的行 filtered_chunk = chunk[chunk["word_count"] >= 10].drop(columns=["word_count"]) # 追加写入结果 filtered_chunk.to_csv(output_path, mode="a", index=False, header=False)
Pandas的向量操作比Python原生循环快,分块处理不会占用过多内存。
3. 命令行awk工具(速度最快)
如果你的系统支持awk,命令行处理是最快的选择,完全不需要加载文件到内存:
awk -F',' 'BEGIN {OFS=","} NR==1 {print; next} {gsub(/^"|"$/,"",$2); if(split($2, arr, /[[:space:]]+/) >=10) print}' input.csv > output.csv
-F',':设置输入分隔符为逗号BEGIN {OFS=","}:确保输出分隔符也是逗号NR==1 {print; next}:直接输出表头行gsub(/^"|"$/,"",$2):移除text列前后的引号split($2, arr, /[[:space:]]+/) >=10:按空格分割text列,统计单词数,达标则输出整行
原代码慢的原因
原代码存在逻辑错误(循环变量item未使用,直接操作row),且大概率错误地将整个大文件加载到内存,导致内存占用过高、处理速度骤降。
内容的提问来源于stack exchange,提问作者AJW
相关产品推荐
相关产品推荐

