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()
说明:上图中没有‘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()
最后我们保存一下词云
#保存词云
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')
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()
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()
更换背景图片
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()
对比下原图,出现不同的原因在于弓箭的弓背很细,词条和图不能很好的适配。因此在选择图片时要注意。
(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()
(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()
参考资料:
Python数据分析--玩转文本挖掘
自然语言处理NLTK之入门
wordCloud的基本使用