用python实现词频分析+词云

在这里插入图片描述

2021.02.17更新

1.百度网盘链接

2.部分网友反应,用文章给出的代码分析文档的时候,有时会遇到如下的问题:

“ValueError: ‘zg’ is not in list”

这是因为“ zg”这个词性没有添加到#英文词性转中文词性字典这里面。程序发现分析文档中存在词性属于zg的词,但是我在程序里列出的字典中缺少这个词性的转换,所以就出问题了。

解决方法:在代码的#英文词性转中文词性字典里面添加上zg对应的转换就行,具体zg是什么百度一下就可。小花当时是把能查到的都写进去了,但是难免有几个词性查不到,谅解一下哈~如果出现类似的问题(比如“ValueError: ‘xxh’ is not in list”),也是把相应的词(如xxh)添加进去就行。
3.大家点个赞再收藏吧(点赞后观看,养成好习惯)TAT
在这里插入图片描述

前言

本文章也发表在了知乎平台上。两个平台的文章内容大致相同(但阅读体验是两种风格),大家可以按需所取。这里放上知乎文章的链接:知乎 丨小小花丨:用python实现词频分析+词云

如你所见。文章标题图是以 周杰伦的百度百科 词条为分析文档,以 周杰伦超话第一的那张图+PPT删除背景底色 为词频背景进行制作的(PPT真是个巨强的软件!我以后有时间一定会和大家分享的!)。这种词频分析、尤其是这种词云图,在这两年流行了起来。

但大家在制作的过程中可能总会这样或那样的问题:配色单调、收费、对中文的适配很差等等。而若我说,我可以免费给你一个软件,让你可以很方便地实现词频分析+词云生成(并且支持自定义);或者说,我可以免费教你自己写python来实现这些看起来很高大上的功能呢?
在这里插入图片描述
前几天总结2019年日记的时候,本想用一些词频统计软件/网站分析一下自己的2019年度关键词,结果发现能翻到的软件/网站要么只支持5w/10w字符以内文档的分析,要么就得乖乖掏钱才能进行无限制字数的分析……(是的我去年日记写了14w+字……)勤(jia)劳(jing)节(pin)俭(han)的我怎么可能就此认输!于是花了些时间自学python、写出了这个程序。在此分享给大家~ヾ(•ω•`)o

废话不多说,先上程序:程序理论支持无上限的字数分析(应该吧)。在运行程序后,会生成最高频的前100个字/词,并生成词云。分析文档、词云背景等都是支持用户自定义的,在文档“使用说明”中有更详细的介绍,这里就不再赘述。

放上百度云盘的链接,以飨读者。

词频分析(提取码:z344)

这篇文章主要是想分享一下自己所写的代码,毕竟程序是死的,代码是活的。大家若是学会了自己写或改代码,那就相当于拥有了更多自定义的权力。(python真的比C、C#等语言要好学呜呜呜QAQ,而且网上好多好多教程的)

在开始分享之前,我可以向大家保证,在网上真的很难找到比我的功能更完善、同时代码更美观且注释详细、同时还不收费的教程/软件了(要是找到了当我没说略略略)。开讲!

以下代码都是基于 python3.7 进行开发的。

正文

首先,安装所需的库。(当然,记得先安好python)

可以直接在cmd中(按下win+R,输入 cmd 后点确定)分别输入以下代码进行安装(部分可能已系统内置),也可以用其他方式进行安装。不过个人比较推荐通过cmd进行安装,毕竟cmd安装方便,不费事儿。

pip install re
pip install jieba
pip install collections
pip install numpy
pip install PIL
pip install wordcloud
pip install matplotlib.pyplot

安装完成后,就可以开心的敲代码啦~

在代码的开头,先进行一些定义

在程序的开头进行定义,是为了以后修改代码更加方便。当然,在凭空开始写程序的时候,可能自己也不清楚自己之后都需要定义哪些东西,所以这一步可以在边写代码时边在程序开头进行修改。

另外,在运行程序的时候,记得把程序运行所需文件放在程序的运行目录下

# 主要功能自定义设置
Analysis_text = '分析文档.txt'        # 分析文档
userdict = '用户词典.txt'             # 用户词典
StopWords = '停用词库.txt'            # 停用词库
number = 100                          # 统计个数
Output = '词频.txt'                   # 输出文件
background = '词频背景.jpg'           # 词频背景

然后是导入相关的库

这个没什么好说的,代码的注释中已经解释的很详细了。(我是按用到的库的先后顺序对安装库和导入库的顺序进行排序的哦,这样也许会更好理解一些)

# 导入扩展库
import re                           # 正则表达式库
import jieba                        # 结巴分词
import jieba.posseg                 # 词性获取
import collections                  # 词频统计库
import numpy                        # numpy数据处理库
from PIL import Image               # 图像处理库
import wordcloud                    # 词云展示库
import matplotlib.pyplot as plt     # 图像展示库(这里以plt代表库的全称)

在导入扩展库后,才是程序正文的开始。

工作的开头,当然是对所需分析文档进行读取

读取方式有很多种,这里选择用open这一种比较简洁的方式;在读取完成后,不要忘记close哦,这是一个好————————习惯!(或者用with语句)这里读取的文件“Analysis_text”是前文定义的“Analysis_text = ‘分析文档.txt’”。

# 读取文件
fn = open(Analysis_text,'r',encoding = 'UTF-8')  # 打开文件
string_data = fn.read()                          # 读出整个文件
fn.close()                                       # 关闭文件

读取完成后,对文本进行一些预处理

# 文本预处理
pattern = re.compile(u'\t|\n|\.|-|:|;|\)|\(|\?|"') # 定义正则表达式匹配模式(空格等)
string_data = re.sub(pattern, '', string_data)     # 将符合模式的字符去除

添加动态调整词典用户词典功能。这两个功能并不是必须的,大家可以根据个人需求决定是否使用。变量“userdict”是开头定义的“userdict = ‘用户词典.txt’”。

这两个功能的用处,是在自带词库的基础上、 根据动态调整词典/用户词典中的字/词对文档内容进行分词统计。若对程序自带词库的分词效果不尽满意, 可以在动态调整词典/用户词典中单独加入想要统计的词汇,以提高个别词汇识别成功率。格式为每行一个字/词。 比如:想统计“小小花”这个词的出现次数,但程序可能会将其分为“小小”“ 花”这两个词语分别进行统计;或是将“小小花”与前后文字/词一同进行统计,如“小小花朵”。 这时就可以在动态调整词典/用户词典中加入“小小花”一词,以提高识别成功率。

# 动态调整词典
jieba.suggest_freq('小小花', True)     #True表示该词不能被分割,False表示该词能被分割

# 添加用户词典
jieba.load_userdict(userdict)

进行分词

利用jieba词库进行分词。jieba词库在汉语语义分析中运用的十分广泛,上手也相对容易一点。更详细的相关介绍大家可以千度一下,我就不占地儿了。这里采用的是精确模式分词+使用HMM模型,可以将字/词划分的更加准确。

# 文本分词
seg_list_exact = jieba.cut(string_data, cut_all=False, HMM=True)    # 精确模式分词+HMM
object_list = []

去除停用词

对于停用词库中出现的词汇,程序不会进行统计。这个功能也不是必须的,大家可以根据个人需求决定是否使用。这里给出的停用词库是前面定义的“StopWords = ‘停用词库.txt’”,用的是常见的“Chinese stopwords”词库。这个词库在网上不太难找,懒得找的话也可以在我上面给出的链接中进行下载。

# 去除停用词(去掉一些意义不大的词,如标点符号、嗯、啊等)
with open(StopWords, 'r', encoding='UTF-8') as meaninglessFile:
    stopwords = set(meaninglessFile.read().split('\n'))
stopwords.add(' ')
for word in seg_list_exact:         # 循环读出每个分词
    if word not in stopwords:       # 如果不在去除词库中
        object_list.append(word)    # 分词追加到列表

进行词频统计

这里的“number”是前面定义的“number = 100”,具体数值大家也可以自己更改。词频统计也有很多种写法,但个人认为使用Couter进行统计更加简洁。

# 词频统计
word_counts = collections.Counter(object_list)       # 对分词做词频统计
word_counts_top = word_counts.most_common(number)    # 获取前number个最高频的词

然后是添加“英文词性转中文词性字典”

我在这个程序中加入了词性分析的功能,即识别当前字/词是形容词、动词还是名词等等。但jieba自带的词性分析输出结果为英文(a/v/n等),不便于用户直接阅读;因此我就在网上搜罗了一圈,自己花了点时间整理出来了这两个对照词典。

词典分为简洁版和详细版两个版本,大家按需所取。一般来说简洁版的就够用了,所以我在我的程序中使用的也是简洁版的转换。

# 英文词性转中文词性字典:简洁版
En2Cn = {
    'a'    : '形容词',
    'ad'   : '形容词',
    'ag'   : '形容词',
    'al'   : '形容词',
    'an'   : '形容词',
    'b'    : '区别词',
    'bl'   : '区别词',
    'c'    : '连词',
    'cc'   : '连词',
    'd'    : '副词',
    'e'    : '叹词',
    'eng'  : '英文',
    'f'    : '方位词',
    'g'    : '语素',
    'h'    : '前缀',
    'i'    : '成语',
    'j'    : '简称略语',
    'k'    : '后缀',
    'l'    : '习用语',
    'm'    : '数词',
    'mq'   : '数量词',
    'n'    : '名词',
    'ng'   : '名词',
    'nl'   : '名词',
    'nr'   : '名词',
    'nr1'  : '名词',
    'nr2'  : '名词',
    'nrf'  : '名词',
    'nrfg' : '名词',    
    'nrj'  : '名词',
    'ns'   : '名词',
    'nsf'  : '名词',
    'nt'   : '名词',
    'nz'   : '名词',
    'o'    : '拟声词',
    'p'    : '介词',
    'pba'  : '介词',
    'pbei' : '介词',
    'q'    : '量词',
    'qt'   : '量词',
    'qv'   : '量词',
    'r'    : '代词',
    'rg'   : '代词',
    'rr'   : '代词',
    'rz'   : '代词',
    'rzs'  : '代词',
    'rzt'  : '代词',
    'rzv'  : '代词',
    'ry'   : '代词',
    'rys'  : '代词',
    'ryt'  : '代词',
    'ryv'  : '代词',
    's'    : '处所词',
    't'    : '时间词',
    'tg'   : '时间词',
    'u'    : '助词',
    'ude1' : '助词',
    'ude2' : '助词',
    'ude3' : '助词',
    'udeng': '助词',
    'udh'  : '助词',
    'uguo' : '助词',
    'ule'  : '助词',
    'ulian': '助词',
    'uls'  : '助词',
    'usuo' : '助词',
    'uyy'  : '助词',
    'uzhe' : '助词',
    'uzhi' : '助词',
    'v'    : '动词',
    'vd'   : '动词',
    'vf'   : '动词',
    'vg'   : '动词',
    'vi'   : '动词',
    'vl'   : '动词',
    'vn'   : '动词',
    'vshi' : '动词',
    'vx'   : '动词',
    'vyou' : '动词',
    'w'    : '标点符号',
    'wb'   : '标点符号',
    'wd'   : '标点符号',
    'wf'   : '标点符号',
    'wj'   : '标点符号',
    'wh'   : '标点符号',
    'wkz'  : '标点符号',
    'wky'  : '标点符号',
    'wm'   : '标点符号',
    'wn'   : '标点符号',
    'wp'   : '标点符号',
    'ws'   : '标点符号',
    'wt'   : '标点符号',
    'ww'   : '标点符号',
    'wyz'  : '标点符号',
    'wyy'  : '标点符号',
    'x'    : '字符串',
    'xu'   : '字符串',
    'xx'   : '字符串',
    'y'    : '语气词',
    'z'    : '状态词',
    'un'   : '未知词',
}
# 英文词性转中文词性字典:详细版
En2Cn_Pro = {
    'a'    : '形容词',
    'ad'   : '形容词-副形词',
    'ag'   : '形容词-形容词性语素',
    'al'   : '形容词-形容词性惯用语',
    'an'   : '形容词-名形词',
    'b'    : '区别词',
    'bl'   : '区别词-区别词性惯用语',
    'c'    : '连词',
    'cc'   : '连词-并列连词',
    'd'    : '副词',
    'e'    : '叹词',
    'eng'  : '英文',
    'f'    : '方位词',
    'g'    : '语素',
    'h'    : '前缀',
    'i'    : '成语',
    'j'    : '简称略语',
    'k'    : '后缀',
    'l'    : '习用语',
    'm'    : '数词',
    'mq'   : '数量词',
    'n'    : '名词',
    'ng'   : '名词-名词性语素',
    'nl'   : '名词-名词性惯用语',
    'nr'   : '名词-人名',
    'nr1'  : '名词-汉语姓氏',
    'nr2'  : '名词-汉语名字',
    'nrf'  : '名词-音译人名',
    'nrfg' : '名词-人名',    
    'nrj'  : '名词-日语人名',
    'ns'   : '名词-地名',
    'nsf'  : '名词-音译地名',
    'nt'   : '名词-机构团体名',
    'nz'   : '名词-其他专名',
    'o'    : '拟声词',
    'p'    : '介词',
    'pba'  : '介词-“把”',
    'pbei' : '介词-“被”',
    'q'    : '量词',
    'qt'   : '量词-动量词',
    'qv'   : '量词-时量词',
    'r'    : '代词',
    'rg'   : '代词-代词性语素',
    'rr'   : '代词-人称代词',
    'rz'   : '代词-指示代词',
    'rzs'  : '代词-处所指示代词',
    'rzt'  : '代词-时间指示代词',
    'rzv'  : '代词-谓词性指示代词',
    'ry'   : '代词-疑问代词',
    'rys'  : '代词-处所疑问代词',
    'ryt'  : '代词-时间疑问代词',
    'ryv'  : '代词-谓词性疑问代词',
    's'    : '处所词',
    't'    : '时间词',
    'tg'   : '时间词-时间词性语素',
    'u'    : '助词',
    'ude1' : '助词-“的”“底”',
    'ude2' : '助词-“地”',
    'ude3' : '助词-“得”',
    'udeng': '助词-“等”“等等”“云云”',
    'udh'  : '助词-“的话”',
    'uguo' : '助词-“过”',
    'ule'  : '助词-“了”“喽”',
    'ulian': '助词-“连”',
    'uls'  : '助词-“来讲”“来说”“而言”“说来”',
    'usuo' : '助词-“所”',
    'uyy'  : '助词-“一样”“一般”“似的”“般”',
    'uzhe' : '助词-“着”',
    'uzhi' : '助词-“之”',
    'v'    : '动词',
    'vd'   : '动词-副动词',
    'vf'   : '动词-趋向动词',
    'vg'   : '动词-动词性语素',
    'vi'   : '动词-不及物动词(内动词)',
    'vl'   : '动词-动词性惯用语',
    'vn'   : '动词-名动词',
    'vshi' : '动词-“是”',
    'vx'   : '动词-形式动词',
    'vyou' : '动词-“有”',
    'w'    : '标点符号',
    'wb'   : '标点符号-百分号千分号,全角:% ‰ 半角:%',
    'wd'   : '标点符号-逗号,全角:, 半角:,',
    'wf'   : '标点符号-分号,全角:; 半角: ; ',
    'wj'   : '标点符号-句号,全角:。',
    'wh'   : '标点符号-单位符号,全角:¥ $ £ ° ℃ 半角 $',
    'wkz'  : '标点符号-左括号,全角:( 〔 [ { 《 【 〖 〈 半角:( [ { <',
    'wky'  : '标点符号-右括号,全角:) 〕 ] } 》 】 〗 〉 半角: ) ] { >',
    'wm'   : '标点符号-冒号,全角:: 半角: :',
    'wn'   : '标点符号-顿号,全角:、',
    'wp'   : '标点符号-破折号,全角:—— -- ——- 半角:—',
    'ws'   : '标点符号-省略号,全角:…… …',
    'wt'   : '标点符号-叹号,全角:! 半角:!',
    'ww'   : '标点符号-问号,全角:? 半角:?',
    'wyz'  : '标点符号-左引号,全角:“ ‘ 『',
    'wyy'  : '标点符号-右引号,全角:” ’ 』',
    'x'    : '字符串',
    'xu'   : '字符串-网址URL',
    'xx'   : '字符串-非语素字',
    'y'    : '语气词',
    'z'    : '状态词',
    'un'   : '未知词',
}

接下来的这一步最为关键,是把词频分析结果输出至工作台,并导出“词频.txt”文件

为使分析结果便于理解,首先输出/写入“\n词语\t词频\t词性”,并用破折号作为分割线进行划分。利用count计数,进行双重for循环:第一重for循环是获取前number个词语与其词频,第二重for循环是获取前number个词语的词性;若count≠number,则依次输出/写入词语、词频、词性,并将count+1;直到count=number,终止循环。

另外,输出文件“Output”是前文定义的“Output = ‘词频.txt’”,程序会在运行目录下创建文本文件并进行写入。

# 输出至工作台,并导出“词频.txt”文件
print ('\n词语\t词频\t词性')
print ('——————————')
fileOut = open(Output,'w',encoding='UTF-8')     # 创建文本文件;若已存在,则进行覆盖
fileOut.write('词语\t词频\t词性\n')
fileOut.write('——————————\n')
count = 0
for TopWord,Frequency in word_counts_top:                       # 获取词语和词频
    for POS in jieba.posseg.cut(TopWord):                       # 获取词性
        if count == number:
            break
        print(TopWord + '\t',str(Frequency) + '\t',list(En2Cn.values())[list(En2Cn.keys()).index(POS.flag)])                    # 逐行输出数据
        fileOut.write(TopWord + '\t' + str(Frequency) + '\t' + list(En2Cn.values())[list(En2Cn.keys()).index(POS.flag)] + '\n') # 逐行写入str格式数据
        count += 1
fileOut.close()                                                 # 关闭文件

其实若能实现上面所给出的所有代码,那就已经是一个较为完善的词频分析软件了。但是我觉得还不够,还要再做点什么。

于是加入了制作词云这一功能。

首先,输出“开始制作词云……”,提示用户系统当前运行状态。定义词频的背景,这里的“background”是前面定义的“background = ‘词频背景.jpg’”。调用wordcloud函数,对部分参数进行调整。最后利用plt函数进行词云的展示。

# 词频展示
print ('\n开始制作词云……')                    # 提示当前状态
mask = numpy.array(Image.open(background))      # 定义词频背景
wc = wordcloud.WordCloud(
    font_path = 'C:/Windows/Fonts/simfang.ttf', # 设置字体(这里选择“仿宋”)
    background_color='white',                   # 背景颜色
    mask = mask,                                # 文字颜色+形状(有mask参数再设定宽高是无效的)
    max_words = number,                         # 显示词数
    max_font_size = 150                         # 最大字号
)

wc.generate_from_frequencies(word_counts)                                        # 从字典生成词云
wc.recolor(color_func=wordcloud.ImageColorGenerator(mask))                       # 将词云颜色设置为背景图方案
plt.figure('词云')                                                               # 弹框名称与大小
plt.subplots_adjust(top=0.99,bottom=0.01,right=0.99,left=0.01,hspace=0,wspace=0) # 调整边距
plt.imshow(wc, cmap=plt.cm.gray, interpolation='bilinear')                       # 处理词云
plt.axis('off')                                                                  # 关闭坐标轴
print ('制作完成!')                                                             # 提示当前状态
print ('\n作者:丨小小花丨')
print ('日期:2020.01.16') 
plt.show()  

至此,一个词频分析的程序就基本完成啦!

最后!是加入一个小小的语句——

# 避免程序运行完成后直接退出
input()

在运行.py文件时,程序在运行完成后常常会“一闪而过”,很多时候是因为程序运行完了没事儿干了就自闭了。其实只要在代码的最后加上这样一句话就可以解决啦!
在这里插入图片描述

后记

以上就是我想分享的全部内容🤪不管是打算自己动手写代码的盆友,还是觉得我前文给出的软件就够用的筒子,都建议先运行一下那个链接中给出的程序、看看程序的实现效果是什么样子的,这有益于自己对程序的理解。如果程序尚有什么问题的话,或者有什么更好的idea的话,欢迎大家的评论或是私信!🥳

我也上传了一份.py格式的文件,大家有需要的话可以进行下载,在这里放上链接。

用python实现词频分析+词云.py

最后,祝大家学有所成!😛

  • 103
    点赞
  • 459
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丨小小花丨

喜欢的话点个赞呗,嘻嘻~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值