第 8 章 文本数据可视化

大数据环境下,人们处理和理解海量信息的难度日益增大,传统的文本分析技术提取的信息已经无法满足人们的分析需求,将文本中复杂的或者难以通过文字表达的内容和规律以图表的形式表达出来,即文本数据的可视化处理,使人们能够快速获取大数据中所蕴含的的关键信息。

文本可视化技术综合了文本数据分析、数据挖掘、数据可视化等学科的理论和方法,是人们理解复杂的文本内容、结构和内在的规律等信息的有效手段。其中,文本数据分析是文本数据可视化的基础,通过文本数据分析将文本数据结构化处理并提取出关键信息后才能进一步进行灵活、直观的可视化操作。截止到目前为止的章节,已经介绍了文本数据结构化处理及分析的基本方法,本章将在此基础上对这些整合过的信息进行可视化展示。

对于不同的文本数据分析结果,可以有不同的可视化方式,比如对分词的结果进行词频统计后可以绘制词频相关的柱状图或者词云图、对文本聚类或者分类的结果可以绘制矩形树图、对于各种文本数据分析结果还可以结合时间信息判断其变动趋势,本章根据文本数据可视化对象的不同将文本数据可视化任务分为文本数据内容可视化、文本数据关系可视化及基于时间信息的文本数据可视化三类,具体内容安排如下:8.1 节主要介绍文本数据内容的可视化,包括词频柱状图和词云图;8.2 节讨论文本数据主题模型可视化;8.3 节结合时间信息对文本数据进行可视化处理,反映词频及话题随时间的变动情况,

8.1 文本数据内容可视化

文本内容可视化旨在快速展示文本的大致内容,快速直观的为文本阅读者提取文本内容的重点,对进一步进行复杂文本数据分析具有指导意义。最常用的是基于词频的可视化,其基本原理是:将文本看成词汇的集合,统计词汇出现的次数用以表现文本特征,进而用相关统计图表对词频进行展示,柱状图和词云(标签云)是两种常见的文本数据内容可视化形式。

8.1.1 柱状图

8.1.1.1 使用 matplotlib 绘制柱状图

matplotlib 是基于 Python 的二维绘图库,其中的 pyplot 模块提供了可以直接调用的编程接口支持 MATLAB 形式的绘图框架,该模块下定义的 bar 函数可以实现柱状图的绘制,调用方式为:bar(left, height, width=0.8, bottom=None, **kwargs)

参数说明:

left:柱状图中每个矩形左起点横坐标,取值为数值序列或者标量

height:柱状图中每个矩形的高度,取值为数值序列或者标量

其他部分参数:

width:柱状图中每个矩形的宽度,默认取值为 0.8

bottom:柱状图中每个矩形底边纵坐标

color:柱状图填充颜色,取值为标量或者数组

edgecolor:柱状图框线颜色

linewidth:柱状图框线宽度,默认取值为 None,使用默认宽度,取值为 0 时,不绘制框线

align:设置横坐标对齐方式,有以下两种取值:
(1)"center":横坐标位于柱状图每个矩形底边的中间位置 (2)"edge":横坐标位于柱状图每个矩形底边的左侧

orientation:设置柱状图的方向,有以下两种取值:
(1)"vertical":垂直方向 (2)"horizontal":水平方向 也可以通过函数 barh 直接绘制水平方向柱状图,相关参数说明见官方文档:http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.barh

label:图例标签

注意:color、edgecolor、linewidth 这些参数取值既可以常数也可以是长度为柱状图矩形个数的序列,取值为常数时,表示所有矩形参数取值一致,取值为序列时,可以为每个矩形设置不同的参数取值。

此外,在绘图过程中,为了增强图像的可读性、美观性,经常需要进行一些细节调整,可以利用 pyplot 模块下定义的这些函数:

@todo 补充表格

例 1


In [1]:import matplotlib.pyplot as plt
       %matplotlib inline # 执行该命令后,绘图时,可将图片嵌入 notebook 交互框,而不是单独弹出一个图片窗口
       import numpy as np

# 绘制柱状图

In [2]:fre_1 = (120, 95, 230, 35, 27) 
       fre_2 = (213, 130, 324, 100, 59) 
       index = np.arange(5)  
       plt.bar(index, fre_1,width=0.3,color="g",align="center",label="fre_1")
       plt.bar(index+0.3, fre_2,width=0.3,color="r",align="center",label="fre_2")
       plt.xlabel("category")
       plt.ylabel("fre")
       plt.text(2,330,"highest")
       plt.legend()
       plt.title("barplot")
Out[2]:@todo 补充图片 9.1.1.1

8.1.1.2 使用 Pandas 绘制柱状图

对于 Pandas 库的基本数据结构 Series 和 DataFrame ,可以直接调用其对应的 plot 方法绘制所需图像,本部分对数据结构并未做详细说明,而是重点讲解 Series 和 DataFrame 两种数据结构的柱状图的绘制,关于数据结构介绍读者可以阅读官方文档(http://pandas.pydata.org/pandas-docs/stable/dsintro.html)。

(1)绘制 Series 的柱状图

Series 可以用于存储任何类型的一维数据,其中的每一个数据都有自己的索引,构建 Series 使用 series 模块下的 Series 类即可实现,构建方式为:Series(data, index=index)

参数说明:

data:用于构建 Series 的数据,可以是列表、元组、数组、字典、标量

index:索引列表/数组或者 Index 对象,长度与参数 data 相同,取值必须唯一,如果不指定该参数,则默认赋予从 0 开始的索引

例 2


In [3]:data=(0,1,2)
       index=("a","b","c")
       pd.Series(data,index)
Out[3]:a    0
       b    1
       c    2
       dtype: int64
In [4]:pd.Series(data)
Out[4]:0    0
       1    1
       2    2
       dtype: int64

如果 data 为字典类型,不指定 index 参数时,则直接以字典中的键为索引构建 Series,如果指定 index 参数,则以 index 参数为基准对应字典键抽取相应的字典值,没有对应的参数则赋值为 NaN,具体可参见下例:

例 3


In [5]:pd.Series({"x":1,"y":2,"z":3})
Out[5]:x    1
       y    2
       z    3
       dtype: int64
In [6]:pd.Series({"x":1,"y":2,"z":3},index=["a","b","x","z"])
Out[6]:a    NaN
       b    NaN
       x    1.0
       z    3.0
       dtype: float64

data 参数取值为常数会出现什么情况呢?读者可以尝试生成,查看结果。

Series 中数据的索引方式与数组和字典类似,具体可以参见相关文档(http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing),本书在此不做过多说明。

在文本数据分析过程中,可以将分词、词频统计等结果统一保存为 Series 结构,对需要绘图的数据直接调用 plot 方法调用 matplotlib API 进行绘图,plot 方法的调用方式为:Series.plot(kind='line', ax=None, figsize=None, use_index=True, title=None, grid=None, legend=False, style=None, logx=False, logy=False, loglog=False, xticks=None, yticks=None, xlim=None, ylim=None, rot=None, fontsize=None, colormap=None, table=False, yerr=None, xerr=None, label=None, secondary_y=False, **kwds)

部分参数说明:

kind:绘制的图像类型,所支持的图像类型及对应的字符串取值如下: -'line':折线图 (默认取值)
-'bar':垂直方向柱状图
-'barh':水平方向柱状图
-'hist':直方图
-'box':箱线图
-'kde':概率密度估计图
-'density':与'kde'相同
-'area':堆叠面积图
-'pie':饼图

figsize:图片大小,取值为形如 (width, height) 的数组,分别表示图片的宽和高,单位为英寸

use_index:是否使用 index 取值作为图像横坐标,默认取值为 True

title:图片的名称

grid:是否在图片背景添加坐标网格线,默认取值为 False

例 4


In [7]:s = pd.Series(data=[13,10,14,9],index=["a","b","c","d"])
       s.plot(kind="bar",title="bar plot",grid=True)
Out[7]:<matplotlib.axes._subplots.AxesSubplot at 0x7f6efaec73d0>
@todo 补充截图 9.1.1.2-1

(2)绘制 DataFrame 的柱状图

DataFrame 是包含多列数据的二维数据结构,类似 excel 表格。构建 DataFrame 使用 frame 模块下的 DataFrame 类即可实现,构建方式为:DataFrame(data, index, columns)

参数说明:

data:用于构建 DataFrame 的数据,支持多种数据结构,可以是一维数组、列表、字典、Series 的字典(即命名了列名的一维数据,数据类型可以是数组、列表、字典、Series),或者二维数组,甚至是 DataFrame

index:行标签

columns:列标签

与 Series 类似,如果 data 为字典类型,不指定 index 和 columns 参数时,则直接以原有列标签和字典中的键为行列标签构建 DataFrame,如果指定 index 和 columns 参数,则对应抽取相应的值构成 DataFrame,没有对应的参数则赋值为 NaN,若不专门设定行标签,则默认赋予从 0 开始,具体可参见下例:

例 5


In [8]:s_1 = pd.Series(data=[1,2,3],index=["a","b","c"])
       s_2 = pd.Series(data=[4,5,6,7],index=["a","b","c","d"])
       pd.DataFrame({"x":s_1,"y":s_2})
Out[8]:@todo 补充图片 9.1.1.2-2
In [9]:pd.DataFrame({"x":s_1,"y":s_2},index=["b","c","d"])
Out[9]:@todo 补充图片 9.1.1.2-3
In [10]:pd.DataFrame({"x":s_1,"y":s_2},index=["b","c","d"],columns=["x","z"])
Out[10]:@todo 补充图片 9.1.1.2-4

除了将文本数据分析的结果统一保存为 Series ,也可以将多个结果汇总为 DataFrame 结构,筛选需要绘图的数据并调用 plot 方法绘图即可,plot 方法的调用方式为:DataFrame.plot(x=None, y=None, kind='line', ax=None, subplots=False, sharex=None, sharey=False, layout=None, figsize=None, use_index=True, title=None, grid=None, legend=True, style=None, logx=False, logy=False, loglog=False, xticks=None, yticks=None, xlim=None, ylim=None, rot=None, fontsize=None, colormap=None, table=False, yerr=None, xerr=None, secondary_y=False, sort_columns=False, **kwds)

大部分参数与 Series 相同,部分参数区别如下:

在使用数据框中某两列绘制图像时,使用 x、y 参数指定图形横纵坐标,其中:x 为横坐标数据的列标签,y 为纵坐标数据的列标签

kind:除了上面提到几种图像类型,DataFrame 还支持:

  - 'scatter':散点图  
  -  'hexbin':高密度散点图

subplots:是否为数据框中的每一列单独绘图,默认取值为 False

sharex/sharey:每一列单独绘图时,各个子图是否使用相同的横坐标/纵坐标

layout:输出子图的排列格式,取值类型为 (rows, columns) 的数组,其中 rows 为子图行数,columns 为子图列数

例 6


In [11]:s_1 = pd.Series(data=[1,2,3,4],index=["a","b","c","d"])
        s_2 = pd.Series(data=[4,5,6,7],index=["a","b","c","d"])
        df=pd.DataFrame({"x":s_1,"y":s_2})
        df.plot(kind="bar")
Out[11]:@todo 补充图片 9.1.1.2-5
In [12]:df.plot(kind="bar", subplots=True)
Out[12]:todo 补充图片 9.1.1.2-6
In [13]:df.plot(kind="bar", subplots=True, sharex=False, layout=(1,2))
Out[13]:todo 补充图片 9.1.1.2-7
In [14]:df["x"].plot(kind="bar")
Out[14]:todo 补充图片 9.1.1.2-8

(3)Series 文本数据处理方法

Series 支持一系列的方法,其中包括字符串处理方法 str ,类似 Python 字符串处理方法,下面介绍几种常用方法:

(3.1)cat 方法

cat 方法可以使用指定的分隔符号将 Series 中字符串进行连接,调用方式为:Series.str.cat(others=None, sep=None, na_rep=None)

参数说明:

others:有两种取值类型:
(1)None:默认取值,直接返回 Series 中字符串连接后形成的字符串 (2)字符串列表:将列表中的字符串与 Series 元素按照顺序对应连接,返回一个字符串 Series

sep:用于连接字符串的分隔符,取值类型为字符串,默认取值为 None

na_rep:有两种取值类型:
(1)None:默认取值,表示忽略 NA 值 (2)字符串:使用指定的字符串替换 NA 值

例 7


In [15]:pd.Series(['text','mining',np.nan,'python']).str.cat(sep=' ')
Out[15]:'text mining python'
In [16]:pd.Series(['text','mining',np.nan,'python']).str.cat(sep=' ',na_rep="?")
Out[16]:'text mining ? python'
In [17]:pd.Series(['text','with']).str.cat(others=['mining','python'],sep=',')
Out[17]:0    text,mining
        1    with,python
        dtype: object

(3.2)count 方法

count 方法用于统计某个字符串在 Series 各个字符串中出现的次数,调用方式为:Series.str.count(pat, flags=0, **kwargs)

参数说明:

pat:需要统计出现次数的字符串或者正则表达式

flags:当参数 pat 为正则表达式时,该参数用于设置正则表达式的匹配模式

例 8


In [18]:pd.Series(['text','mining','with','python']).str.count('t')
Out[18]:0    2
        1    0
        2    1
        3    1
        dtype: int64

(3.3)endswith 方法

当需要判断 Series 中字符串是否以某个字符串结尾时,可以调用 endswith 方法,调用方式为:Series.str.endswith(pat, na=nan)

参数说明:

pat:需要判断的末尾字符串

na:Series 中缺失值的返回形式,默认返回 nan

例 9


In [19]:pd.Series(['text','mining',np.nan,'python']).str.endswith ("ing")
Out[19]:0    False
        1     True
        2      NaN
        3    False
        dtype: object

(3.4)find 方法

find 方法可以返回指定字符串在 Series 各个字符串的起始位置,若不包含指定字符串则返回 -1,调用方式为:Series.str.find(sub, start=0, end=None)

参数说明:

sub:需要搜索位置的指定字符串

start:从字符串左侧开始索引

end:从字符串右侧开始索引

例 10


In [20]:pd.Series(['text','mining',np.nan,'python']).str.find ("t")
Out[20]:0    0.0
        1   -1.0
        2    NaN
        3    2.0
        dtype: float64

其他类似 Python 字符串处理方法可参加以下表格:

@补充表格

8.1.2 词云图

词云图将关键词按照一定的顺序和规则排列,以文字的大小代表词语的重要性,直观、快速地展示重要文本信息。

wordcloud 是较为常用的 Python 词云绘制包,利用其定义的 WordCloud 类即可实现词云图的绘制,此外还可以通过 ImageColorGenerator 类使用指定的图片定义词云图形状和颜色,下面将对这两个类的初始化方式及相关方法作重点介绍。

8.1.2.1 WordCloud 类

WordCloud 类的初始化方式为:实例 = WordCloud(font_path=None, width=400, height=200, margin=5, ranks_only=False, prefer_horizontal=0.9, mask=None, max_words=200, stopwords=None, random_state=None, background_color='black', max_font_size=None)

参数说明:

font_path:词云图使用的字体路径

width:画布宽度

height:画布高度

margin:画布边缘空白宽度

ranks_only:是否按照词汇的排序进行绘图,而不是词频,默认取值为 False

prefer_horizontal:词云图中词汇横向呈现与纵向呈现的比率

mask:用于绘制词云图的背景图片,取值类型为数组( scipy 的 imread 函数可以将图片转换为数组形式,后续会详细说明),若指定该参数,将忽略词云图原有宽度和高度设置,而直接使用图片形状,并且不会在白的背景位置绘制词汇

max_words:词云图中显示的最大词汇数

stopwords :不在词云图中显示的词汇集合

background_color:词云图背景颜色,默认取值为”black”

max_font_size:最大的字体大小,默认取值为 None,使用图片高度作为限制

WordCloud 类方法:

(1)fit_words

调用 fit_words 方法(或者 generate_from_frequencies 方法)可以根据词汇词频绘制词云图,调用方式为:实例.fit_words(frequencies),其中参数 frequencies 即为词频,其取值类型为列表,列表元素为包含词汇和相应词频的元组

例 11


In [21]:!pip install wordcloud # 安装 wordcloud 包
In [22]:import wordcloud
        cloud = wordcloud.WordCloud()
        frequencies = [("text",10),("mining",25),("with",2),("python",11)]
        cloud.fit_words(frequencies)
Out[22]:<wordcloud.wordcloud.WordCloud at 0x7f0ba2bea990>
In [23]:plt.imshow(cloud) # 在坐标轴上显示图像
        plt.axis("off") # 去除图像坐标轴
        plt.show() # 显示词云图
@todo 补充截图 9.1.2.1-1

(2)generate

generate 方法(或者 generate_from_text 方法)可以直接将文本数据展示为词云图,不必事先计算词频,调用方式为:实例.generate(text),参数 text 即为需要可视化展示的文本内容

例 12


In [24]:text="text mining with python , text visualization "
        cloud.generate(text)
Out[24]:<wordcloud.wordcloud.WordCloud at 0x7f0ba2bea990>
In [25]:plt.imshow(cloud)
        plt.axis("off")
        plt.show()
@todo 补充截图 9.1.2.1-2

(3)process_text

process_text 方法可以对文本进行分词处理,并自动过滤停用词,调用方式为:实例. process_text(text),其中参数 text 即为需要分词的文本,该方法可以直接返回分词结果以及对应的词频

例 13


In [26]:cloud.process_text("Good muffins cost $3.88\nin New York.  Please buy me two of them.\nThanks.")
Out[26]:[('Good', 1),
         ('Please', 1),
         ('two', 1),
         ('cost', 1),
         ('York', 1),
         ('muffins', 1),
         ('New', 1),
         ('buy', 1),
         ('Thanks', 1)]

(4)recolor

recolor 方法用于改变当前词云图的颜色,直接调用该方法比重新绘制词云图更快,调用方式为:实例.recolor(random_state=None, color_func=None)

参数说明:

random_state:随机配色方案种子,取值类型为整数,默认取值为 None

color_func:根据词频、字体等生成新配色的函数,若不设置,则默认使用 self.color_func

例 14


In [27]:cloud.recolor()
        plt.imshow(cloud)
        plt.axis("off")
        plt.show()
@todo 补充截图 9.1.2.1-3

In [28]:cloud.recolor(random_state=2)
        plt.imshow(cloud)
        plt.axis("off")
        plt.show()
@todo 补充截图 9.1.2.1-4

8.1.2.2 ImageColorGenerator 类

除了在绘图过程中选择不同的配色方案种子,也可以通过 ImageColorGenerator 类根据图片生成配色方案,词云图中的文字颜色由其所在图片位置的颜色决定,调用方式为:实例 = ImageColorGenerator(image),其中参数 image 为图片的数组形式。该实例可以当做配色函数传入 color_func 参数。

例 15

将配色图片(如下所示)上传到 notebook 文件夹,命名为“mask.jpg”,利用该图片对词云图进行配色调整

@补充图片 9.1.2.1-5


In [29]:from scipy.misc import imread

        # 使用 imread 函数将图片转换为数组形式
        mask = imread("mask.jpg") 

        # 将图片设置为词云图背景图片
        cloud = wordcloud. WordCloud(background_color="white", mask=mask) 

        # 使用 wikipedia “Text mining” 检索结果作为语料,绘制词云图
        text="Text mining, …… the information extracted."
        cloud.generate(text)
        plt.imshow(cloud)
        plt.axis("off")
        plt.show()
@补充图片 9.1.2.1-6

In [30]:image_colors = wordcloud.ImageColorGenerator(mask)

        # 使用图片颜色对词云图进行调色
        plt.imshow(cloud.recolor(color_func=image_colors))
        plt.axis("off")
        plt.show()
@补充图片  9.1.2.1-7

results matching ""

    No results matching ""