赞
踩
作者 | 苏克1900
来源 | 高级农民工
摘要: 当我们手中有一篇文档,比如书籍、小说、电影剧本,若想快速了解其主要内容是什么,则可以采用绘制 WordCloud 词云图,显示主要的关键词(高频词)这种方式,非常方便。本文将介绍常见的英文和中文文本的词云图绘制,以及 Frequency 频词频词云图。
接下来,将详细说明各种形式的词云图绘制步骤。
我们先绘制英文文本的词云图,因为它相对简单一些。这里以《海上钢琴师》这部电影的剧本为例。
首先,准备好电影剧本的文本文件(如下图):
接下来,我们绘制一个最简单的矩形词云图,代码如下:
- 1import os
- 2from os import path
- 3from wordcloud import WordCloud
- 4from matplotlib import pyplot as plt
- 5# 获取当前文件路径
- 6d = path.dirname(__file__) if "__file__" in locals() else os.getcwd()
- 7# 获取文本text
- 8text = open(path.join(d,'legend1900.txt')).read()
- 9# 生成词云
- 10wc = WordCloud(scale=2,max_font_size = 100)
- 11wc.generate_from_text(text)
- 12# 显示图像
- 13plt.imshow(wc,interpolation='bilinear')
- 14plt.axis('off')
- 15plt.tight_layout()
- 16#存储图像
- 17wc.to_file('1900_basic.png')
- 18# or
- 19# plt.savefig('1900_basic.png',dpi=200)
- 20plt.show()
这里,通过 open() 方法读取文本文件,然后在 WordCloud 方法中设置了词云参数,再利用 generate_from_text() 方法生成该电影剧本的词云,最后显示和保存词云图。十几行代码就可以生成最简单的词云图:
通过上面的词云图,你可能会发现有几点问题:
以上这些都是可以更改的,如果你想实现以上想法,那么需要先了解一下 WordCloud 的API 参数及它的一些方法。
这里,我们列出它的各项参数,并注释重要的几项:
- 1wordcloud.WordCloud(
- 2 font_path=None, # 字体路径,英文不用设置路径,中文需要,否则无法正确显示图形
- 3 width=400, # 默认宽度
- 4 height=200, # 默认高度
- 5 margin=2, # 边缘
- 6 ranks_only=None,
- 7 prefer_horizontal=0.9,
- 8 mask=None, # 背景图形,如果想根据图片绘制,则需要设置
- 9 scale=1,
- 10 color_func=None,
- 11 max_words=200, # 最多显示的词汇量
- 12 min_font_size=4, # 最小字号
- 13 stopwords=None, # 停止词设置,修正词云图时需要设置
- 14 random_state=None,
- 15 background_color='black', # 背景颜色设置,可以为具体颜色,比如white或者16进制数值
- 16 max_font_size=None, # 最大字号
- 17 font_step=1,
- 18 mode='RGB',
- 19 relative_scaling='auto',
- 20 regexp=None,
- 21 collocations=True,
- 22 colormap='viridis', # matplotlib 色图,可更改名称进而更改整体风格
- 23 normalize_plurals=True,
- 24 contour_width=0,
- 25 contour_color='black',
- 26 repeat=False)
关于更详细的用法,你需要到官网了解。
了解了各项参数后,我们就可以自定义想要的词云图了。比如更换一下背景颜色和整体风格,就可以通过修改以下几项参数实现:
- 1wc = WordCloud(
- 2 scale=2,# 缩放2倍
- 3 max_font_size = 100,
- 4 background_color = '#383838',# 灰色
- 5 colormap = 'Blues')
- 6# colormap名称 https://matplotlib.org/examples/color/colormaps_reference.html
结果如下:
接下来,我们提升一点难度,通过设置 StopWords 去掉没有实际意义的「ONE」字符,然后将词云图绘制在我们自定义的一张图片上。
代码实现如下:
- 1import os
- 2from os import path
- 3import numpy as np
- 4from wordcloud import WordCloud,STOPWORDS,ImageColorGenerator
- 5from PIL import Image
- 6from matplotlib import pyplot as plt
- 7from scipy.misc import imread
- 8import random
- 9
- 10def wc_english():
- 11 # 获取当前文件路径
- 12 d = path.dirname(__file__) if "__file__" in locals() else os.getcwd()
- 13 # 获取文本text
- 14 text = open(path.join(d,'legend1900.txt')).read()
- 15 # 读取背景图片
- 16 background_Image = np.array(Image.open(path.join(d, "mask1900.jpg")))
- 17 # or
- 18 # background_Image = imread(path.join(d, "mask1900.jpg"))
- 19 # 提取背景图片颜色
- 20 img_colors = ImageColorGenerator(background_Image)
- 21 # 设置英文停止词
- 22 stopwords = set(STOPWORDS)
- 23 wc = WordCloud(
- 24 margin = 2, # 设置页面边缘
- 25 mask = background_Image,
- 26 scale = 2,
- 27 max_words = 200, # 最多词个数
- 28 min_font_size = 4, # 最小字体大小
- 29 stopwords = stopwords,
- 30 random_state = 42,
- 31 background_color = 'white', # 背景颜色
- 32 max_font_size = 150, # 最大字体大小
- 33 )
- 34 # 生成词云
- 35 wc.generate_from_text(text)
- 36 # 等价于
- 37 # wc.generate(text)
- 38 # 根据图片色设置背景色
- 39 wc.recolor(color_func=img_colors)
- 40 #存储图像
- 41 wc.to_file('1900pro1.png')
- 42 # 显示图像
- 43 plt.imshow(wc,interpolation='bilinear')
- 44 plt.axis('off')
- 45 plt.tight_layout()
- 46 plt.show()
这里,首先通过 open() 方法读取文本文件,Image.open() 方法读取了背景图片,np.array 方法将图片转换为矩阵。
接着设置了词云自带的英文 StopWords 停止词,用来分割筛除文本中不需要的词汇,比如:a、an、the 这些。
然后,在 WordCloud 方法中,设置词云的具体参数。generate_from_text() 方法生成该词云,recolor() 则是根据图片色彩绘制词云文字颜色。最终的词云绘制效果如下:
现在,我们还是看到了显眼的「ONE」,下面我们将它去除掉,方法也很简单,几行代码就可以实现:
- 1# 获取文本词排序,可调整 stopwords
- 2process_word = WordCloud.process_text(wc,text)
- 3sort = sorted(process_word.items(),key=lambda e:e[1],reverse=True)
- 4print(sort[:50]) # 获取文本词频最高的前50个词
- 5# 结果
- 6[('one', 60), ('ship', 47), ('Nineteen Hundred', 43), ('know', 38), ('music', 36), ...]
- 7
- 8stopwords = set(STOPWORDS)
- 9stopwords.add('one')
首先,我们对文本词频进行排序,可以看到 「ONE」词频最高,就将它添加进 stopwords 中,这样就可以屏蔽该词从而不在词云中显示。
需要注意的是,这种手动添加停止词的方法适用于词数量比较少的情况。
另外,我们还可以将词云图颜色显示为黑白渐变色,也只需修改几行代码即可:
- 1def grey_color_func(word, font_size, position, orientation, random_state=None,
- 2 **kwargs):
- 3 return "hsl(0, 0%%, %d%%)" % random.randint(50, 100)
- 4 # 随机设置hsl色值
- 5wc.recolor(color_func=grey_color_func)
效果如下:
以上,就是英文词云图绘制的几种方法,下面我们介绍中文词云图的绘制。
相比于英文词云,中文在绘制词云图前,需要先切割词汇,这里推荐使用 jieba 包来切割分词。因为它可以说是最好的中文分词包了,GitHub 上拥有 160 K 的 Star 数。安装好 jieba 包后,我们就可以对文本进行分词然后生成词云。
这里,选取吴军老师的著作《浪潮之巅》作为中文文本的案例,仍然采用图片形式的词云图。素材准备好后,接下来就可以开始中文词云图绘制。
首先,需要读取文本文件,相比于英文,这里要添加文本编码格式,否则会报错,添加几行代码就可以识别文本的编码格式:
- 1text = open(path.join(d,'langchao.txt'),'rb').read()
- 2text_charInfo = chardet.detect(text)
- 3print(text_charInfo)
- 4# 结果
- 5{'encoding': 'UTF-8-SIG', 'confidence': 1.0, 'language': ''}
- 6text = open(path.join(d,r'langchao.txt'),encoding='UTF-8-SIG').read()
接着,对文本进行分词。jieba 分词有 3 种方式:精确模式、全模式和搜索引擎模式,它们之间的差别,可以用一个例子来体现。
比如,有这样的一句话:「"我来到北京清华大学"」,用 3 种模式进行分词,结果分别如下:
根据结果可知,我们应该选择「精确模式」来分词。关于 jieba 包的详细用法,可以参考 GitHub 仓库链接:
https://github.com/fxsjy/jieba
分词完成后,还需要设置 stopwords 停止词,由于 WordCloud 没有中文停止词,所以需要自行构造。这里可以采取两种方式来构造:
这种方法和前面的英文停止词构造的方法是一样的,目的是在词云图中不显示 stopwords 就行了 ,即先不设置 stopwords,而是先对文本词频进行排序,然后将不需要的词语添加为 stopwords 即可,代码实现如下:
- 1# 获取文本词排序,可调整 stopwords
- 2process_word = WordCloud.process_text(wc,text)
- 3sort = sorted(process_word.items(),key=lambda e:e[1],reverse=True)
- 4print(sort[:50]) # # 获取文本词频最高的前50个词
- 5
- 6[('公司', 1273), ('但是', 769), ('IBM', 668), ('一个', 616), ('Google', 429), ('自己', 396), ('因此', 363), ('微软', 358), ('美国', 344), ('没有', 334)...]
可以看到,我们先输出文本词频最高的一些词汇后,发现:「但是」、「一个」、「因此」这些词都是不需要显示在词云图中的。因此,可以把这些词用列表的形式添加到 stopwords 中,然后再次绘制词云图就能得出比较理想的效果,完整代码如下:
- 1import chardet
- 2import jieba
- 3text+=' '.join(jieba.cut(text,cut_all=False)) # cut_all=False 表示采用精确模式
- 4# 设置中文字体
- 5font_path = 'C:\Windows\Fonts\SourceHanSansCN-Regular.otf' # 思源黑体
- 6# 读取背景图片
- 7background_Image = np.array(Image.open(path.join(d, "wave.png")))
- 8# 提取背景图片颜色
- 9img_colors = ImageColorGenerator(background_Image)
- 10# 设置中文停止词
- 11stopwords = set('')
- 12stopwords.update(['但是','一个','自己','因此','没有','很多','可以','这个','虽然','因为','这样','已经','现在','一些','比如','不是','当然','可能','如果','就是','同时','比如','这些','必须','由于','而且','并且','他们'])
- 13
- 14wc = WordCloud(
- 15 font_path = font_path, # 中文需设置路径
- 16 margin = 2, # 页面边缘
- 17 mask = background_Image,
- 18 scale = 2,
- 19 max_words = 200, # 最多词个数
- 20 min_font_size = 4, #
- 21 stopwords = stopwords,
- 22 random_state = 42,
- 23 background_color = 'white', # 背景颜色
- 24 # background_color = '#C3481A', # 背景颜色
- 25 max_font_size = 100,
- 26 )
- 27wc.generate(text)
- 28# 获取文本词排序,可调整 stopwords
- 29process_word = WordCloud.process_text(wc,text)
- 30sort = sorted(process_word.items(),key=lambda e:e[1],reverse=True)
- 31print(sort[:50]) # 获取文本词频最高的前50个词
- 32# 设置为背景色,若不想要背景图片颜色,就注释掉
- 33wc.recolor(color_func=img_colors)
- 34# 存储图像
- 35wc.to_file('浪潮之巅basic.png')
- 36# 显示图像
- 37plt.imshow(wc,interpolation='bilinear')
- 38plt.axis('off')
- 39plt.tight_layout()
- 40plt.show()
stopwords 添加之前:
stopwords 添加之后:
可以看到,stopwords.update() 这种方法需要手动去添加,比较麻烦一些,而且如果 stopwords 过多的话,添加就比较费时了。下面介绍第 2 种自动去除 stopwords 的方法。
这种方法的思路也比较简单,主要分为 2 个步骤:
代码实现如下:
- 1# 对原文本分词
- 2def cut_words():
- 3 # 获取当前文件路径
- 4 d = path.dirname(__file__) if "__file__" in locals() else os.getcwd()
- 5 text = open(path.join(d,r'langchao.txt'),encoding='UTF-8-SIG').read()
- 6 text = jieba.cut(text,cut_all=False)
- 7 content = ''
- 8 for i in text:
- 9 content += i
- 10 content += " "
- 11 return content
- 12
- 13# 加载stopwords
- 14def load_stopwords():
- 15 filepath = path.join(d,r'stopwords_cn.txt')
- 16 stopwords = [line.strip() for line in open(filepath,encoding='utf-8').readlines()]
- 17 # print(stopwords) # ok
- 18 return stopwords
- 19
- 20# 去除原文stopwords,并生成新的文本
- 21def move_stopwwords(content,stopwords):
- 22 content_after = ''
- 23 for word in content:
- 24 if word not in stopwords:
- 25 if word != '\t'and'\n':
- 26 content_after += word
- 27
- 28 content_after = content_after.replace(" ", " ").replace(" ", " ")
- 29 # print(content_after)
- 30 # 写入去停止词后生成的新文本
- 31 with open('langchao2.txt','w',encoding='UTF-8-SIG') as f:
- 32 f.write(content_after)
网上有很多中文 stopwords 词库资料,这里选取了一套包含近 2000 个词汇和标点符号的词库:stopwords_cn.txt,结构形式如下:
遍历该 stopwords 词库,删除停止词获得新的文本,然后利用第一种方法绘制词云图即可。
首先输出一下文本词频最高的部分词汇,可以看到常见的停止词已经没有了:
1[('公司', 1462), ('美国', 366), ('IBM', 322), ('微软', 320), ('市场', 287), ('投资', 263), ('世界', 236), ('硅谷', 235), ('技术', 234), ('发展', 225), ('计算机', 218), ('摩托罗拉', 203)...]
词云图最终效果如下:
上面两种中英文词云图都是通过文本绘制的,而除了直接读入文本生成词云以外,比较常见的还有通过「词频」绘制词云图。这种词云图,则可以使用 DataFrame 或者 字典格式 来绘制。
下面,以此前我们爬过的一篇「近十年 世界大学排名 TOP500 强」教程的数据为例,介绍如何绘制词频词云图。
该份数据大小为 5001行 x 6 列,我们想根据各国 TOP 500 强大学的数量,来可视化地展示各国之间的大学数量差异。
- 1world_rank university score quantity year country
- 21 哈佛大学 100 500 2009 USA
- 32 斯坦福大学 73.1 499 2009 USA
- 43 加州大学-伯克利 71 498 2009 USA
- 54 剑桥大学 70.2 497 2009 UK
- 65 麻省理工学院 69.5 496 2009 USA
- 7...
- 8496 犹他州立大学 2018 USA
- 9497 圣拉斐尔生命健康大学 2018 Italy
- 10498 早稻田大学 2018 Japan
- 11499 韦恩州立大学 2018 USA
- 12500 西弗吉尼亚大学 2018 USA
这里,有两种方式可以直接生成频率词云图,第一种是 利用 Series 列表生成,代码实现如下:
- 1import pandas as pd
- 2import matplotlib.dates as mdate
- 3from wordcloud import WordCloud
- 4import matplotlib.pyplot as plt
- 5
- 6df = pd.read_csv('university.csv',encoding = 'utf-8')
- 7df = df.groupby(by = 'country').count()
- 8df = df['world_rank'].sort_values(ascending = False)
- 9print(df[:10])
- 10# 结果如下:
- 11country
- 12USA 1459
- 13Germany 382
- 14UK 379
- 15China 320
- 16France 210
- 17Canada 209
- 18Japan 206
- 19Australia 199
- 20Italy 195
- 21Netherlands 122
第二种方式是转换为 dict 字典生成,一行代码就可以完成:
- 1df = dict(df)
- 2print(df)
- 3# 结果如下:
- 4{'USA': 1459, 'Germany': 382, 'UK': 379, 'China': 320, 'France': 210,..}
数据转换好以后,就可以生成词云图了,代码实现如下:
- 1font_path='C:\Windows\Fonts\SourceHanSansCN-Regular.otf' # 思源黑
- 2wordcloud = WordCloud(
- 3 background_color = '#F3F3F3',
- 4 font_path = font_path,
- 5 width = 5000,
- 6 height = 300,
- 7 margin = 2,
- 8 max_font_size = 200,
- 9 random_state = 42,
- 10 scale = 2,
- 11 colormap = 'viridis', # 默认virdis
- 12 )
- 13wordcloud.generate_from_frequencies(df)
- 14# or
- 15# wordcloud.fit_words(df)
- 16plt.imshow(wordcloud,interpolation = 'bilinear')
- 17plt.axis('off')
- 18plt.show()
效果如下:
可以看到,美国最为突出,其次是德国、英国、中国等。看来,我们国内的大学还得加把劲啊。
以上,就是绘制词云图常见的几种方式。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。