使用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阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容