首页 > 代码库 > Python word_cloud 样例 标签云系列(三)
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 codecsfp=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 pathfrom wordcloud import WordCloudd = 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 pltplt.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 pathfrom PIL import Imageimport numpy as npimport matplotlib.pyplot as pltfrom wordcloud import WordCloud, STOPWORDSd = 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.jpgalice_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 cloudwc.generate(text)# store to filewc.to_file(path.join(d, "alice.png"))# showplt.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 npfrom PIL import Imagefrom os import pathimport matplotlib.pyplot as pltimport randomfrom wordcloud import WordCloud, STOPWORDSdef 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.gifmask = 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 bittext = text.replace("HAN", "Han")text = text.replace("LUKE‘S", "Luke")# adding movie script specific stopwordsstopwords = 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 imagedefault_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 inImageColorGenerator. It uses the average color of the region occupied by the wordin a source image. You can combine this with masking - pure-white will be interpretedas ‘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 pathfrom PIL import Imageimport numpy as npimport matplotlib.pyplot as pltfrom wordcloud import WordCloud, STOPWORDS, ImageColorGeneratord = 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-282261010alice_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 cloudwc.generate(text)# create coloring from imageimage_colors = ImageColorGenerator(alice_coloring)# showplt.imshow(wc)plt.axis("off")plt.figure()# recolor wordcloud and show# we could also give color_func=image_colors directly in the constructorplt.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 提供这种功能,但是学习的还不透彻,以后可以专门记录一些分词的东西),分词以后也可以手动删除一些词语,使重点突出。
遮罩图片的选择很重要。首先需要是大面积白底,否则会整张图片铺满词语。其次,图片的颜色要丰富,最好能有渐变度,这样的配色会很舒服。但是符合条件的图片实在是太难找了…可遇而不可求。
最后,完美的图片需要很多次地微调参数。词语的数量,字体的大小等,都会对整张图片的效果和词云形状的拟合度产生影响。
这些只是对现有工具的简单学习应用,并没有什么创新与创造。
希望这几篇文章能对感兴趣的人有所帮助。
#这一篇主要是对官方样例的重复,比较简单,代码也是现成的。图片可以根据喜好自己去找,就不提供这次用到的文件了。
Python word_cloud 样例 标签云系列(三)