100毫秒过滤一百万字文本的停用词
作者簡介:小小明,Pandas數據處理專家,致力于幫助無數數據從業者解決數據處理難題。
之前有位群友分享了使用Pandas過濾停用詞的技巧:
不過其實這并不是效率最高的一種方法,今天我將演示一種更高效過濾停用詞的方法。
文章目錄
- 過濾停用詞前的準備工作
- 數據讀取
- jieba分詞器設置角色為特定詞匯
- 開始分詞
- 加載停用詞
- 過濾停用詞的n種方法性能對比
- 直接過濾
- 使用Pandas進行停用詞過濾
- 使用set集合過濾
- 速度最快的過濾方法
- 總結
過濾停用詞前的準備工作
這次我打算用一部197W字的小說作為數據示例。
數據讀取
首先,我們讀取這部小說的數據:
with open(r"D:\hdfs\novels\天龍八部.txt", encoding="gb18030") as f:text = f.read() print(len(text))結果:
1272432可見這部小說共127.2萬字。
下面我們對它進行分詞并加載停用詞:
jieba分詞器設置角色為特定詞匯
為了避免jieba分詞庫不能將主角正確的切詞,所以現在我們需要將這部小說的角色名稱加入到jieba的分詞表中。
首先,加載《天龍八部》小說的角色名稱:
with open('D:/hdfs/novels/names.txt', encoding="utf-8") as f:for line in f:if line.startswith("天龍八部"):names = next(f).split()breakprint(names[:20])前20個角色為:
['刀白鳳', '丁春秋', '馬夫人', '馬五德', '小翠', '于光豪', '巴天石', '不平道人', '鄧百川', '風波惡', '甘寶寶', '公冶乾', '木婉清', '包不同', '天狼子', '太皇太后', '王語嫣', '烏老大', '無崖子', '云島主']設置角色到特定詞匯中:
import jieba for word in names:jieba.add_word(word)提示了一些警告信息:
Building prefix dict from the default dictionary ... Loading model from cache C:\Users\Think\AppData\Local\Temp\jieba.cache Loading model cost 0.759 seconds. Prefix dict has been built successfully.開始分詞
然后對原始文本進行中文分詞:
%time cut_word = jieba.lcut(text) Wall time: 6 s中文分詞耗時6秒。
加載停用詞
然后加載停用詞:
# 加載停用詞 with open("stoplist.txt", encoding="utf-8-sig") as f:stop_words = f.read().split() stop_words.extend(['天龍八部', '\n', '\u3000', '目錄', '一聲','之中', '只見']) print(len(stop_words), stop_words[:10]) 5748 ['說', '人', '元', 'hellip', '&', ',', '?', '、', '。', '"']過濾停用詞的n種方法性能對比
直接過濾
%%time all_words = [word for word in cut_word if len(word) > 1 and word not in stop_words] print(len(all_words), all_words[:20])結果:
300656 ['釋名', '青衫', '磊落', '險峰', '玉壁', '月華', '馬疾香幽', '高人遠', '微步', '紋生', '誰家', '子弟', '誰家', '無計悔', '多情', '虎嘯', '龍吟', '換巢', '鸞鳳', '劍氣'] Wall time: 26.2 s直接過濾耗時26.2秒
使用Pandas進行停用詞過濾
%%time words = pd.Series(cut_word) all_words = words[(words.str.len() > 1) & (~words.isin(stop_words))].tolist() print(len(all_words), all_words[:20])結果:
300656 ['釋名', '青衫', '磊落', '險峰', '玉壁', '月華', '馬疾香幽', '高人遠', '微步', '紋生', '誰家', '子弟', '誰家', '無計悔', '多情', '虎嘯', '龍吟', '換巢', '鸞鳳', '劍氣'] Wall time: 465 ms耗時0.46秒
使用set集合過濾
%%time stop_words = set(stop_words) all_words = [word for word in cut_word if len(word) > 1 and word not in stop_words] print(len(all_words), all_words[:20])結果:
300656 ['釋名', '青衫', '磊落', '險峰', '玉壁', '月華', '馬疾香幽', '高人遠', '微步', '紋生', '誰家', '子弟', '誰家', '無計悔', '多情', '虎嘯', '龍吟', '換巢', '鸞鳳', '劍氣'] Wall time: 104 ms耗時0.1秒
速度最快的過濾方法
雖然我們過濾停用詞使用set集合過濾更快,但是我們并沒有考慮一開始分詞過程所消耗的時間,分詞耗時達到6秒的時間,有沒有辦法降低這個時間呢?
先看看使用set集合的情況,分詞過濾的整體耗時:
%%timeall_words = [word for word in jieba.cut(text) if len(word) > 1 and word not in stop_words] print(len(all_words), all_words[:20])結果:
300656 ['釋名', '青衫', '磊落', '險峰', '玉壁', '月華', '馬疾香幽', '高人遠', '微步', '紋生', '誰家', '子弟', '誰家', '無計悔', '多情', '虎嘯', '龍吟', '換巢', '鸞鳳', '劍氣'] Wall time: 5.91 s耗時5.9s秒。
但假如我們一開始就將停用詞從原始文本中去掉會不會更快點呢?
%%timetext_sub = text for stop_word in stop_words:text_sub = text_sub.replace(stop_word, " ") all_words = [word for word in jieba.cut(text_sub) if len(word) > 1] print(len(all_words), all_words[:20])結果:
174495 ['天龍', '釋名', '青衫', '磊落', '險峰', '玉壁', '月華', '馬疾香幽', '微步', '紋生', '子弟', '家院', '計悔', '虎嘯', '龍吟', '換巢', '鸞鳳', '劍氣', '碧煙', '水榭'] Wall time: 5.76 s整體耗時5.7秒。
速度稍微提升了一丁點兒,區別不大,結果差異還挺大,所以還是使用set集合來過濾比較好一點。
總結
綜上所述,中文分詞過濾停用詞時,使用set集合即可獲得最好的性能。
感謝各位讀者的陪伴,下期我們將分享 詞頻統計的3種方法 和 字典與集合的原理。
咱們不見不散,下期再見~
總結
以上是生活随笔為你收集整理的100毫秒过滤一百万字文本的停用词的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过piranha搭建lvs高可用集群
- 下一篇: TortoiseSVN右键没有菜单