三國人物出場詞頻統(tǒng)計

忽然想知道三國中到底誰是主角达椰,簡單使用 Python 分析一下看看项乒。最后畫一個詞云展示結論。

首先導入必要的包:

import jieba
from collections import Counter
from wordcloud import WordCloud

然后導入需要的電子版三國蝇裤,儲存在 txt 對象中频鉴,但是如果直接這樣調用的話十分占用內(nèi)存,我們采用一個可迭代對象分次導入垛孔。

關于這方面的說明詳見:http://www.reibang.com/p/968550b63f34

# 直接導入
with open('threekingdom.txt' ,'r', encoding='utf-8') as f:
    txt = f.read()
# 使用可迭代對象分次導入
def read_file(fpath): 
   BLOCK_SIZE = 1024 
   with open(fpath, 'r', encoding='utf-8') as f: 
       while True: 
           block = f.read(BLOCK_SIZE) 
           if block: 
               yield block 
           else: 
               return
            
txt = read_file('threekingdom.txt')

我先檢查一下是否導入成功

txt.__next__()

這個輸出還是很多截取了部分在這里:

'\n------------\n\n正文\n\n\n------------\n\n第一回 宴桃園豪杰三結義 斬黃巾英雄首立功\n\n 滾滾長江東逝水浪花淘盡英雄似炎。是非成敗轉頭空辛萍。\n\n 青山依舊在幾度夕陽紅。\u3000\u3000白漁樵江渚上慣\n\n 看秋月春風贩毕。一壺濁酒喜相逢仆嗦。古今多少事都付\n\n 笑談中。\n\n ——調寄《臨江仙》\n\n 話說天下大勢分久必合合久必分瘩扼。周末七國分爭并入于秦。及秦滅之后楚规辱、漢分爭又并入于漢栽燕。漢朝自高祖斬白蛇而起義一統(tǒng)天下后來光武中興傳至獻帝遂分為三國。推其致亂之由殆始于桓碍岔、靈二帝∮芘Γ桓帝禁錮善類崇信宦官。及桓帝崩靈帝即位大將軍竇武奈籽、太傅陳蕃共相輔佐。

導入沒問題爆捞,接下來是使用jieba.lcut()函數(shù)勾拉,將字符串分割成等量的中文詞語。下面插播一條廣告:

txt1 = '我來到北京清華大學'
setlist = jieba.lcut(txt1)
setlist
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\AppData\Local\Temp\jieba.cache
Loading model cost 1.719 seconds.
Prefix dict has been built succesfully.





['我', '來到', '北京', '清華大學']

從上面的例子可以看到輸入一個字符串藕赞,返回了一個等量的中文詞匯列表。

回到正題双霍,知道了這個函數(shù)的用法批销,我們來看看怎么把我們的這本《三國》全部分詞,并將全部詞匯列表命名為: world 均芽。

words = []
while True:
    words += jieba.lcut(txt.__next__())
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\AppData\Local\Temp\jieba.cache
Loading model cost 1.654 seconds.
Prefix dict has been built succesfully.



---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-3-9c577e6b04b4> in <module>
      1 words = []
      2 while True:
----> 3     words += jieba.lcut(txt.__next__())


StopIteration: 

上面的StopIteration并不是報錯他是可迭代對象全部迭代完成的標志。接下來我們需要統(tǒng)計一下每個詞出現(xiàn)的頻率深纲,因為是一個詞對應一個頻率劲妙,那么我們選擇內(nèi)置數(shù)據(jù)結構字典來儲存。

但是分詞十分多镣奋,因為我們要統(tǒng)計人名出現(xiàn)的次數(shù),所以我們其實只需要統(tǒng)計有兩個字或三個字的詞語即可富雅。

# 創(chuàng)建空字典
counts = {}
# 遍歷字典
for word in words:
    if len(word) == 1:
        continue
    else:
        # 往字典里增加元素
        counts[word] =counts.get(word, 0) + 1
        
# print(counts)

這個輸出也有點多肛搬,大概類似于這種:

{'正文': 1, '第一回': 1, '桃園': 19, '豪杰': 22, '結義': 14, '黃巾': 40, '英雄': 82, '立功': 22, '滾滾': 5, '長江': 25, '逝水': 1, '浪花': 1, '淘盡': 1, '是非成敗': 1, '轉頭': 2, '青山': 1, '依舊': 11, '幾度': 1, '夕...


這里面的'向子典里增加元素'是很巧妙的一步毕贼,我來解釋一下這步:

counts[word] =counts.get(word, 0) + 1

其實這個語句是比較復雜的counts['key'] = value, 舉一個栗子,如果此時的word是“曹操”(曹操一定會是主角9硌ⅰF》贰0菅怼)那么這一步就應該是:

counts['曹操'] = counts.get('曹操', 0) + 1

dic.get('key', 默認值)是一個字典函數(shù),它的作用是確定字典中是否存在某個 key 并獲取其 value志衍,如果沒找到這個 key 就返回默認值聊替。詳見:http://www.reibang.com/p/5d0bef1bc259

那么程序在執(zhí)行這一步的時候會在字典 counts 中尋找 key 值為‘曹操’的鍵值對,如果找到了把 value 加一惹悄,并更新 value。


我們趕快看看到底是誰出現(xiàn)的次數(shù)比較多:

items = list(counts.items())
items.sort(key=lambda x: x[1], reverse=True)
items

輸出大概類似于這種:[('曹操', 909),('孔明', 817),('將軍', 740),('卻說', 642),('玄德', 514),('關公', 507),('丞相', 483),('二人', 457),('不可', 427)('荊州', 419),('孔明曰', 385) ('不能', 380),('如此', 376),('玄德曰', 375),('商議', 341),('張飛', 339),('如何', 332),('主公', 326),('軍士', 307),('左右', 288),('軍馬', 288),('劉備', 268),('次日', 267),('引兵', 265),('大喜', 263),('呂布', 258),('孫權', 258),...

哈哈哈哈果然是曹操老哥暂殖,曹操老哥牛X当纱!等等先不要高興太早,這里面其實還有像‘劉備’惫东,‘玄德’,‘玄德曰’其實都是‘劉備’這個人颓遏,好的本著公平公正的原則就把他們都整合到一起吧滞时。

counts['孔明'] = counts.get('孔明') + counts.get('孔明曰')
counts['玄德'] = counts.get('玄德曰') + counts.get('玄德')
counts['玄德'] = counts.get('玄德') + counts.get('劉備')
counts['關公'] = counts.get('關公') + counts.get('云長')

我們看一下現(xiàn)在的 top 20是啥樣:

items[0:20]

輸出為[('曹操', 909),('孔明', 817),('將軍', 740),('卻說', 642),('玄德', 514),('關公', 507),('丞相', 483),('二人', 457),('不可', 427),('荊州', 419),
('孔明曰', 385),('不能', 380),('如此', 376),('玄德曰', 375),('商議', 341),('張飛', 339),('如何', 332),('主公', 326),('軍士', 307),('左右', 288)]

從上面的輸出中可以看出有很多無關的詞匯,真的我忍他們很久了B妗窒百!是時候對他們下手了!8萆摇!
首先創(chuàng)建一個無關詞字典,值得注意的是榴嗅,我們整合后的詞也成了無關詞就沒有必要再次計算了陶舞,還有就是我們的目標是統(tǒng)計前 10 的人物,所以不需要獲得全部的無關詞肿孵。

excludes = {"將軍", "卻說", "丞相", "二人", "不可", "荊州", "不能", "如此", "商議",
            "如何", "主公", "軍士", "軍馬", "左右", "次日", "引兵", "大喜", "天下",
            "東吳", "于是", "今日", "不敢", "魏兵", "陛下", "都督", "人馬", "不知",
            '玄德曰', '孔明曰', '劉備', '關公'}
for word in excludes:
        del counts[word]

我們重新排序來看看處理后的結果

items = list(counts.items()) # 將字典轉化為 元組的字典
items.sort(key=lambda x: x[1], reverse=True)
print(items[0:10])
[('孔明', 1202), ('玄德', 1157), ('曹操', 909), ('張飛', 339), ('呂布', 258), ('孫權', 258), ('趙云', 254), ('云長', 239), ('司馬懿', 221), ('周瑜', 215)]
items.sort(key=lambda x: x[1], reverse=True)
for i in range(10):
        character, count= items[i]  # 這是一個拆包操作
        print(character, count)
孔明 1202
玄德 1157
曹操 909
張飛 339
呂布 258
孫權 258
趙云 254
云長 239
司馬懿 221
周瑜 215

好吧颁井,恭喜孔明,玄德君成功反超雅宾。

再次插播多條廣告:

  • 統(tǒng)計出現(xiàn)頻次最高的前20個詞方法2
roles = Counter(counts)
role = roles.most_common(10)
print(role)
[('孔明', 1202), ('玄德', 1157), ('曹操', 909), ('張飛', 339), ('呂布', 258), ('孫權', 258), ('趙云', 254), ('云長', 239), ('司馬懿', 221), ('周瑜', 215)]

這是使用collections中的Counter()函數(shù),這個我還沒有仔細研究贯吓,詳細資料見http://www.pythoner.com/205.html

  • 注意items.sort(key=lambda x: x[1], reverse=True)中的 lambda 函數(shù)的使用
a = (1,2)
a[1]
2

廣告插播結束蜀变,好啦到現(xiàn)在基本上我們就分析的差不多啦,但是這樣的結果還是有點不直觀库北,我們來試試畫一個詞云:

# 構造詞云字符串
li = []
for i in range(10):
    character, count = items[i]
    for _ in range(count):
        li.append(character)
# print(li)
cloud_txt = ",".join(li)

測試一下emmmmm這個的輸出誰用誰知道,情屹,杂腰,

# 構造詞云字符串
wc = WordCloud(
    background_color='white', # 改變底色 默認為黑色
    font_path='msyh.ttc',
    # 是否包含兩個詞的搭配默認是True
    collocations=False
).generate(cloud_txt)
wc.to_file('三國中出現(xiàn)前十的人物.png')
詞云圖
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喂很,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子少辣,更是在濱河造成了極大的恐慌,老刑警劉巖漓帅,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件煎殷,死亡現(xiàn)場離奇詭異,居然都是意外死亡豪直,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門末融,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暇韧,“玉大人,你說我怎么就攤上這事懈玻。” “怎么了涂乌?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵湾盒,是天一觀的道長。 經(jīng)常有香客問我罚勾,道長,這世上最難降的妖魔是什么尖殃? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任分衫,我火速辦了婚禮,結果婚禮上蚪战,老公的妹妹穿的比我還像新娘。我一直安慰自己邀桑,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布贼急。 她就那樣靜靜地躺著,像睡著了一般空闲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碴倾,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天掉丽,我揣著相機與錄音,去河邊找鬼捶障。 笑死,一個胖子當著我的面吹牛担平,可吹牛的內(nèi)容都是我干的芥挣。 我是一名探鬼主播驱闷,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼空另,長吁一口氣:“原來是場噩夢啊……” “哼蹋砚!你這毒婦竟也來了扼菠?” 一聲冷哼從身側響起坝咐,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤墨坚,失蹤者是張志新(化名)和其女友劉穎秧饮,沒想到半個月后泽篮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡泼各,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年亏拉,在試婚紗的時候發(fā)現(xiàn)自己被綠了逆巍。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莽使。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖溪烤,靈堂內(nèi)的尸體忽然破棺而出庇勃,到底是詐尸還是另有隱情,我是刑警寧澤责嚷,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布掂铐,位于F島的核電站,受9級特大地震影響全陨,放射性物質發(fā)生泄漏。R本人自食惡果不足惜辱姨,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一雨涛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧替久,春花似錦、人聲如沸蚯根。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矩距。三九已至拗盒,卻和暖如春锥债,著一層夾襖步出監(jiān)牢的瞬間痊臭,已是汗流浹背登夫。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留恼策,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓分唾,卻偏偏與公主長得像狮斗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子碳褒,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348