Python绘图与可视化
Python 有很多可视化工具,本篇只介绍 Matplotlib。
Matplotlib 是一种 2D 的绘图库,它可以支持硬拷贝和跨系统的交互,它可以在 Python 脚本、IPython 的交互环境下、Web 应用程序中使用。该项目是由 John Hunter 于 2002 年启动的,其目的是为 Python 构建一个 MATLAB 式的绘图接口。如果结合使用一种 GUI 工具包(如 IPython),Matplotlib 还具有诸如缩放和平移等交互功能。它不仅支持各种操作系统上许多不同的 GUI 后端,而且还能将图片导出为各种常见的食量(vector)和光栅(raster)图:PDF、SVG、JPG、PNG、BMP、GIF 等。
Matplotlib 程序包
所谓“一图胜千言”,我们很多时候需要通过可视化的方式查看、分析数据,虽然 Pandas 中也有一些绘图操作,但是相比较而言,Matplotlib 在绘图显示效果方面更加出色。Python 为 Matplotlib 提供了一个方便的接口,我们可以通过 Pyplot 对 Matplotlib 进行操作,多数情况下,Pyplot 的命令与 MATLAB 有些相似。
导入 Matplotlib 包进行简单的操作(此处需要安装 pip install matplotlib):
import matplotlib.pyplot as plt#约定俗成的写法 plt #首先定义两个函数(正弦 & 余弦) import numpy as npX=np.linspace(-np.pi,np.pi,256,endpoint=True)#-π to+π的 256 个值
C,S=np.cos(X),np.sin(X)
plt.plot(X,C)
plt.plot(X,S)
#在 ipython 的交互环境中需要这句话才能显示出来
plt.show()
输出结果:
绘图命令的基本架构及其属性设置
上面的例子我们可以看出,几乎所有的属性和绘图的框架我们都选用默认设置。现在我们来看 Pyplot 绘图的基本框架是什么,用过 Photoshop 的人都知道,作图时先要定义一个画布,此处的画布就是 Figure,然后再把其他素材“画”到该 Figure 上。
1)在 Figure 上创建子 plot,并设置属性
x=np.linspace(0,10,1000)#X 轴数据 y1=np.sin(x)#Y 轴数据 y2=np.cos(x**2)#Y 轴数据 x**2 即 x 的平方 plt.figure(figsize=(8,4))plt.plot(x,y1,label="$sin(x)$",color="red",linewidth=2)#将 $ 包围的内容渲染为数学公式
plt.plot(x,y2,"b--",label="$cos(x^2)$")
#指定曲线的颜色和线性,如‘b--’表示蓝色虚线(b:蓝色,-:虚线)
plt.xlabel("Time(s)")
plt.ylabel("Volt")
plt.title("PyPlot First Example")'''
使用关键字参数可以指定所绘制的曲线的各种属性:
label:给曲线指定一个标签名称,此标签将在图标中显示。如果标签字符串的前后都有字符 '$',则 Matplotlib 会使用其内嵌的 LaTex 引擎将其显示为数学公式
color:指定曲线的颜色。颜色可以用如下方法表示
英文单词
以‘#’字符开头的 3 个 16 进制数,如‘#ff0000’表示红色。
以 0~1 的 RGB 表示,如(1.0,0.0,0.0)也表示红色。
linewidth:指定权限的宽度,可以不是整数,也可以使用缩写形式的参数名 lw。
'''plt.ylim(-1.5,1.5)
plt.legend()#显示左下角的图例
plt.show()
2)在 Figure 上创建多个子 plot
如果需要绘制多幅图表的话,可以给 Figure 传递一个整数参数指定图表的序号,如果所指定序号的绘图对象已经存在的话,将不创建新的对象,而只是让它成为当前绘图对象。
fig1=plt.figure(2) plt.subplot(211) #subplot(211) 把绘图区域等分为 2 行 *1 列共两个区域,然后在区域 1(上区域)中创建一个轴对象 plt.subplot(212)#在区域 2(下区域)创建一个轴对象 plt.show()
输出结果:
我们还可以通过命令再次拆分这些块(相当于 Word 中拆分单元格操作)
f1=plt.figure(5)#弹出对话框时的标题,如果显示的形式为弹出对话框的话 plt.subplot(221) plt.subplot(222) plt.subplot(212) plt.subplots_adjust(left=0.08,right=0.95,wspace=0.25,hspace=0.45) # subplots_adjust 的操作时类似于网页 css 格式化中的边距处理,左边距离多少? # 右边距离多少?这取决于你需要绘制的大小和各个模块之间的间距 plt.show()
输出结果:
3)通过 Axes 设置当前对象 plot 的属性
以上我们操作的是在 Figure 上绘制图案,但是当我们绘制图案过多,又需要选取不同的小模块进行格式化设置时,Axes 对象就能很好地解决这个问题。
fig,axes=plt.subplots(nrows=2,ncols=2)#定一个 2*2 的 plot plt.show()
输出结果:
现在我们需要通过命令来操作每个 plot(subplot),设置它们的 title 并删除横纵坐标值。
fig,axes=plt.subplots(nrows=2,ncols=2)#定一个 2*2 的 plot axes[0,0].set(title='Upper Left') axes[0,1].set(title='Upper Right') axes[1,0].set(title='Lower Left') axes[1,1].set(title='Lower Right')# 通过 Axes 的 flat 属性进行遍历
for ax in axes.flat:
# xticks 和 yticks 设置为空置
ax.set(xticks=[],yticks=[])
plt.show()
输出结果:
另外,实际来说,plot 操作的底层操作就是 Axes 对象的操作,只不过如果我们不使用 Axes 而用 plot 操作时,它默认的是 plot.subplot(111),也就是说 plot 其实是 Axes 的特例。
4)保存 Figure 对象
最后一项操作就是保存,我们绘图的目的是用在其他研究中,或者希望可以把研究结果保存下来,此时需要的操作时 save。
plt.savefig(r"C:\Users\123\Desktop\save_test.png",dpi=520)#默认像素 dpi 是 80
很明显保存的像素越高,内存越大。此处只是用了 savefig 属性对 Figure 进行保存。
另外,除了上述的基本操作之外,Matplotlib 还有其他的绘图优势,此处只是简单介绍了它在绘图时所需要注意的事项,更多的属性设置请参考:https://matplotlib.org/api/
Seaborn 模块介绍
前面我们简单介绍了 Matplotlib 库的绘图功能和属性设置,对于常规性的绘图,使用 Pandas 的绘图功能已经足够了,但如果对 Matplotlib 的 API 属性研究较为透彻,几乎没有不能解决的问题。但是 Matplotlib 还是有它的不足之处,Matplotlib 自动化程度非常高,但是,掌握如何设置系统以便获得一个吸引人的图是相当困难的事。为了控制 Matplotlib 图表的外观,Seaborn 模块自带许多定制的主题和高级的接口。
1)未加 Seaborn 模块的效果
import numpy as np import matplotlib as mpl import matplotlib.pyplot as pltnp.random.seed(sum(map(ord,"aesthetics")))
#首先定义一个函数用来画正弦函数,可帮助了解可以控制的不同风格参数
def sinplot(flip=1):
x=np.linspace(0,14,100)
for i in range(1,7):
plt.plot(x,np.sin(x+i0.5)(7-i)*flip)
sinplot()
plt.show()
输出结果:
2)加入 Seaborn 模块的效果
import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt# 添加了 Seaborn 模块
np.random.seed(sum(map(ord,"aesthetics")))
#首先定义一个函数用来画正弦函数,可帮助了解可以控制的不同风格参数
def sinplot(flip=1):
x=np.linspace(0,14,100)
for i in range(1,7):
plt.plot(x,np.sin(x+i0.5)(7-i)*flip)
#转换成 Seaborn 模块,只需要引入 seaborn 模块
import seaborn as sns#添加 Seaborn 模块
sinplot()
plt.show()
输出效果:
小编使用的 jupyter notebook 编辑器,使用与不使用 Seaborn 模块效果差别不明显。
使用 Seaborn 的优点有:
- Seaborn 默认浅灰色背景与白色网格线的灵感来源于 Matplotlib,却比 Matplotlib 的颜色更加柔和
- Seaborn 把绘图风格参数与数据参数分开设置。
其中,Seaborn 有两组函数对风格进行控制:axes_style()/set_style() 函数和 plotting_context()/set_context() 函数。
axes_style()函数和 plotting_context() 函数返回参数字典,set_style()函数和 set_context() 函数设置 Matplotlib。
使用 set_style() 函数
import seaborn as sns'''
Seaborn 有 5 种预定义的主题:
darkgrid(灰色背景 + 白网格)
whitegrid(白色背景 + 黑网格)
dark(仅灰色背景)
white(仅白色背景)
ticks(坐标轴带刻度)
默认的主题是 darkgrid,修改主题可以使用 set_style 函数
'''
sns.set_style("whitegrid")
sinplot()# 即上段代码中定义的函数
plt.show()
输出结果:
使用 set_context() 函数
''' 上下文(context)可以设置输出图片的大小尺寸(scale) Seaborn 中预定义的上下文有 4 种:paper、notebook、talk 和 poster 默认使用 notebook 上下文 ''' sns.set_context("poster")sinplot()#即前文定义的函数 plt.show()
输出结果:
使用 Seaborn“耍酷”
然而 Seaborn 不仅能够用来更改背景颜色,或者改变画布大小,还有其他很多方面的用途,比如下面的例子。
''' Annotated heatmaps ================================ ''' import matplotlib.pyplot as plt import seaborn as sns sns.set()#通过加载 sns 自带数据库中的数据(具体数据可以不关心)
flights_long=sns.load_dataset("flights")
flights=flights_long.pivot("month","year","passengers")# 使用每个单元格中的数据值绘制一个热力图 heatmap
sns.heatmap(flights,annot=True,fmt="d",linewidths=.5)
plt.show()
输出结果:
描述性统计图形概览
描述性统计是借助图表或者总结性的数值来描述数据的统计手段。数据挖掘工作的数据分析阶段,我们可借助描述性统计来描绘或总结数据的基本情况,一来可以梳理自己的思维,而来可以更好地向他人展示数据分析结果。数值分析的过程中,我们往往要计算出数据的统计特征,用来做科学计算的 Numpy 和 Scipy 工具可以满足我们的需求。Matplotlib 工具可用来绘制图,满足图分析的需求。
1)制作数据
数据是自己制作的,主要包括个人身高、体重及一年的借阅图书量(之所以自己制作数据是因为不是每份真实的数据都可以进行接下来的分析,比如有些数据就不能绘制饼图,另一个角度也说明,此处举例的数据其实没有实际意义,只是为了分析二举例,但是不代表在具体的应用中这些分析不能发挥作用)。
另外,以下的数据显示都是在 Seaborn 库的作用下体现的效果。
# 案例分析 from numpy import array from numpy.random import normaldef getData():
heights=[]
weights=[]
books=[]
N=10000
for i in range(N):
while True:
#身高服从均值为 172,标准差为 6 的正态分布
height=normal(172,6)
if 0<height:
break
while True:
#体重由身高作为自变量的线性回归模型产生,误差服从标准正态分布
weight=(height-80)*0.7+normal(0,1)
if 0<weight:
break
while True:
#借阅量服从均值为 20,标准差为 5 的正态分布
number=normal(20,5)
if 0<=number and number<=50:
book='E' if number<10 else ('D' if number<15 else ('C' if number<20 else ('B' if number<25 else 'A')))
break
heights.append(height)
weights.append(weight)
books.append(book)
return array(heights),array(weights),array(books)
heights,weights,books=getData()
2) 频数分析
(1)定性分析
柱状图和饼形图是对定性数据进行频数分析的常用工具,使用前需将每一类的频数计算出来。
柱状图。柱状图是以柱的高度来指代某类型的频数,使用 Matplotlib 对图书借阅量这一定性变量绘制柱状图的代码如下。(接上段代码)
from matplotlib import pyplot#绘制柱状图
def drawBar(books):
xticks=['A','B','C','D','E']
bookGroup={}
#对每一类借阅量进行频数统计
for book in books:
bookGroup[book]=bookGroup.get(book,0)+1
#创建柱状图
#第一个参数为柱的横坐标
#第二个参数为柱的高度
#参数 align 为柱的对齐方式,以第一个参数为参考标准
pyplot.bar(range(5),[bookGroup.get(xtick,0) for xtick in xticks],align='center')</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">设置柱的文字说明</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">第一个参数为文字说明的横坐标</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">第二个参数为文字说明的内容</span> pyplot.xticks(range(5<span style="color: rgba(0, 0, 0, 1)">),xticks) </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">设置横坐标的文字说明</span> pyplot.xlabel(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Types of Students</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">设置纵坐标的文字说明</span> pyplot.ylabel(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Frequency</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">设置标题</span> pyplot.title(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Numbers of Books Students Read</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">绘图</span>
pyplot.show()
drawBar(books)
输出结果:
饼形图。饼形图事宜扇形的面积来指代某类型的频率,使用 Matplotlib 对图书借阅量这一定性变量绘制饼形图的代码如下:
#绘制饼形图 def drawPie(books): labels=['A','B','C','D','E'] bookGroup={} for book in books: bookGroup[book]=bookGroup.get(book,0)+1 #创建饼形图 #第一个参数是扇形的面积 #labels 参数为扇形的说明文字 #autopct 参数为扇形占比的显示格式 pyplot.pie([bookGroup.get(label,0) for label in labels],labels=labels,autopct='%1.1f%%') pyplot.title("Number of Books Students Read")pyplot.show() drawPie(books)
输出结果:
(2)定量分析
直方图类似于柱状图,是用柱的高度来指代频数,不同的是其将定量数据划分为若干连续的区间,在这些连续的区间上绘制柱。
直方图。使用 Matplotlib 对身高这一定量变量绘制直方图的代码如下:
#绘制直方图 def drawHist(heights): #创建直方图 #第一个参数为待绘制的定量数据,不同于定性数据,这里并没有实现进行频数统计 #第二个参数为划分的区间个数 pyplot.hist(heights,100) pyplot.xlabel('Heights') pyplot.ylabel('Frequency') pyplot.title('Height of Students')pyplot.show() drawHist(heights)
输出结果:
累积曲线。使用 Matplotlib 对身高这一定量变量绘制累积曲线的代码如下:
#绘制累积曲线 def drawCumulativaHist(heights): #创建累积曲线 #第一个参数为待绘制的定量数据 #第二个参数为划分的区间个数 #normal 参数为是否无量纲化 #histtype 参数为‘step’,绘制阶梯状的曲线 #cumulative 参数为是否累积 pyplot.hist(heights,20,normed=True,histtype='step',cumulative=True) pyplot.xlabel('Heights') pyplot.ylabel('Frequency') pyplot.title('Heights of Students')pyplot.show() drawCumulativaHist(heights)
输出结果:
3) 关系分析
散点图。在散点图中,分别以自变量和因变量作为横坐标。当自变量与因变量线性相关时,散点图中的点近似分布在一条直线上。我们以身高作为自变量,体重作为因变量,讨论身高对体重的影响。使用 Matplotlib 绘制散点图的代码如下:
#绘制散点图 def drawScatter(heights,weights): #创建散点图 #第一个参数为点的横坐标 #第二个参数为点的纵坐标 pyplot.scatter(heights,weights) pyplot.xlabel('Heights') pyplot.ylabel('Weight') pyplot.title('Heights & Weight of Students')pyplot.show() drawScatter(heights,weights)
输出结果:
4) 探索分析
箱型图。在不明确数据分析的目标时,我们对数据进行一些探索性的分析,可以知道数据的中心位置、发散程度及偏差程度。使用 Matplotlib 绘制关于身高的箱型图代码如下:
#绘制箱型图 def drawBox(heights): #创建箱型图 #第一个参数为待绘制的定量数据 #第二个参数为数据的文字说明 pyplot.boxplot([heights],labels=['Heights']) pyplot.title('Heights of Students')pyplot.show() drawBox(heights)
输出结果:
注:
- 上四分位数与下四分位数的差叫四分位差,它是衡量数据发散程度的指标之一
- 上界线和下界线是距离中位数 1.5 倍四分位差的线,高于上界线或者低于下界线的数据为异常值
描述性统计是容易操作、直观简洁的数据分析手段。但是由于简单,对于多元变量的关系难以描述。现实生活中,自变量通常是多元的:决定体重的不仅有身高,还有饮食习惯、肥胖基因等因素。通过一些高级的数据处理手段,我们可以对多元变量进行处理,例如,特征工程中,可以使用互信息方法来选择多个对因变量有较强相关性的自变量作为特征,还可以使用主成分分析法来消除一些冗余的自变量来降低运算复杂度。
参考书目:《数据馆员的 Python 简明手册》