大CSV文件非英文段落快速筛选的代码优化问询
兄弟,我看你这处理8万行CSV的问题,核心就是逐词遍历+列表查询拖慢了速度,还有没用到Pandas的高效操作。给你一套针对性的优化方案,处理8万行绝对秒级搞定:
核心优化思路
- 放弃逐词检查,优先整段语言检测:既然允许少量误判,
langdetect的整段检测速度快到飞起,完全没必要逐词啃语料库。 - 用Pandas矢量化操作替代原生for循环:手动遍历DataFrame行是效率杀手,Pandas的
apply/map内部做了优化,速度差好几个数量级。 - 语料库转集合:如果非要补单词校验,把nltk的语料库转成
set——列表的in是O(n),集合是O(1),这是你之前逐词慢的关键原因。
完整优化代码
import pandas as pd from langdetect import detect, LangDetectException import nltk from nltk.corpus import stopwords, words import csv # 你原来的代码漏了这个导入 # 提前加载语料库并转成集合(重中之重!) stop_e = set(stopwords.words('english')) english_words = set(words.words()) # 读取CSV,保持你的原有参数 df = pd.read_csv( "file.csv", sep='\t', header=0, index_col=False, quoting=csv.QUOTE_NONE, usecols=["TI","AB","PY","DI"], dtype=str ) # 定义英文判断函数:先粗筛再细查(可选) def is_english(text): # 先排除非字符串类型(比如NaN) if not isinstance(text, str): return False try: # 第一步:快速整段语言检测 if detect(text) != 'en': return False # 可选第二步:补充单词占比校验(怕langdetect误判的话开这个) tokens = nltk.word_tokenize(text) # 只保留字母组成的单词,转小写 alpha_tokens = [tok.lower() for tok in tokens if tok.isalpha()] if not alpha_tokens: return False # 计算英文单词(含停用词)的占比,阈值可以自己调 english_ratio = sum(1 for tok in alpha_tokens if tok in english_words or tok in stop_e) / len(alpha_tokens) return english_ratio > 0.8 # 比如要求80%以上是英文单词 except LangDetectException: # 处理无法检测的情况(比如文本太短、乱码) return False # 过滤出符合要求的行,直接生成新的DataFrame filtered_df = df[df["AB"].apply(is_english)] # 保存结果 filtered_df.to_csv("filtered_english_only.csv", sep='\t', index=False)
关键优化点解释
- 集合查询:把
stopwords和words转成set,查询速度直接从O(n)降到O(1),之前逐词慢就是因为用了列表的in操作,太耗时间。 - 矢量化操作:用
df["AB"].apply(is_english)替代手动遍历每一行,Pandas内部做了批量优化,比原生for循环快10-100倍。 - 先粗后细:先用langdetect快速过滤掉绝大多数非英文内容,只有通过的才做单词校验,减少不必要的计算。
- 异常处理:捕获
LangDetectException,避免因为空文本、太短文本导致程序崩溃。
进一步提速的可选方案
如果langdetect还是不够快,可以试试fastText——Facebook开源的语言检测工具,速度更快,准确率也更高,适合超大规模数据集。用法大概是这样:
import fasttext # 先下载预训练模型(本地加载即可) model = fasttext.load_model('lid.176.bin') def is_english_fasttext(text): if not isinstance(text, str): return False # 预测语言,取top1结果 pred = model.predict(text, k=1) return pred[0][0] == '__label__en'
替换掉上面的is_english函数就行,速度会更快。
内容的提问来源于stack exchange,提问作者Seeamoebe
相关产品推荐
相关产品推荐

