Python大数据与机器学习实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

4.1 Matplotlib绘图库

Matplotlib是Python最著名的图表绘制库,支持很多绘图工具,可以从其官网中看到大量的图表及对应的使用方法。本节不尽数所有方法和参数,而是从功能的角度出发,介绍在数据分析时最常用的方法及使用场景。

4.1.1 准备工作

1.安装软件

安装Matplotlib库,注意在Python 2的环境下,需要指定安装Matplotlib 3.0以下版本,同时安装python-tk软件包。在Ubuntu系统中,执行以下命令:

2.包含头文件

使用Matplotlib库需要包含头文件,例程中还使用了Numpy库。在4.1节中所有示例都需要包括以下头文件,在此统一说明,后续例程中省略。

另外,如果使用Jupyter Notebook编写程序,还需要加入:

以保证图片在浏览器中正常显示。

4.1.2 散点图与气泡图

1.散点图

Matplotlib的pyplot模块提供了类似MATLAB的绘图接口,其中plot函数最为常用。它支持绘制散点图、线图,本例中使用plot函数绘制散点图。

程序运行结果如图4.2所示。

图4.2 绘制散点图

在本例程中,随机生成了50个点,并利用plot函数生成图像,其中参数'o'指定生成图像为散点图(默认为线图)。

散点图通常用于展示数据的分布情况,即xy的关系。在数据分析中,最常用的场景是将两维特征分别作为x轴和y轴,通过散点图展示二者的相关性,相关性将在4.2节中详细讨论。

2.气泡图

气泡图的绘制函数scatter也常被用于绘制上例中的散点图。相对于plot函数,scatter函数提供更强大的功能,支持指定每个点的大小及颜色,可以展示更多维度的信息。

程序运行结果如图4.3所示。

图4.3 绘制气泡图

在例程中,由于用参数s指定每个图点面积的大小、用参数c指定每个点的颜色,因此,图中可以展示四个维度的信息。但在实际应用中,一张图中四个维度携带的信息量太大,更多的时候仅使用x轴,y轴及面积大小这三个维度。

4.1.3 线图

线图常用于展示当x轴数据有序增长时,y轴的变化规律。

1.对比线图

本例也使用了plot函数进行绘制,不同的是绘制线图可在同一张图中展示两条曲线,可看到对比效果。

程序运行结果如图4.4所示。

图4.4 绘制对比线图

与散点图不同的是,线图把数组中前后相邻的点连接在一起。当数据在x轴方向未被排序时,图示看起来比较混乱,如图4.5中的左图所示。在这种情况下,建议先排序后作图,结果如图4.5中的右图所示。

图4.5 对x轴数组排序前后对比图

2.时序图

线图的另一个常见应用场景是绘制时序图,从时序图中可以直观地看出整体趋势、时间周期,以及特殊日期带来的影响。在绘制时序图时,x轴一般为时间类型数据。

程序运行结果如图4.6所示。

图4.6 绘制时序图

绘图前使用pd.to_datetime函数将字符型的日期转换成日期时间类型,绘制时用gca函数和gcf函数设置当前绘图区域时间格式和旋转角度,绘图区域相关概念将在4.1.7节中详细介绍。除了可以用autofmt_xdate方法自动调整旋转角度,还可以使用rotation参数手动设置旋转的具体角度,形如:

4.1.4 柱图

柱图、条形图、堆叠图和直方图都属于柱图范畴,柱图的核心功能在于对比柱与柱之间的关系,常用于统计中。例如,常用直方图描述单个变量值的分布情况,也可在不同分类之下用柱图描述各个类别的计数、均数或者数据之和,以对比类间的差异。

1.柱图

本例中使用bar函数绘制普通柱图,其横坐标可以是数值,也可以是字符串。

程序运行结果如图4.7所示。

图4.7 绘制柱图

2.条形图

条形图是横向显示的柱图,本例中绘制了带误差线的条形图。

程序运行结果如图4.8所示。

图4.8 绘制条形图

本例中用error数组模拟了误差范围,可以将此图解读为酸橙limes的平均值为20,用柱表示,上下波动范围为±7,用黑色线条表示。它们对应了数值型数据统计中最重要的两个因素:均值和方差。

3.堆叠图

堆叠图是在同一张图中展示了两组柱,以及两组柱叠加的结果,也是常用的统计工具。

程序运行结果如图4.9所示。

图4.9 绘制堆叠图

本例中使用bar函数的参数bottom设置第二组柱显示的起点,以实现堆叠效果。另外,还设置了柱的宽度。

4.直方图

直方图是使用频率最高的柱图,常用它来展示数据的分布。与上述几种柱图不同的是,在通常情况下,直方图只需要指定一个参数,而非x和y两个参数。它分析的是一组数据的内部特征,而非两组数据的相互关系。

程序运行结果如图4.10所示。

图4.10 绘制直方图

本例中生成了两维数组,目的是对比两组数据的分布情况,当然也可以只传入一维数组。在图4.10中,x轴展示了数据变量的取值范围,y轴是在该取值范围内实例的数量,如第一根柱表示第一组数据中有5个数,其值的范围为0~0.1。

4.1.5 饼图

饼图用于展示一组数据的内部规律,多用于分类后展示各个类别的统计值。相对于其他图表,饼图携带的信息量不大,不太容易出效果。使用饼图有一些注意事项,比如太过细碎的分类,最好把占比不多的归为一类,描述为“其他”;如果只有两种类别,与其做饼图,不如用文字描述。

程序运行结果如图4.11所示。

图4.11 绘制饼图

4.1.6 箱线图和小提琴图

箱线图和小提琴图同为统计图,是二维图中相对较难理解的图示,但由于它们可以在一张图中描述各个分组的多种性质,因此也被广泛使用。

1.箱线图

箱线图中每个箱体描述的是一组数,箱体从上到下的五条横线分别对应该组的最大值、75分位数、中位数、25分位数和最小值,相对于均值和方差,该描述携带更多的信息。

在作箱线图时,通常涉及数值型和分类型两种特征,比如先利用性别(分类型变量)将学生分为两组,然后计算每组学生身高(数值型变量)的统计值。

程序运行结果如图4.12所示。

图4.12 绘制箱线图

2.小提琴图

小提琴图的功能类似于箱线图,除了最大值、最小值和中位数,小提琴图两侧的曲线还描述了概率密度,相对来说展示的信息更为具体。

程序运行结果如图4.13所示。

图4.13 绘制小提琴图

4.1.7 三维图

1.三维散点图

mpl_toolkits.mplot3d模块提供了三维绘图功能,但它在大数据量绘图时速度较慢。三维图的优势在于能在同一图表中展示出三维特征的相互关系,但三维静态的图片由于不能随意旋转,故描述能力有限。本章将在后续的PyEchart部分介绍制作可交互的图表。

程序运行结果如图4.14所示。

图4.14 绘制三维散点图

程序用Axes3D函数构造了三维的绘图区域,并绘制出散点图,通常在x轴和y轴两个方向绘制自变量x1和x2,在z轴方向上绘制因变量y

2.三维柱图

与二维柱图一样,三维柱图也常用于描述统计数量。由于三维的统计数据是通过两个类别特征统计得出的,因此它同时也反应了两个特征交互作用的结果。

程序运行结果如图4.15所示。

图4.15 绘制三维柱图

3.三维曲面图和等高线图

本例使用plot_surface函数绘制三维曲面图,只需要指定其X轴、Y轴和Z轴上的三维数组即可绘制曲面图,并将图像在z轴方向上投影。

程序运行结果如图4.16所示。

图4.16 绘制三维曲面图和等高线图

4.1.8 Matplotlib绘图区域

在绘图时,一般包括从大到小三个层次:画板、画布、绘图区。在Matplotlib中,窗口就是画板,Figure是绘制对象,Axes是绘图区。当我们需要在一张大图中展示多张子图时,就要用到绘图区域的概念。

一个绘制对象中可以包含一个或多个Axes子图,每个Axes都是一个拥有自己坐标系统的绘图区域。在上述例程中,使用的都是默认绘图对象和子图。

可以使用plt.gcf(Get current figure)函数获取当前绘制对象,plt.gca(Get current Axes)函数获取当前绘图区域,而使用plt.sca(Set current figure)函数可以设置当前操作的绘图区域。下面介绍多子图绘制中的两个核心方法:

1.创建绘图对象

◎ figure(num=None,figsize=None,dpi=None,facecolor=None,edgecolor=None…)

◎ num:图像编号或名称(数字为编号,字符串为名称)。

◎ figsize:指定绘制对象的宽和高,单位为英寸(1英寸等于2.54cm)。

◎ dpi:指定绘图对象的分辨率,即每英寸多少像素,默认值为80,它决定了图片的清晰程度。

2.创建单个子图

◎ subplot(nrows,ncols,index,**kwargs)

◎ nrows:整体绘图对象中的总行数。

◎ ncols:整体绘图对象中的总列数。

◎ index:指定编号,编号顺序为从左到右、从上到下,从1开始。如果nrows,ncols,index三个参数值都小于10,就可以去掉逗号,如“221”。

最常见的子图排序方式是左右并列两子图和“田”字形四子图。下面将以“田”字形的四子图为例,首先创建8英寸×6英寸的绘图对象,然后分别新建和绘制各个子图,以及设置主标题和子标题。

程序运行结果如图4.17所示。

图4.17 绘制“田”字形四子图

如果需要各个子图大小不同,则可以使用subplot2grid分格显示方法绘制相对复杂的子图。

◎ plt.subplot2grid(shape,loc,rowspan=1,colspan=1,fig=None,**kwargs)

◎ shape:划分网格的行数和列数。

◎ loc:子图开始区域的位置。

◎ rowspan:子图所占行数。

◎ colspan:子图所占列数。

下面通过例程说明subplot2grid的具体用法,将绘图区域分成shape=3×3共9个小区域,第一个子图从loc=(0.0)位置开始,占一行两列,其他子图以此类推。

程序运行结果如图4.18所示。

图4.18 绘制复杂子图

4.1.9 文字显示问题

1.中文字体安装和显示

Matplotlib默认的字体不能正常显示中文,但可以通过配置支持中文,并且指定字体。首先,要获取可用的字体列表,找到对应中文字体的名称,然后用以下方法列出引用字体时的字体名,以及字体文件的实际存储位置。

有时系统未安装中文字体,如在Ubuntu系统中,Matplotlib使用字体和系统字体存放在不同位置,这时就需要把中文字体安装到Matplotlib所定的目录中。假设需要使用黑体字simhei.ttf(可从Windows系统复制,或者从网络下载),就需要将其复制到Matplotlib的字体目录中,请注意不同Python版本目录略有差异。复制后还需要删除用户主目录下Matplotlib的缓存文件,这时安装的字体才能使用。具体命令如下:

注意,由于Matplotlib只搜索TTF字体,因此无法用ttflist方法搜索到TTC字体。如果想使用TTC字体,则需要在程序中指定字体文件的具体位置来装载和使用字体,

推荐使用修改rc默认配置方法设置字体,这样只需要设置一次,即可对所有中文字体显示生效。

2.负号显示问题

另一个常见的显示问题是负号不能正常显示(显示为黑色方框),我们可以通过加入以下代码解决该问题。

4.1.10 导出图表

除了在程序中显示,更多的时候需要把生成的图表导出成为图片,放入文章、PPT中,或者以网页的形式展示。尤其是在发表论文时,对图片的精度有较高要求,Matplotlib提供了plt.savefig函数保存图片,其参数dpi(Dots Per Inch,每英寸点数)可设置精度,其中用于印刷的图片一般设置为dpi:300以上。

除了导出图片,有时也需要将图片嵌入在网页中作为应用展示。下例中通过使用构造网页的etree库和调用浏览器的webbrowser库,将数据表格和Matplotlib生成的图表显示在浏览器中。

程序运行结果如图4.19所示。

图4.19 图表保存成网页并显示

不带格式定义的HTML文件看起来显得比较简陋,可以通过设置网页的风格来美化显示效果,推荐使用bootstrap的css样式。

4.1.11 Matplotlib技巧

在Matplotlib的最后一小节中,将通过综合实例介绍Matplotlib作图的一些技巧,用以做出更加专业的图表。其知识点如下:

◎ 图例:使用plot的label参数和legend方法显示图例,当一张图中显示多个图示时,可以使用图例描述每个图示的含义。注意,只有在调用legend方法后,图例才能显示出来,默认显示在图像内侧的最佳位置。

◎ 图示风格:使用plt.style设置默认图示风格,ggplot灰底色加网络是一种较常用的显示风格。

◎ 绘制文字:使用text函数绘制文字,绘制位置与x轴、y轴坐标一致,常用于在图片内部显示公式、说明等。

◎ 标注:使用annotate函数绘制标注,该函数提供在图片中的不同位置标注多组文字,还支持以箭头方式标注。

x轴和y轴设置:图表默认显示所有内容,但有时候只需要显示其中部分区域。例如,可能由于离群点把核心区域压缩得很小,或者在多图对比时需要显示范围一致。这时,可以使用xlim和ylim设置x轴和y轴的显示范围,使用xlabel和ylabel设置x轴与y轴上显示的标签文字,使用xticks和yticks设置坐标轴的刻度。

◎ 用matplotlib.artist.getp方法获取绘图对象的属性值。综合实例见以下例程:

程序运行结果如图4.20所示。

图4.20 设置风格及标注