使用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
- 一张你喜欢的图片
再安装两个库
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
函数则保存文件到指定位置。