用Py做文本分析3:制作词云图

1.词频统计

在词频统计之前,需要先完成分词工作。因为词频统计是基于分词后所构建的list进行的。

import jieba

#对小说文本第一回分词
word_list = jieba.lcut(chapter.txt[1])
word_list[:10]

['第一回', ' ', '风雪', '惊变', '钱塘江', '浩浩', '江水', ',', '日日夜夜', '无穷']

1.1使用Pandas统计

#使用pandas统计
#将数据放入DataFrame
import pandas as pd
df = pd.DataFrame(word_list, columns = ['word'])
df.head(10)

word
0   第一回
1   
2   风雪
3   惊变
4   钱塘江
5   浩浩
6   江水
7   ,
8   日日夜夜
9   无穷

#统计并降序排列
result = df.groupby(['word']).size()
print(type(result))
freqlist = result.sort_values(ascending=False)
freqlist[:10]

<class 'pandas.core.series.Series'>
word
,    2034
。     714
了     400
“     344
:     343
”     342
的     291
道     210
他     187
是     167
dtype: int6

1.2 使用NLTK统计

NLTK的生成结果为频数字典,可以被一些程序包直接调用

import nltk

#生成完整的词条频数字典
fdist = nltk.FreqDist(word_list)
fdist

#查看某词出现的次数
fdist['颜烈']

37

#列出词条列表
fdist.keys()


#频率分布表
fdist.tabulate(10)

   ,    。    了    “    :    ”    的    道    他    是 
2034  714  400  344  343  342  291  210  187  167 

#高频词汇Top10
fdist.most_common(10)

[(',', 2034),
 ('。', 714),
 ('了', 400),
 ('“', 344),
 (':', 343),
 ('”', 342),
 ('的', 291),
 ('道', 210),
 ('他', 187),
 ('是', 167)]

2.词云图

词云实际上是对分词结果频数表的图形化展示,使得浏览者能快速发现文本的核心内容。

常见的词云工具有:

  • Python

    • 生成比较标准的词云
    • 可以对背景图片进行修饰
  • R

    • 可以展示不同类别间的词云比较
    • 可以实现彩色动态效果的词云
    • 可以对背景图片进行修饰
  • Tableau

    • 可以实现词云结果的动态监测和展示

2.1wordcloud包安装

wordcloud包不太好安装,这里给一些攻略:
Anaconda 3.6安装wordcloud 词云出现问题
Anaconda安装jieba、wordcloud等第三方库

对于wordcloud,我们需要指定中文字体支持
WordCloud(font_path='xxx')
以上需要写字体文件所在的完整路径

2.2 wordcloud包用法

class wordcloud.WordCloud(
        font_path=None, 
        width=400, 
        height=200, 
        margin=2, 
        ranks_only=None, 
        prefer_horizontal=0.9,
        mask=None, 
        scale=1, 
        color_func=None, 
        max_words=200, 
        min_font_size=4, 
        stopwords=None, 
        random_state=None,
        background_color='black', 
        max_font_size=None, 
        font_step=1, 
        mode='RGB', 
        relative_scaling=0.5, 
        regexp=None, 
        collocations=True,
        colormap=None, 
        normalize_plurals=True)

常用功能:

  • font_path = None:字体路径,默认使用系统字体
  • width = 400 :宽度
  • height = 200:高度
  • max_words = 200:需要绘制的词条最大数目
  • stopwords = None:停用词列表

字体设定:

  • min_font_size=4 / max_font_size=None:字符大小范围
  • font_step=1:字号增加的步长
  • relative_scaling=0.5:词频和字号的换算关系
  • prefer_horizontal=0.9:词条水平显示的比例

颜色设定:

  • background_color='black':图形背景色
  • mode='RGB':图形颜色编码,如果指定为“RGBA”且背景色为None时,背景色为透明
  • color_func=None:生成新颜色的函数,使用matplotlib的colormap

背景掩模:

  • mask=None:词云使用过的背景图

用wordcloud绘制特定文本的词云时,需要用空格或标点符号对文本进行分隔,以便后续对文本进行分词处理

#对原始文本直接分词并绘制
import wordcloud
myfont = 'C:/Windows/Fonts/simkai.ttf'
text = 'this is hangzhou, 郭靖, 和, 哀牢山 三十六剑'
cloudobj = wordcloud.WordCloud(font_path = myfont).generate(text)
print(cloudobj)

<wordcloud.wordcloud.WordCloud object at 0x00000289345D7908>

#显示词云
import matplotlib.pyplot as plt
plt.imshow(cloudobj)
plt.axis('off')
plt.show()
image.png

说明:上图中没有‘this’,'is',‘和’是因为默认的停用表中包含上述词。

#优化词云
cloudobj = wordcloud.WordCloud(font_path = myfont,
                              width = 360, height = 180,
                              mode = 'RGBA', background_color = None).generate(text)
plt.imshow(cloudobj)
plt.axis('off')
plt.show()
image.png

最后我们保存一下词云

#保存词云
cloudobj.to_file('词云test.png')

接下来制作射雕英雄传第一章的词云

#射雕英雄传第一章词云
import pandas as pd
import jieba

stoplist_path = 'D:/Files/program data/nlp/PythonData/停用词.txt'
stoplist = list(pd.read_csv(stoplist_path, names = ['w'], sep = 'aaa',
                           encoding = 'utf-8', engine = 'python').w)

cloudobj = wordcloud.WordCloud(font_path = myfont,
                              width = 1200, height = 800,
                              mode = 'RGBA', background_color = None,
                              stopwords = stoplist).generate(' '.join(jieba.lcut(chapter.txt[1])))

plt.imshow(cloudobj)
plt.axis('off')
plt.show()

#保存图片
cloudobj.to_file('词云test2.png')
image.png

generate()操作背后实际上执行了两个函数

  • 调用分词函数process_text()
  • 调用基于频数的绘制函数fit_words()

fit_words(dict)

  • dict:由词条和频数构成的字典
#基于分词频数绘制词云
def m_cut(intext):
    return [w for w in jieba.cut(intext) if w not in stoplist]

import nltk
from nltk import FreqDist

tokens = m_cut(chapter.txt[1])
fdist = FreqDist(tokens)

cloudobj = wordcloud.WordCloud(font_path = myfont).fit_words(fdist)

plt.imshow(cloudobj)
plt.axis('off')
plt.show()
image.png

2.3词云美化

(1)设置背景图片
Mask 掩模/遮罩

  • 用于控制词云的整体形状
  • 设定Mask后,设定的高度和宽度值将被忽略,遮罩形状被指定图形的形状取代。除全白的部分仍然保留外,其余部分会用于绘制词云。因此背景图片的画布一定要设置为白色(#FFFFFF)
  • 字的大小,布局和颜色也会基于Mask生成
  • 必要时可以调整颜色来增强可视化效果
from scipy.misc import imread

def m_cut(intext):
    return [w for w in jieba.cut(intext) if w not in stoplist and len(w) >1]

cloudobj = wordcloud.WordCloud(font_path = myfont,
                              mask = imread('D:/Files/program data/nlp/PythonData/射雕背景1.png'),
                              mode = 'RGBA', background_color =None
                              ).generate(' '.join(m_cut(chapter.txt[1])))

plt.imshow(cloudobj)
plt.axis('off')
plt.show()
image.png

更换背景图片

from scipy.misc import imread

def m_cut(intext):
    return [w for w in jieba.cut(intext) if w not in stoplist and len(w) >1]

cloudobj = wordcloud.WordCloud(font_path = myfont,
                              mask = imread('D:/Files/program data/nlp/PythonData/射雕背景2.png'),
                              mode = 'RGBA', background_color =None
                              ).generate(' '.join(m_cut(chapter.txt[1])))

plt.imshow(cloudobj)
plt.axis('off')
plt.show()
image.png

对比下原图,出现不同的原因在于弓箭的弓背很细,词条和图不能很好的适配。因此在选择图片时要注意。


射雕背景2.png

(2)指定图片的色系
我们可以选择合适图片,将其色系运用在词云中。

import numpy as np

imgobj = imread('D:/Files/program data/nlp/PythonData/射雕背景2.png')
image_colors = wordcloud.ImageColorGenerator(np.array(imgobj))
cloudobj.recolor(color_func = image_colors)

plt.imshow(cloudobj)
plt.axis('off')
plt.show()
image.png

(3)指定单词组上色
理想的情况是分组比较词频,在两组中都高频的词条在图形中相互抵消。Python目前只能实现词条分组上色。

from wordcloud import get_single_color_func

class GroupedColorFunc(object):
    
    def __init__(self, color_to_words, default_color):
        self.color_func_to_words = [
            (get_single_color_func(color), set(words))
            for (color, words) in color_to_words.items()
        ]
        
        self.default_color_func = get_single_color_func(default_color)
        
    def get_color_func(self, word):
        try:
            color_func = next(
                color_func for (color_func, words) in self.color_func_to_words
                if word in words
            )
        except StopIteration:
            color_func = self.default_color_func
        
        return color_func
    
    def __call__(self, word, **kwargs):
        return self.get_color_func(word)(word, **kwargs)

color_to_words = {
    '#00ff00': ['颜烈', '武官', '金兵', '官兵'],
    'red': ['包惜弱', '郭啸天', '杨铁心', '丘处机']
}

default_color = 'grey'

grouped_color_func = GroupedColorFunc(color_to_words, default_color)
cloudobj.recolor(color_func = grouped_color_func)
plt.imshow(cloudobj)
plt.axis('off')
plt.show()
image.png

参考资料:
Python数据分析--玩转文本挖掘
自然语言处理NLTK之入门
wordCloud的基本使用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容