使用wordcloud制作精美詞云圖

使用wordcloud制作精美詞云圖

一個簡單的開始

安裝庫

>>>pip3 install wordcloud
>>>pip3 install matplotlib

??wordcloud用來繪制詞云圖,是今天的主角。
??matplotlib是python中的2D繪圖庫,如果看官不熟悉可以先移步了解一下,或者也可以直接看我對使用到的函數的簡單注釋。

示例

@python 3.6.7

from os import path

import matplotlib.pyplot as plt
from wordcloud import WordCloud

CURRENT_PATH = path.dirname(path.abspath(__file__))


def show():
    # 讀取本地test.txt文本,注意使用英文,中文后面會介紹
    file_path = path.join(CURRENT_PATH, 'test.txt')
    with open(file_path, 'r') as f:
        text = f.read()

    # 生成WordCloud對象,調用generate方法
    # windows下請選擇要使用的字體路徑
    # wordcloud = WordCloud(font_path='your_font_path').generate(text)
    wordcloud = WordCloud().generate(text)
    plt.imshow(wordcloud)  # 繪制傳入的wordcloud
    plt.axis('off')  # 傳入off,關閉坐標軸
    plt.show()  # 顯示圖片


if __name__ == '__main__':
    show()

??上面過程很好理解,唯一可能不熟悉的是兩個新庫的API。
??Wordcloud是一個類,有很多可以初始化的參數,這里全部采用默認的設置,然后調用generate方法。
??imshowshow的區別可以這樣理解,imshow將圖像繪制到內存,也就是說圖像已經繪制了,只是在內存沒有傳到顯示器,然后調用show呈現在顯示器上。

test.txt內容

A Lion lay asleep in the forest, his great head resting on his paws. A timid little Mouse came upon him unexpectedly, and in her fright and haste to get away, ran across the Lion's nose.

效果展示

figure1.png

來,深入了解一下

generate的遞進層次

??下面是wordcloud模塊中generate的調用過程源碼分析。


def generate(self, text):
    return self.generate_from_text(text)

??沒錯,generate方法就一行代碼,調用generate_from_text方法然后返回。有種被欺騙的感覺,不過因為是面向對象的設計也情有可原,畢竟方法名變短了O(∩_∩)O哈哈~。


def generate_from_text(self, text):
    words = self.process_text(text)
    self.generate_from_frequencies(words)
    return self

??generate_from_text先調用了process_text對英文單詞進行簡單分詞,返回的數據類型是字典,鍵是單詞,值是頻數。作者在這個函數里也說了有更好的方法來進行分詞和標記,所以在process_text的實現上也就沒有應有盡有。這也是為什么需要了解generate的層次,當你采用其它分詞技術后,也就不需要也不應該重頭調用generate
??所以generate_from_frequencies應當是你深入了解后常用的方法。generate_from_frequencies接受分詞后包含有詞匯頻數的字典,然后經過一系列轉化返回WordCloud對象,之后就能調用matplotlib.pyplot進行處理和顯示了。
??當然generate_from_frequencies也被封裝在fit_words方法下。不過如果直接調用generate_from_frequencies還有第二個參數max_font_size可選,它用來指定生成的詞云圖中字體的最大字號,默認為None


def fit_words(self, frequencies):
    return self.generate_from_frequencies(frequencies)

全方位認識WordCloud

??WordCloud含有眾多的可選參數,認識這些參數可以幫助你更好的創建完美的wordcloud詞云圖。
??font_path=None
??要使用的字體(OTF或TTF)的字體路徑。默認為None即使用Linux機器上的DroidSansMono路徑。如果你在另一個操作系統或者沒有此字體,您需要調整此路徑。這也是為啥最開始windows用戶需要自己動手找字體的原因了。

??width=400
??生成的圖像寬度,默認400

??height=200
??生成的圖像高度,默認200

??margin=2
??詞匯之間間距,默認為2。

??ranks_only=None
??已經棄用,沒有效果。

??prefer_horizontal=.9
??原文翻譯為嘗試水平擬合的次數與垂直擬合的次數之比。白話一點就是這個值小于1(默認為0.9),就會嘗試旋轉那些不適合水平方向的詞匯為豎直方向;如果大于等于1的話就沒有詞匯豎直顯示的效果,但即使設置為0也不會讓所有詞匯都豎直顯示。

??mask=None
??當使用自己的圖片來制作詞云圖的時候就需要這個參數,默認為None。這個參數是一個多維數組,需要使用其它庫來將自己路徑中的圖像轉化為數組。一旦使用mask后,之前設定的高和寬都將忽略而采用圖像的形狀。如果想要自己的詞匯能夠被明確的繪制成圖片的圖形形狀,那么請采用白底圖片。因為只有白色的背景(#FF or #FFFFFF)會被忽略,否則如果背景色彩不是純白的話那么繪制出來的就是一個矩形。

nice

alice_color.png

bad 即使長得很帥也不行哦

pengyuyan.jpg

??scale=1
??計算和繪圖之間的縮放,默認為1。也就是說如果你想要更大的詞云圖,使用這個進行調試比使用更大的圖像作為mask更好,這樣圖形變大,字體會更清晰。不過可能會造成粗糙的詞匯匹配。

??color_func=None
??生成顏色的函數,默認為None,使用自帶的顏色生成函數。比如可以使用color_func=lambda *args, **kwargs: "white"來使字體變成白色。這個參數用法比較多,有興趣的看官可以再深入研究。

??max_words=200
??使用詞匯的最大數量,默認為200。

??min_font_size=4
??最小的字體號,默認為4,沒有空間繪制這號字體時就停止。直白一點,不繪制比這還小的字。

??stopwords=None
??繪制時忽略的詞匯,默認為None即使用內置的停用詞匯表。如果直接使用generate_from_frequencies方法則會忽略這個參數。(stopwords只在process_text方法中被使用。)

??random_state=None
??用來生成隨機對象,默認為None。這個參數主要是為color_func等一些顏色設置方法服務的。

??background_color='black'
??詞云圖的背景顏色,默認為black

??max_font_size=None
??最大的字體號,如果傳入None即默認為圖像的高度。

??font_step=1
??字體步長,默認為1。加大這個值會加快計算速度,但會造成粗糙的詞匯匹配。

??mode="RGB"
??顏色模型,默認為RGB。如果傳入RGBA并且設置background_color=None,那么生成的詞云圖背景將會變成透明。

??relative_scaling='auto'
??設置字體頻率對字體大小的影響。設置為0,那么只考慮詞匯順序;設置為1,那么頻率是兩倍,大小就是兩倍。默認為auto,即設置為0.5,次序和頻率兩者兼顧。但是如果repeat=True,那么就只會被設置為0。

??regexp=None
??正則匹配,只在process_text方法中被使用,默認為None則使用r"\w[\w']+"來進行正則匹配單詞。直接使用generate_from_frequencies則會忽略這個參數。

??collocations=True
??是否包含兩個單詞的搭配(bigrams),默認為True。同樣這個參數只在process_text中被使用。如果直接使用generate_from_frequencies則會忽略這個參數。

??colormap=None
??matplotlib顏色映射,為每個單詞隨機繪制顏色,默認為None即使用viridis。感興趣的看官可以到網上搜索更多的colormap種類來挑選自己最喜愛的那一款。另外如果指定了color_func參數值,則會忽略這個參數。

??normalize_plurals=True
??是否從單詞中刪除尾隨的“s”,默認為True。如果出現帶有或不帶有尾隨“s”的單詞,則將帶有尾隨“s”的刪除并將其計數添加到沒有尾隨“s”的單詞中——除非單詞是以'ss'結尾。當然了這個參數也是只在process_text中使用,如果直接使用generate_from_frequencies則會忽略這個參數。

??contour_width=0
??默認為0,如果采用了mask,并且傳遞參數大于0,那么就會繪制圖形輪廓,數值大小代表厚度。

??contour_color='black'
??繪制圖形輪廓使用的顏色,默認為black

??repeat=False
??是否重復使用詞匯,直到達到最大的詞匯數量或者最小字體號沒有空間不能被繪制為止,默認為False。

常用API認識,之前沒介紹到的

??to_image(self)
??返回PIL.Image.Image對象。

??recolor(self, random_state=None, color_func=None, colormap=None)
??對圖形重新著色。重新上色會比重新生成整個詞云圖快很多。有三個可選的參數random_state=None, color_func=None, colormap=None,和我們之前介紹的含義一樣。它們默認值都是None,意味著會如果不傳遞參數便使用內部自己定義的初始值。

??to_file(self, filename)
??將生成的圖像保存到指定路徑,參數為文件路徑加上文件名。

??to_array(self)
??內部會調用to_image(self),然后將得到的PIL.Image.Image對象轉化為numpy array

動手制作自己的中文詞云圖

提前準備

再安裝兩個庫

pip3 install jieba

??結巴是現在比較火的中文分詞庫,用法也比較簡單。

pip3 install scipy

??雖然matplotlib.pyplot也有圖像讀取的API,但是在讀取某些圖像的時候會使用浮點數進行存儲,此時wordcloud就會提示浮點數錯誤。所以我們在這里再安裝另外一個圖像讀取庫。

好,開始寫代碼

@python 3.6.7
# -*- coding: utf-8 -*-

from os import path

from wordcloud import WordCloud
import matplotlib.pyplot as plt
from scipy.misc import imread
import jieba.analyse

CURRENT_PATH = path.dirname(path.abspath(__file__))
TEXT_FILE = path.join(CURRENT_PATH, 'Chinese.txt')
IMG_FILE = path.join(CURRENT_PATH, 'jiqimao.jpg')
FONT_PATH = path.join(CURRENT_PATH, 'SourceHanSerifK-Light.otf')


def get_frequencies():
    # use jieba to get Chinese frequencies
    # 'topK' is the max words need to return
    # 'withWeight=True' means return frequencies
    with open(TEXT_FILE, 'r') as f:
        text = f.read()
    words = jieba.analyse.extract_tags(text, topK=200, withWeight=True)
    # words is list, change it to dict
    return dict(words)


def make_wordcloud(words):
    # get mask
    my_mask = imread(IMG_FILE)

    # set wordcloud
    my_wordcloud = WordCloud(
        font_path=FONT_PATH,
        background_color='white',
        mask=my_mask,
        max_font_size=68,
        min_font_size=8,
        contour_width=2,
        contour_color='steelblue'
    )
    # words must be dict
    my_wordcloud.generate_from_frequencies(words)

    return my_wordcloud


def show_it(wordcloud):
    # show it
    plt.imshow(wordcloud)
    plt.axis('off')
    plt.show()


def save_it(wordcloud, name):
    # save in current path
    filename = '{}.jpg'.format(name)
    wordcloud.to_file(path.join(CURRENT_PATH, filename))


if __name__ == '__main__':
    words = get_frequencies()
    wordcloud = make_wordcloud(words)
    show_it(wordcloud)
    save_it(wordcloud, 'my_wordcloud')

??整個流程比較直白,我們先將所有的準備文件都放在當前目錄下。在get_frequencies函數中使用jieba進行分詞,jieba.analyse.extract_tags會從指定文本中提取關鍵詞,topK指定提取的詞匯數量,withWeight=True會返回詞匯的頻數。注意這里最終返回的words是列表,需要使用dict將其轉化為字典后才能傳遞給generate_from_frequencies使用。
??后面的步驟就比較常規了,make_wordcloud函數中使用imread讀取圖像,然后設置wordcloud參數,并繪制輪廓,最后調用generate_from_frequencies進行生成。
??接下來,show_it函數會展示成果,save_it函數則保存文件到指定位置。

效果展示

my_wordcloud.jpg
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容