文本可视化(一)——《今生今世》词云生成与小说分析

大数据

作者:Sinte-Beuve

好的数据可视化,可以使得数据分析的结果更通俗易懂。“词云”就是数据可视化的一种形式。给出一段文本的关键词,根据关键词的出现频率而生成的一幅图像,人们只要扫一眼就能够明白文章主旨。

最近在知乎、以及各大媒体上经常可以看到这个词云,刚好前段之间读了胡兰成的《今生今世》,所以就尝试着自己通过python来实现图云。碰巧的是,今天刚好也是张爱玲的诞辰。下面是最终生成的结果。图一为全词的图生成,背景是张爱玲的肖像,图二图三分别是散文集中出现的人名和地名。

大数据

下面主要来介绍一下词云生成的过程。顺便一提的是,现在也有很多在线的网站是可以直接生成词云的,只要把文字贴进去就可以了,例如图悦。但是,由于我选取的是二十世纪中期的作品,分析和提取关键词的过程有一定的复杂性,所以还是通过python来处理。

需要的工具

matplotlib
matplotlib,不用多讲,用python学习过机器学习的人都知道,是一个绘图库,最终词云的绘制需要用到它。jieba
jieba,最好用的开源中文分词工具。他最主要的两个功能是分词和关键词的抽取。在词云的生成过程中都需要用到。wordcloud
wordcloud是一个词云生成器,只要进行相关的配置就能生成相应的词云。

以上三个工具具体的使用方法,我会在参考文献中贴出来,这里就不花篇幅单独讲了,直接看《今生今世》的例子。

实现过程

实现的过程简单来讲,两步走,1. 提取关键词,2. 生成词云。

提取关键词

在使用jieba来提取关键词之前,我们需要考虑几个问题。比如说,

jieba是否能准确提取我们散文集中的关键词(人名、地名)?散文中会存在例如“我们”、“觉得”、“这样”这一类的词,这类词的出现导致了,散文集中真正的关键词无法被提取出来。散文中会存在例如“汪先生”,而jieba分词,将其分成“汪先生”和“先生”两个词,从而导致“先生”的频率远大于“汪先生”,从而对结果产生影响。

正是由于中文的复杂性,所以对关键词的提取带来了难度,好在jieba基本能够将上述问题解决。那么下面就是代码实现的过程了。

1. 解决问题1和问题3

jieba有内置词库,一些常见的人名地名,他是能够自己分辨出来了的。一些比较生僻的词可以通过自定义词库来添加进去,保证识别率。词典格式和dict.txt一样,一个词占一行;每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。file_name 若为路径或二进制方式打开的文件,则文件必须为 UTF-8 编码。例如,

应英娣 10 nr英娣 10 nr应小姐 10 nr范秀美 10 nr白相人 9 nr俞傅家 8 ns俞傅村 8 ns俞家 8 ns斯家 8 ns蕙兰中学 8 ns蕙兰 8 ns静安寺路 8 ns胡村 8 ns大楚报 6 nt苦竹 6 nt

自定义词典的词频一般在10左右,或者>10都可以。

然后在代码中通过代码引入即可。

jieba.load_userdict("namedict.txt")

2. 解决问题2

“我们”、“觉得”、“这样”这一类词语叫做停顿词,需要先处理。我们可以先去网上下载各大机构的停用词词库,然后应用到散文集中,由于停用词词库大多使用的是现在的文法,而《今生今世》创作时间比较早,有些可能还需要人为添加停顿词。

下面是去除停顿词的代码。

 def clean_using_stopword(text):    """    去除停顿词,利用常见停顿词表+自建词库    :param text:    :return:    """    mywordlist = []    # 用精确模式来分词    seg_list = jieba.cut(text, cut_all=False)    liststr = "/ ".join(seg_list)    with open(stopwords_path) as f_stop:        f_stop_text = f_stop.read()        f_stop_text = unicode(f_stop_text, 'utf-8')    f_stop_seg_list = f_stop_text.split('\n')    for myword in liststr.split('/'):  # 去除停顿词,生成新文档        if not (myword.strip() in f_stop_seg_list) and len(myword.strip()) > 1:            mywordlist.append(myword)    return ''.join(mywordlist)

经过以上两步的操作,就生成了一个新的文档,去除了停顿词。接下来就是提取关键词的时候了。

def extract_keywords():    """    利用jieba来进行中文分词。    analyse.extract_tags采用TF-IDF算法进行关键词的提取。    :return:    """    # 抽取1000个关键词,带权重,后面需要根据权重来生成词云    allow_pos = ('nr',) # 词性    tags = jieba.analyse.extract_tags(preprocessing(), 1000, withWeight=True)    keywords = dict()    for i in tags:        print("%s---%f" % (i[0], i[1]))        keywords[i[0]] = i[1]    return keywords

jieba.analyse.extract_tags()方法就是用来提取关键词的,参数依次为(文本,抽取关键词的数量,返回结果是否带权重,提取关键词的词性)。由于词云是需要根据权重来生成的因此withWeight为true。得到结果如下,对TF-IDF算法有了解的,应该知道这里的权重就是tf-idf。

汪先生---0.037881爱玲---0.032921这样---0.030461爱珍---0.025920日本---0.025699只觉---0.019628太太---0.019364

allowPOS=allow_pos可以提取指定词性的关键词,“nr”为人物名词,“ns”为地点名词。这样就可以生成散文集的人名词云和地点词云了。

大数据

生成词云

接下来就轮到wordcloud登场了。过程很简单,依次是

初始化WordCloud生成词云。
直接给出代码,
def draw_wordcloud():    """    生成词云。1.配置WordCloud。2.plt进行显示    :return:    """    back_coloring = plt.imread(bg_image_path)  # 设置背景图片    # 设置词云属性    wc = WordCloud(font_path=font_path,  # 设置字体                   background_color="white",  # 背景颜色                   max_words=2000,  # 词云显示的最大词数                   mask=back_coloring,  # 设置背景图片                   )    # 根据频率生成词云    wc.generate_from_frequencies(extract_keywords())    # 显示图片    plt.figure()    plt.imshow(wc)    plt.axis("off")    plt.show()    # 保存到本地    wc.to_file("wordcloud.jpg")

这里需要注意的,WordCloud默认生成的词云为矩形的,如果需要自定义词云的形状,需要提供一张二值化的图片,生成的词会填充图的黑色部分。

wordcloud对中文的支持不太好,需要自己设置字体,自己文件在项目中。ttf的字体可以去系统中提取。

完整的代码实现

代码可见我的github

# -*- coding: utf-8 -*-from __future__ import print_functionimport jieba.analyseimport matplotlib.pyplot as pltfrom wordcloud import WordCloudjieba.load_userdict("namedict.txt")# 设置相关的文件路径bg_image_path = "pic/image2.jpg" # 二值化图片text_path = 'jsjs.txt' # 《今生今世》文本font_path = 'msyh.ttf' # 字体stopwords_path = 'stopword.txt'# 函数体见上文def clean_using_stopword(text)def preprocessing():    """    文本预处理    :return:    """    with open(text_path) as f:        content = f.read()    return clean_using_stopword(content)    return content    # 函数体见上文def extract_keywords():if __name__ == '__main__':    draw_wordcloud()

提取的算法原理

jieba的jieba.analyse.extract_tags()用到的是自然语言处理当中非常常见的一个算法——TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆文件频率)算法。原理也比较容易看懂,有兴趣了解的,可以看下面的博客。

TF-IDF原理及使用TF-IDF与余弦相似性的应用(一):自动提取关键词

散文的分析

显然,爱玲是词云中最大的一个词,这就提现了,胡兰成是爱张爱玲的吗?或许也不见得吧,毕竟胡兰成总共有8个老婆,张只是其中之一。

小说三要素,人物、情节、环境。

人物,词云上基本已经可以很好的体现。最大的无疑是他的爱人和他的上司。其中贯穿了两条主线——政治和爱情。政治线上。汪精卫、李士群、周佛海提到的最多,都是大汉奸;爱情线上,胡兰成的8个老婆当中,有6个在词云上,玉凤、爱玲、秀美、一枝、爱珍、小周。

环境,这里就弱化成地名吧。最大的是胡村,他的出生地;日本,他了结余生的地方。当然也能梳理出一条他作为汉奸最后逃亡的路线。胡村—>杭州—>诸暨—>温州—>香港—>台湾—>日本


企业会员

免责声明:本网站内容主要来自原创、合作伙伴供稿和第三方自媒体作者投稿,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证有关资料的准确性及可靠性,读者在使用前请进一步核实,并对任何自主决定的行为负责。本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。任何单位或个人认为本网站中的网页或链接内容可能涉嫌侵犯其知识产权或存在不实内容时,应及时向本网站提出书面权利通知或不实情况说明,并提供身份证明、权属证明及详细侵权或不实情况证明。本网站在收到上述法律文件后,将会依法尽快联系相关文章源头核实,沟通删除相关内容或断开相关链接。

2017-10-23
文本可视化(一)——《今生今世》词云生成与小说分析
作者:Sinte-Beuve 好的数据可视化,可以使得数据分析的结果更通俗易懂。“词云”就是数据可视化的一种形式。给出一段文本的关键词,根据关键词的出现频率而

长按扫码 阅读全文

Baidu
map