使用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
方法。
??imshow
和show
的區別可以這樣理解,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.
效果展示
來,深入了解一下
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
bad 即使長得很帥也不行哦
??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
。
動手制作自己的中文詞云圖
提前準備
- 中文測試文本??社會主義核心價值觀
- 中文字體??
SourceHanSerifK-Light.otf
- 一張你喜歡的圖片
jiqimao.jpg
再安裝兩個庫
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
函數則保存文件到指定位置。