前言:大家好,这里是Seon塞翁。最近工作中开发了一个需要对大批量文本进行分词及统计词频的工具,主要是在 jieba 分词、过滤停用词两个环节耗时。分词部分可以考虑采用 jieba-fast 库提升速度,而过滤环节的效率低下问题一直没找到好方法解决,今天偶然发现了pandas可以帮助实现!果然还是太无知了哈哈哈…
1、常规方法
那么开始吧!首先完成分词部分,得到一个储存了所有单词的超大列表;
import pandas as pd
import jieba
stopwords = [line.strip() for line in open('chineseStopWords.txt', 'r', encoding='utf-8').readlines()]
df = pd.read_excel("/home/kesci/待分词文本.xlsx")
jieba_list = (jieba.cut(x) for x in list(df['内容'])) # 对每一行进行分词
cut_words = [w for words in jieba_list for w in words] # 所有行的分词汇总列表
循环判断分词是否在停用词列表中,乍一看这列表推导式已经很简洁了,在不使用多进程的情况下似乎没法更快了。
cut_word_list = [w for w in cut_words if w not in stopwords]
但实际上这竟然要耗费超过一分钟!这用户体验也太差了吧…
这是因为原始分词结果 cut_word_list
是超过 200 万个分词的列表,而停用词列表长度也超过 1000 个,如此一来需要经历的循环大大降低了过滤效率。
2、利用 pandas 中的 isin
利用 pandas 的内置方法 isin
可以对一列数据进行过滤,与 apply(lamba x: x if x not in stopwords)
或 for 循环这样的逐行逐个操作不同,使用 isin
进行的是向量化操作。
cut_df = pd.DataFrame({'cut_words':cut_words})
cut_df = cut_df[~cut_df.cut_words.isin(stopwords)] # 用isin的反函数过滤词
cut_word_list = cut_df['cut_words'].to_list()
可见执行速度是常规方法的100倍以上,如此一来便大幅提升了过滤效率。