Python word_cloud 樣例 標簽雲系列(三)


轉載地址:https://zhuanlan.zhihu.com/p/20436642
word_cloud/examples at master · amueller/word_cloud · GitHub

上面是官方樣例。這一篇里的大部分嘗試都基於這些樣例進行修改。前提是你已經完成了安裝,依照上一篇修改了 FONT_PATH 。

還記得 http://zhuanlan.zhihu.com/666666/20432734 里提到的中文分詞方法吧,這次我們就不再贅述對文本的預處理了。有所不同的是,在上次的 pytagcloud 庫中我們要求傳入字典,而這次我們要求傳入數組。所以需要做一點小小的改動。

上一次我們是這么寫的:

 

wd = {}

fp=codecs.open("rsa.txt", "r",'utf-8');

alllines=fp.readlines();

fp.close();

for eachline in alllines:
    line = eachline.split('        ')
    #print eachline,
    wd[line[0]] = int(line[1])
print wd

這次我們需要將其中生成字典的部分變為數組:

 

# -*- coding: utf-8 -*-
import codecs
fp=codecs.open("rs300.txt", "r",'utf-8');

wd = []
alllines=fp.readlines();

fp.close();

for eachline in alllines:
    line = eachline.split('\\')
    line[1]=int(line[1])
    wd.append(line)
    #print eachline,

print wd

文本預處理好了以后,我們就可以開始對照樣例依葫蘆畫瓢,嘗試生成詞雲了。在此過程中會強調一些比較重要的方法,請自行對照上一篇的文檔理解。

 

word_cloud 生成詞雲有兩個方法。from text 和 from frequencies 。如果我們處理英文文檔的話,就可以直接使用第一個方法,而不需要提前預處理文本,由於我們要做的是中文文本,所以我們必須自己分詞,並處理為數組,使用第二種方法。

讓我們從一個最簡單的例子開始,也就是官方文檔的 simple.py

#-*- coding: utf-8 -*-
"""
Minimal Example
===============
Generating a square wordcloud from the US constitution using default arguments.
"""

from os import path
from wordcloud import WordCloud

d = path.dirname(__file__)

# Read the whole text.
 此處原為處理英文文本,我們修改為傳入中文數組
#text = open(path.join(d, 'constitution.txt')).read()
frequencies = [(u'知乎',5),(u'小段同學',4),(u'曲小花',3),(u'中文分詞',2),(u'樣例',1)]

# Generate a word cloud image 此處原為 text 方法,我們改用 frequencies 
#wordcloud = WordCloud().generate(text)
wordcloud = WordCloud().fit_words(frequencies)

# Display the generated image:
# the matplotlib way:
import matplotlib.pyplot as plt
plt.imshow(wordcloud)
plt.axis("off")

# take relative word frequencies into account, lower max_font_size
#wordcloud = WordCloud(max_font_size=40, relative_scaling=.5).generate(text)
wordcloud = WordCloud(max_font_size=40, relative_scaling=.5).fit_words(frequencies)
plt.figure()
plt.imshow(wordcloud)
plt.axis("off")
plt.show()

# The pil way (if you don't have matplotlib)
#image = wordcloud.to_image()
#image.show()

 

運行代碼得到結果:

長的很像我們在第一篇中輸出的結果。但是我們可以注意到,上次的結果如右圖,詞語間是不會發生嵌套的,而這次輸出的左圖,字間空隙也可以插入詞語了。

這一步成功以后起碼說明我們中文環境配好了,可以開始更深層次的嘗試了。

在下面的演示中,我為了節省力氣,會直接使用一些英文的文檔,這樣省去處理中文分詞的步驟。

大家在用的時候只要記得修改 FONT_PATH 、 utf-8 編碼、處理數據為數組格式使用 frequencies 方法這三點就可以了。

接下來我們來到 masked.py

如文件名所示,這一次我們要自定義遮罩形狀來生成真正的詞雲了!

根據文檔說明,遮罩圖片的白色部分將被視作透明,只在非白色部分區域作圖。於是我們找到一張黑白素材圖。



# -*- coding: utf-8 -*-
""""
Masked wordcloud
================
Using a mask you can generate wordclouds in arbitrary shapes.
"""

from os import path
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

from wordcloud import WordCloud, STOPWORDS

d = path.dirname(__file__)

# Read the whole text.
text = open(path.join(d, 'alice.txt')).read()

# read the mask image
# taken from
# http://www.stencilry.org/stencils/movies/alice%20in%20wonderland/255fk.jpg
alice_mask = np.array(Image.open(path.join(d, "huge.jpg")))

wc = WordCloud(background_color="white", max_words=2000, mask=alice_mask,
               stopwords=STOPWORDS.add("said"))
# generate word cloud
wc.generate(text)

# store to file
wc.to_file(path.join(d, "alice.png"))

# show
plt.imshow(wc)
plt.axis("off")
plt.figure()
plt.imshow(alice_mask, cmap=plt.cm.gray)
plt.axis("off")
plt.show()

 

如下圖:

 

圖做好了,可是總覺得哪里怪怪的。可能是顏色太過鮮艷吧,配色總感覺不是那么舒服,有沒有更逼格的處理?自然是有的。我們來到 a_new_hope.py

還是上面的圖,直接處理。

 

"""
Using custom colors
====================
Using the recolor method and custom coloring functions.
"""

import numpy as np
from PIL import Image
from os import path
import matplotlib.pyplot as plt
import random

from wordcloud import WordCloud, STOPWORDS


def grey_color_func(word, font_size, position, orientation, random_state=None, **kwargs):
    return "hsl(0, 0%%, %d%%)" % random.randint(60, 100)

d = path.dirname(__file__)

# read the mask image
# taken from
# http://www.stencilry.org/stencils/movies/star%20wars/storm-trooper.gif
mask = np.array(Image.open(path.join(d, "huge.jpg")))

# movie script of "a new hope"
# http://www.imsdb.com/scripts/Star-Wars-A-New-Hope.html
# May the lawyers deem this fair use.
text = open("a_new_hope.txt").read()

# preprocessing the text a little bit
text = text.replace("HAN", "Han")
text = text.replace("LUKE'S", "Luke")

# adding movie script specific stopwords
stopwords = STOPWORDS.copy()
stopwords.add("int")
stopwords.add("ext")

wc = WordCloud(max_words=1000, mask=mask, stopwords=stopwords, margin=10,
               random_state=1).generate(text)
# store default colored image
default_colors = wc.to_array()
plt.title("Custom colors")
plt.imshow(wc.recolor(color_func=grey_color_func, random_state=3))
wc.to_file("a_new_hope.png")
plt.axis("off")
plt.figure()
plt.title("Default colors")
plt.imshow(default_colors)
plt.axis("off")
plt.show()

 

 

這樣的灰調顏色比上面花花綠綠的感覺好多了。可是總不能老用黑白啊,需要色彩的時候怎么辦?最后一站我們來到 colored.py

為了突出我們鮮明且令人舒服的色調,我挑選了一幅小黃人的圖片進行處理。

 

#!/usr/bin/env python2
"""
Image-colored wordcloud
========================
You can color a word-cloud by using an image-based coloring strategy implemented in
ImageColorGenerator. It uses the average color of the region occupied by the word
in a source image. You can combine this with masking - pure-white will be interpreted
as 'don't occupy' by the WordCloud object when passed as mask.
If you want white as a legal color, you can just pass a different image to "mask",
but make sure the image shapes line up.
"""

from os import path
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator

d = path.dirname(__file__)

# Read the whole text.
text = open(path.join(d, 'alice.txt')).read()

# read the mask / color image
# taken from http://jirkavinse.deviantart.com/art/quot-Real-Life-quot-Alice-282261010
alice_coloring = np.array(Image.open(path.join(d, "xhr.jpg")))

wc = WordCloud(background_color="white", max_words=2000, mask=alice_coloring,
               stopwords=STOPWORDS.add("said"),
               max_font_size=40, random_state=42)
# generate word cloud
wc.generate(text)

# create coloring from image
image_colors = ImageColorGenerator(alice_coloring)

# show
plt.imshow(wc)
plt.axis("off")
plt.figure()
# recolor wordcloud and show
# we could also give color_func=image_colors directly in the constructor
plt.imshow(wc.recolor(color_func=image_colors))
plt.axis("off")
plt.figure()
plt.imshow(alice_coloring, cmap=plt.cm.gray)
plt.axis("off")
plt.show()

 

 



效果還可以,但是和我想的…不太一樣…我們嘗試調整一些參數。……當然,最佳效果可能需要很多次的嘗試才會出現。比如我將字號調大以后
就會出現一些……奇怪的輸出,難道是因為白色白的不夠純凈嗎。


總體上講這樣的配色已經比上面那種花花綠綠的配色好多了…至於為什么白色區域還會有詞語,我剛看了一下小黃人的原圖,
白色區域的確不完全是 255,255,255 ,應該是這個原因。

 

好了,到這里我們四幅樣例就都做完了。最后我發現缺少一張封面圖,那就再多來一張,順便嘗試一下 scale 參數。

我們嘗試在如下位置加入 scale 參數,設置為 1.5 倍。

wc=WordCloud(background_color="white",max_words=2000,mask=alice_coloring,stopwords=STOPWORDS.add("said"),max_font_size=40,random_state=42,scale =1.5 )

  

可以看到輸出的圖片的確是原圖的 2 倍。

 

再次強調使用 word_cloud 的幾個要點吧:

1、FONT_PATH

2、中文要實現分詞,輸出為數組,使用 frequencies 方法

3、scale 的用法,由於程序運行時間較長,如果生成大幅圖片會很慢,可以使用 scale 調節大小,但是會犧牲詞語對形狀的擬合度

 

到此標簽雲這一系列就能告一段落了。我們由中文分詞引入,為了可視化展示,試用了兩個標簽雲生成器。下面簡單總結比較一下 pytagcloud 和 word_cloud 的優點:

pytagcloud :

優點:依賴較少;可以同時添加多個字體,在代碼中選擇;提供相對完善的配色方案。

word_cloud:

優點:文字空隙可以嵌套詞語;支持自定義詞雲形狀;支持通過圖片上色。

缺點:依賴較多;程序運行較慢;默認顏色花花綠綠實在是丑…

 

最后談一下對做標簽雲的看法:

分詞、取詞是關鍵和基礎。圖片畢竟只是一個可視化的展示手段,內容更重要。分詞前要想清楚是否屏蔽某些詞性( jieba 提供這種功能,但是學習的還不透徹,以后可以專門記錄一些分詞的東西),分詞以后也可以手動刪除一些詞語,使重點突出。

遮罩圖片的選擇很重要。首先需要是大面積白底,否則會整張圖片鋪滿詞語。其次,圖片的顏色要豐富,最好能有漸變度,這樣的配色會很舒服。但是符合條件的圖片實在是太難找了…可遇而不可求。

最后,完美的圖片需要很多次地微調參數。詞語的數量,字體的大小等,都會對整張圖片的效果和詞雲形狀的擬合度產生影響。

 

這些只是對現有工具的簡單學習應用,並沒有什么創新與創造。

希望這幾篇文章能對感興趣的人有所幫助。

#這一篇主要是對官方樣例的重復,比較簡單,代碼也是現成的。圖片可以根據喜好自己去找,就不提供這次用到的文件了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM