目录
常规绘图方法
首先导入工具包,一般用plt来当作Matplotlib的别名:
import matplotlib.pyplot as plt
%matplotlib inline
指定魔法指令之后,在Notebook中只需要执行画图操作就可以在界面进行展示,先来画一个简单的折线图,只需要把二维数据点对应好即可:
plt.plot([1,2,3,4,5],[1,4,9,16,25])
plt.xlabel('xlabel',fontsize=16)
plt.ylabel('ylabel')
给定横坐标[1,2,3,4,5],纵坐标[1,4,9,16,25],并且指明x轴与y轴的名称分别为xlabel和ylabel。
细节设置
在plot()函数中可以设置很多细节参数,例如线条的种类。
不仅可以改变线条的形状,也可以自己定义颜色。
首先构造一组数据,然后选择不同的线条类型和颜色来观察一下输出效果:
plt.plot([1,2,3,4,5],[1,4,9,16,25],'-.')
plt.xlabel('xlabel',fontsize=16) #fontsize表示字体的大小
plt.ylabel('ylabel',fontsize=16)
plt.plot([1,2,3,4,5],[1,4,9,16,25],'-.',color='r')
还可以多次调用plot()函数来加入多次绘图的结果,其中颜色和线条参数也可以写在一起,例如,“r- -”表示红色的虚线:
tang_array=np.arange(0,10,0.5)
plt.plot(tang_array,tang_array,'r--')
plt.plot(tang_array,tang_array**2,'bs')
plt.plot(tang_array,tang_array**3,'go')
在用matplotlib绘图中,基本上你能想到的特征都有相应的控制参数,例如线条宽度、形状、大小 等:
x=np.linspace(-10,10)
y=np.sin(x)
plt.plot(x,y,linewidth=3.0) # 设置线条宽度
plt.plot(x,y,color='b',linestyle=':',marker='o',markerfacecolor='r',markersize=10)
line=plt.plot(x,y)
plt.setp(line,color='r',linewidth=2.0,alpha=0.4) #alpha表示透明程度
子图和标注
所谓子图就是指一整幅图形中包含几个单独的小图,这些子图可以按照行或者列的形式排列
plt.subplot(211)
plt.plot(x,y,color='r')
plt.subplot(212)
plt.plot(x,y,color='b')
subplot(211)表示要画的图整体是2行1列的,一共包括两幅子图,最后的1表示当前绘制顺序是第一幅子图。subplot(212)表示还是这个整体,只是在顺序上要画第2个位置上的子图。
上图就是2行1列的子图绘制结果,整体表现为竖着排列,如果想横着排列,那就是1行2列了:
plt.subplot(121)
plt.plot(x,y,color='r')
plt.subplot(122)
plt.plot(x,y,color='b')
不仅可以创建一行或者一列,还可以创建多行多列,指定好整体规模,然后在对应位置画各个子图 就可以了,如果在当前子图位置没有执行绘图操作,该位置子图也会空出来:
plt.subplot(321)
plt.plot(x,y,color='r')
plt.subplot(324)
plt.plot(x,y,color='b')
绘图完成之后,通常会在图上加一些解释说明,也就是标注:
plt.plot(x,y,color='b',linestyle=':',marker='o',markerfacecolor='r',markersize=10)
plt.xlabel('x:---')
plt.ylabel('y:---')
#图题
plt.title('xiao mi yue:---')
plt.text(0,0,'xiao mi yue')# 在指定位置添加注释
plt.grid(True) #显示网络
plt.annotate('xiaomiyue',xy=(-5,0),xytext=(-2,0.3),arrowprops=dict(facecolor='red',shrink=0.05,headlength=20,headwidth=20))
#添加箭头,需给定起始和终止位置以及箭头的各种属性
上图中显示了网格,有时为了整体的美感和需求也可以把网格隐藏起来,通过plt.gca()来获得当前图表,然后改变其属性值:
x=range(10)
y=range(10)
fig=plt.gca()
plt.plot(x,y)
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
上述输出结果看起来光秃秃的不好看,还是往里面添加一些实际数据吧,估计更多人喜欢隐藏上方 和右方的坐标轴,然后带着网格线,可能更好看一些:
import math
x=np.random.normal(loc=0.0,scale=1.0,size=300)
width=0.5
bins=np.arange(math.floor(x.min())-width,math.ceil(x.max())+width,width)
ax=plt.subplot(111)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)#去掉上方和右方的坐标轴线
plt.tick_params(bottom='off',top='off',left='off',right='off')#可以自己选择隐藏坐标轴上的锯齿线
plt.grid()#加入网络
plt.hist(x,alpha=0.5,bins=bins)#绘制直方图
在细节设置中,可以调节的参数太多,例如在x轴上,如果字符太多,横着写容易堆叠在一起了,这该怎么办呢?
x=range(10)
y=range(10)
labels=['xiaomiyue' for i in range(10)]
fig,ax=plt.subplots()
plt.plot(x,y)
plt.title('xiaomiyue')
ax.set_xticklabels(labels,rotation=45,horizontalalignment='right')
横着写不下,也可以斜着写,这些都可以自定义设置。在绘制多个线条或者多个类别数据时,之前我们用颜色来区别,但是还没有给出颜色和类别的对应关系,此时就需要使用legend()函数来指定:
x=np.arange(10)
for i in range(1,4):
plt.plot(x,i*x**2,label='Group %d' %i)
plt.legend(loc='best')
其中loc='best'相当于让工具包自己找一个合适的位置来显示图表中颜色所对应的类别,当然其位置也可以自己指定,那么都有哪些可选项呢?别忘了help函数,可以直接打印出所有可调参数:
print(help(plt.legend))
loc参数中还可以指定特殊位置:
fig=plt.figure()
ax=plt.subplot(111)
x=np.arange(10)
for i in range(1,4):
plt.plot(x,i*x**2,label='Group %d' %i)
ax.legend(loc='upper center',bbox_to_anchor=(0.5,1.15),ncol=3)
在Matplotlib中,绘制一个图表还是比较容易的,只需要传入数据即可,但是想把图表展示得完美就得慢慢调整了,其中能涉及的参数还是比较多的。最偷懒的方法就是寻找一个绘图的模板,然 后把所需数据传入即可,在Matplotlib官网和Sklearn官网的实例中均有绘好的图表,这些都可以作为平时的积累。
风格设置
首先可以查看一下Matplotlib有哪些能调用的风格,代码如下:
plt.style.available
['Solarize_Light2',
'_classic_test_patch',
'_mpl-gallery',
'_mpl-gallery-nogrid',
'bmh',
'classic',
'dark_background',
'fast',
'fivethirtyeight',
'ggplot',
'grayscale',
'seaborn-v0_8',
'seaborn-v0_8-bright',
'seaborn-v0_8-colorblind',
'seaborn-v0_8-dark',
'seaborn-v0_8-dark-palette',
'seaborn-v0_8-darkgrid',
'seaborn-v0_8-deep',
'seaborn-v0_8-muted',
'seaborn-v0_8-notebook',
'seaborn-v0_8-paper',
'seaborn-v0_8-pastel',
'seaborn-v0_8-poster',
'seaborn-v0_8-talk',
'seaborn-v0_8-ticks',
'seaborn-v0_8-white',
'seaborn-v0_8-whitegrid',
'tableau-colorblind10']
默认的风格代码如下:
x=np.linspace(-10,10)
y=np.sin(x)
plt.plot(x,y)
可以通过plt.style.use()函数来改变当前风格,再来尝试几种:
plt.style.use('dark_background')
plt.plot(x,y)
plt.style.use('bmh')
plt.plot(x,y)
plt.style.use('ggplot')
plt.plot(x,y)
常用图表绘制
在对比数据特征的时候,条形图是最常用的方法,在Matplotlib中的调用方法也很简单:
np.random.seed(0)
x=np.arange(5)
y=np.random.randint(-5,5,5)
fig,axes=plt.subplots(ncols=2)
v_bars=axes[0].bar(x,y,color='red')#正常的条形图
h_bars=axes[1].barh(x,y,color='red')#横着画
#通过子图索引来分别设置各自细节
axes[0].axhline(0,color='grey',linewidth=2)
axes[1].axvline(0,color='grey',linewidth=2)
plt.show()
在绘图过程中,有时需要考虑误差棒,以表示数据或者实验的偏离情况,做法也很简单,在bar()函数中,已经有现成的yerr和xerr参数,直接赋值即可:
mean_values=[1,2,3]#数值
variance=[0.2,0.4,0.5]#误差棒
bar_label=['bar1','bar2','bar3']#名字
x_pos=list(range(len(bar_label)))#指定位置
plt.bar(x_pos,mean_values,yerr=variance,alpha=0.3)#带有误差棒的条形图
#可以自己设置x轴和y轴的取值范围
max_y=max(zip(mean_values,variance))
plt.ylim([0,(max_y[0]+max_y[1])*1.2])
plt.ylabel('variable y')
plt.xticks(x_pos,bar_label)
plt.show()
既然是进行数据的对比分析,也可以加入更多对比细节,先把条形图绘制出来,细节都可以慢慢添加:
data=range(200,225,5)
bar_labels=['a','b','c','d','e']#要对比的类别名称
#指定画图区域大小
fig=plt.figure(figsize=(10,8))
#一会要横着画图所以在y轴上找每个起始位置
y_pos=np.arange(len(data))
#在y轴上写上各个类别名字
plt.yticks(y_pos,bar_labels,fontsize=16)
#绘制条形图指定颜色和透明度
bars=plt.barh(y_pos,data,alpha=0.5,color='g')
#画一条竖线,至少需要三个参数,即x轴位置也就是在哪画,y轴的起始位置和终止位置
plt.vlines(min(data),-1,len(data)+0.5,linestyle='dashed')
#在对应位置写上注释,这里写了随意计算的结果
for b,d in zip(bars,data):
plt.text(b.get_width()+b.get_width()*0.05,b.get_y()+b.get_height()/2,'{0:.2%}'.format(d/min(data)))
plt.show()
如果想把条形图画得更个性一些,也可以让各种线条看起来不同:
patterns=('-','+','x','\\','*','o','O','.')#这些图形对应下面的绘图结果
mean_value=range(1,len(patterns)+1)#让条形图数值递增看起来舒服点
x_pos=list(range(len(mean_value)))
bars=plt.bar(x_pos,mean_value,color='white')
for bar,pattern in zip(bars,patterns):
bar.set_hatch(pattern)
plt.show()
盒图
盒图(boxplot)主要由最小值(min)、下四分位数(Q1)、中位数(median)、上四分位数(Q3)、最大值(max) 五部分组成。当然也可以按照自己的喜好加入其他指标,代码如下:
tang_data=[np.random.normal(0,std,100) for std in range(1,4)]
fig=plt.figure(figsize=(8,6))
plt.boxplot(tang_data,sym='s',vert=True)
plt.xticks([y+1 for y in range(len(tang_data))],['x1','x2','x3'])
plt.xlabel('x')
plt.title('box plot')
在每一个小盒图中,从下到上就分别对应之前说的5个组成部分,计算方法如下:
•IQR=Q3–Q1,即上四分位数与下四分位数之间的差;
•min=Q1–1.5×IQR,正常范围的下限;
•max=Q3+1.5×IQR,正常范围的上限。
其中的方块代表异常点或者离群点,离群点就是超出上限或下限的数据点,所以用盒图可以很方便 地观察离群点的情况。
boxplot()函数就是主要绘图部分,其他细节部分都是通用的。sym参数用来展示异常点的符号,可以 用正方形,也可以用加号,这取决于你的喜好。vert参数表示是否要竖着画,它与条形图一样,也可以横着画。可选参数还是比较多的,如果大家想看完整的参数,最直接的办法就是:
print(help(plt.boxplot))
还有一种图形与盒图长得有点相似,叫作小提琴图(violinplot)。绘制方法也相同,可以对比一下:
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(12,5))#接着画两个图来对比
tang_data=[np.random.normal(0,std,100) for std in range(6,10)]
#左边画小提琴图
axes[0].violinplot(tang_data,showmeans=False,showmedians=True)
axes[0].set_title('violin plot')
#右边画盒图
axes[1].boxplot(tang_data)
axes[1].set_title('box plot')
for ax in axes:
#为了对比更清晰一些把网格画出来
ax.yaxis.grid(True)
#指定x轴画的位置
ax.set_xticks([y+1 for y in range(len(tang_data))])
#设置x轴上指定的名字
ax.set_xticklabels(['x1','x2','x3','x4'])
小提琴图给人以“胖瘦”的感觉,越“胖”表示当前位置的数据点分布越密集,越“瘦”则表示此处数据点 比较稀疏。小提琴图没有展示出离群点,而是从数据的最小值、最大值开始展示。
直方图和散点图
直方图(Histogram)可以更清晰地表示数据的分布情况,还是先画一个来看看:
data = np.random.normal(0,20,1000)
bins = np.arange(-100,100,5)
plt.hist(data,bins=bins)
plt.xlim([min(data)-5,max(data)+5])
plt.show()
画直方图的时候,需要指定一个bins,也就是按照什么区间来划分,例如np.arange(−10,10,5)=array([−10,−5,0,5])。
如果想同时展示不同类别数据的分布情况,也可以分别绘制,但是要更透明一些,否则就会堆叠在 一起:
import random
data1 = [random.gauss(15,10) for i in range(500)]
data2 = [random.gauss(5,5) for i in range(500)]
bins = np.arange(-50,50,2.5)
plt.hist(data1,bins=bins,label='class 1',alpha = 0.3)
plt.hist(data2,bins=bins,label='class 2',alpha = 0.3)
plt.legend(loc='best')#用不同颜色表示不同类别
plt.show()
散点图就更常见啦,只要有数据就能绘制,通常还可以用散点图来表示特征之间的相关性,调用 scatter()函数即可:
N=1000
x=np.random.randn(N)
y=np.random.randn(N)
plt.scatter(x,y,alpha=0.3)
plt.grid(True)
plt.show()
3D图
如果要展示三维数据情况,就需要用到3D图:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
plt.show()
这样就形成了一个空白的3D图,接下来只需要往里面填充数据即可:
np.random.seed(1)
def randrange(n,vmin,vmax):
return (vmax-vmin)*np.random.rand(n)+vmin
fig = plt.figure()
ax = fig.add_subplot(111,projection = '3d')
n = 100
#颜色和标记以及取值范围
for c,m,zlow,zhigh in [('r','o',-50,-25),('b','x','-30','-5')]:
xs = randrange(n,23,32)
ys = randrange(n,0,100)
zs = randrange(n,int(zlow),int(zhigh))
ax.scatter(xs,ys,zs,c=c,marker=m)
plt.show()
由于3D图是立体的,还可以对其进行旋转操作,以不同的视角观察结果,只需在最后加入 ax.view_init()函数,并在其中设置旋转的角度即可.
其他图表的3D图绘制方法相同,只需要调用各自的绘图函数即可:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]):
xs = np.arange(20)
ys = np.random.rand(20)
cs = [c]*len(xs)
ax.bar(xs,ys,zs = z,zdir='y',color = cs,alpha = 0.5)
plt.show()
布局设置
几种基本的绘图方法都给大家进行了演示,把多个图表总结在一起进行对比也是很常见的方法,之前讲解了调用子图的方法,但是看起来各个部分都是同样的大小,没有突出某一主题,使用时也可以自定义子图的布局:
#3*3的布局,第一个子图
ax1=plt.subplot2grid((3,3),(0,0))
#布局大小都是3*3,各自位置不同
ax2=plt.subplot2grid((3,3),(1,0))
#可以都占用一些位置一个顶三个
ax3=plt.subplot2grid((3,3),(0,2),rowspan=3)
#同上,一个顶两个
ax4=plt.subplot2grid((3,3),(2,0),colspan=2)
ax5=plt.subplot2grid((3,3),(0,1),rowspan=2)
不同子图的规模不同,在布局时,也可以在图表中再嵌套子图:
本章介绍了可视化库Matplotlib的基本使用方法,绘制图表还是比较方便的,只需1行核心代码就够 了,如果想画得更精致,就要用各种参数慢慢尝试。其实在进行绘图展示的时候很少有人自己从头去 写,基本上都是拿一个差不多的模板,再把实际需要的数据传进去,现在给大家推荐——sklearn工具包 的官方实例,里面有很多可视化展示结果,画得比较精致,而且都和机器学习相关,需要时直接取一个模板即可。