用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]


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)



#显示词云
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的基本使用

你可能感兴趣的:(用Py做文本分析3:制作词云图)