[转载] 在Python中使用Matplotlib绘制常见图表

参考链接: Python | 使用openpyxl模块在Excel工作表中绘制图表 3

Matplotlib 是一个非常强大的 Python 画图工具,通过绘制线图、散点图、等高线图、条形图、柱状图、3D 图形、甚至是图形动画等,可以更加直观的呈现科学计算等遇到的大量数据。 

1、基本元素 

在matplotlib的层级结构中,最高层是由matplotlib.pyplot模块提供的“状态机环境”(state-machine environment),通过它来为当前维度绘制图像元素,例如曲线、文本、图片等。接下来一层是第一级的面向对象接口,在这一层中用户可以使用pyplot创建并追踪图像对象,并由此创建一个或多个数据轴系,这些轴系在之后用于图的绘制。 

如下所示为图像的各个元素: 

 

Figure指的是整张图片对象,用于包含一个或多个数据轴系(Axes),如果没Axes,则图像为空。 

fig = plt.figure()  # 创建一个图像对象

fig.suptitle('No axes on this figure')  # 添加一个标题

 

fig, ax_lst = plt.subplots(2, 2)  # 创建包含2×2个子图的图像 

Aexs是轴(Axis)的复数,翻译为轴系、坐标系,可以将其理解为整个图像(Figure)的一个子图,一个图形可以包含多个子图,我们在子图中进行具体图表的绘制。通过plt.plot()函数可以创建子图对象,通过set_title()可以设置子图的标题,set_xlabel()、set_ylabel()对图的横纵坐标的标签进行设置。 

Axis指具体的坐标轴,其中trick代表坐标轴的刻度,通过Location对象控制刻度的位置,Formatter格式化刻度显示的字符串,通过这两个对象可以精确地控制刻度的显示。 

Artist对象:在图像中任何元素都可以看作Artist,包括2D线条(Line)、文本、以及Axis和图像Figure,当图片被渲染时,这些对象被绘制到图片中。大多数Artist对象绑定于一个具体轴Axis,这样的对象不可以在轴系之间共享。 

matplot的输入数据最好转化为np.array类型,使用其他的数据类型例如np.matrix、pandas等可能会报错,因此在传入参数前先将其他类型通过numpy转换一下。 

matplotlib建议的引入必要库与编码方式如下,绘图时首先通过plt接口创建Figure对象与子图对象ax,之后通过ax调用函数绘图,通过定义函数来进行图像绘制可以避免许多重复操作,而且便于代码维护。例如下面定义了my_plotter()完成图像绘制,传入子图ax,两个数据data1,data2,以及图像绘制参数param_dic。 

import matplotlib.pyplot as plt    # 引入必要的库

import numpy as np

%matplotlib inline     

 

# 定义函数进行图像绘制操作

def my_plotter(ax,data1,data2,param_dic):

    ax.plot(x, y,**param_dic)

 

x = np.arange(0, 10, 0.2)    # 准备数据

y = np.sin(x)

 

fig, ax = plt.subplots(1)    # 创建子图

my_plotter(ax,x, y,{ 'linestyle':'dashed','label':'sinx'})  # 调用函数绘制图像 

2、基本用法 

创建图像并绘制函数 

首先需要导入必须的函数库matplotlib.pyplot与numpy。如果使用jupyternotebook则需要添加%matplotlib inline设置以显示图片 

通过plt.figure()创建一个图像,其中num属性指出显示图像的窗口,figsize属性可以指定图像的大小,facecolor属性指定图像的背景颜色。 

通过plt.plot()进行曲线的绘制,前两个数组参数为图像x、y的坐标值。之后的可选参数对可以对线条的颜色(color)、宽度(linewidth)、样式(linestyle)、不透明度(alpha)进行设置 

plt.scatter()绘制单独的一个点,而不是连起来的曲线,同样前两个参数为数组,对应点的x、y坐标。属性s设置点的大小,color设置颜色 

最后通过plt.show()输出图像,或者通过plt.savefig()保存为指定图片,注意要在show()之前使用,否则图片会被输出,从而保存的图片为空。 

如果需要频繁进行绘图,则需要关闭一些没用的图片以节约内存。通过plt.cla()可以关闭当前Axes,plt.clf()关闭当前图像,plt.close()关闭当前绘图窗口。 

import numpy as np

import matplotlib.pyplot as plt

# 设置行内显示

%matplotlib inline      

 

x = np.linspace(-5, 5, 50)        # 在-5~5内均匀取50个数

y1 = 2*x + 1                      # 定义一个线性函数

y2 = x**2                         # 定义一个二次函数

 

plt.figure(num=3, figsize=(10, 5), facecolor='white')           # 创建一个图形对象

plt.plot(x, y2, alpha=0.5)                                      # 绘制曲线

plt.plot(x, y1, color='red', linewidth=1.0, linestyle='--')     

plt.scatter([1],[1],s=200,color='orange')                       # 绘制一个点

 

plt.savefig('./myplt.jpg')                                      # 保存图片

plt.show()                                                      # 显示图像  

plt.close()                                                     # 关闭绘图窗口 

 

调整坐标轴 

通过plt.xlim可以调整x坐标轴的范围,plt.xlabel设置坐标轴的名字,同理plt.ylim与ylabel对y轴进行设置。matlab中无法使用中文,需要对字符集进行设置。 

plt.xticks()可以自定义坐标刻度,将刻度以数组的形式传入,并且可以传入自定义显示的刻度值 

设置坐标轴刻度的位置:通过axes对象.xaxis获取到x轴,并通过set_ticks_position()方法来设置位置,可选位置有:top,bottom ,both,default,none,对应的y轴刻度有:left,right,both,default,none 

# 设置行内显示

%matplotlib inline  

plt.rcParams['font.sans-serif'] = ['SimHei']    # 设置字符集显示中文

plt.rcParams['axes.unicode_minus'] = False      # 设置负号正确显示

 

x = np.linspace(-5, 5, 50)        

y1 = 2*x + 1    

y2 = x**2   

 

plt.figure(num=3, figsize=(10, 5))   

plt.plot(x, y2)     

plt.plot(x, y1, color='red', linewidth=1.0, linestyle='--')

plt.xlabel('x轴')                                           # 设置显示x轴标签

plt.xlim(-2,2)                                              # 设置x轴的范围为-2~2

plt.xticks([-2,-1,0,1,2])                                   # 设置x轴刻度

axes=plt.gca()

axes.xaxis.set_ticks_position('top')                        # 设置x坐标显示在上边框

plt.ylabel('y轴')

plt.ylim(-5,5)                                              # 设置y轴的范围为-5~5

plt.yticks([-3,-1,0,1,3],['低','较低','中等','高','较高'])     # 自定义刻度值

axes.yaxis.set_ticks_position('left')                       # 设置y坐标显示在左边框

         

 

我们还可以对图片的四个边框进行设置,通过plt.gca()获取轴系对象axes,通过.spines['right']获取右边框,之后可以set_color来设置其颜色,用set_position()来设置边框位置 

axes.spines['right'].set_color('none')                      # 获取并设置右边框透明

axes.spines['top'].set_color('none')

axes.spines['bottom'].set_position(('data', 0))             # 将底部边框放到x=0的位置

axes.spines['left'].set_position(('data',0))                # 将左边框放到y=0的位置

 

 

3、图例和标注 

在使用plt.plot()进行函数绘制时可以添加label属性来定义曲线的名称。 

通过plt.legend()在图片中显示图例,其loc属性定义图例的位置,值有'best' : 0,'upper right' : 1, 'upper left' : 2, 'lower left' : 3, 'lower right' : 4, 'right' : 5, 'center left' : 6, 'center right' : 7, 'lower center' : 8, 'upper center' : 9, 'center' : 10,其中best代表自动分配最佳位置 

plt.plot(x, y1, label='linear')

plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='square')

plt.legend(loc='upper right') 

也可以将plot()结果保存为l1,l2对象,再传入legend函数中的handles属性,这样legend函数可以对图中指定的线条对象添加图例,并通过labels属性设置图例的内容 

l1, = plt.plot(x, y1)

l2, = plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')

# 对指定线条对象添加图例

plt.legend(handles=[l1,l2,], labels=['linear','square'], loc='best') 

通过plt.annotate()函数在图片中添加注释,第一个参数为注释的内容,fontsize注释大小,xycoords表示注释点的位置的表示方式,data代表根据数据,xy代表传入的数据,textcoords='offset points'代表注释的位置为根据点偏移,xytext设置偏移值,arrowprops以dict方式传入箭头的类型和弧度属性 

通过plt.text()在图片中添加文本,前两个参数为文本的位置,第三个参数为文本内容,fontdict对文本字体、颜色进行设置,ha='center'设置居中对齐,va='bottom'设置向底部对其 

plt.scatter([1],[1],s=100,color='orange')

# 添加自定义注释

plt.annotate('x²=2x-1',fontsize=20,xycoords='data',xy=(1,1),

             textcoords='offset points',xytext=(20,-30),

             arrowprops=dict(arrowstyle='->',connectionstyle='arc3,rad=.2'))

# 添加文本

plt.text(0.5,-1,"This is a text",fontdict={'size':15,'color':'green'},ha='center', va='top')

 

 

4、绘制图像 

散点图 

通过scatter()绘制散点图,s属性为点的大小,c为点的颜色,alpha点的不透明度,marker指定点的形状 

n = 1024    # data size

X = np.random.normal(0, 1, n) # 每一个点的X值

Y = np.random.normal(0, 1, n) # 每一个点的Y值

C = np.arctan2(Y,X)           # 为每个点生成颜色

plt.scatter(X, Y, s=75, c=C, alpha=0.5, marker='o')

 

plt.show() 

 

条形图 

通过plt.bar()函数绘制条形图,前两个参数传入柱状图的x位置和y的值的数组,facecolor属性设置主题颜色,edgecolor设置边框颜色 

n = 10

X = np.arange(n)        # X取1~12

Y1 = np.array([8,9,12,6,5,10,11,13,4,2])

Y2 = np.array([5,6,8,3,14,10,3,2,1,4])

 

plt.bar(X, Y1, facecolor='blueviolet', edgecolor='orange')

plt.bar(X, -Y2)

 

# 在柱状图顶部添加文本标注

for x, y in zip(X, Y1):

    plt.text(x, y , y, ha='center', va='bottom')

    

plt.show() 

 

如上右图所示,通过plt.hist(data)可以绘制数据的统计分布直方图,参数bins指定划分的统计区间,为数字时代表划分为几个区间,为数组时代表指定具体的区间。 

plt.hist(data, bins=10)    # 划分区间的个数

plt.hist(data, bins=[0, 500, 1000, 1500, 2000, 2500, 3000])    # 指定具体分组区间

 

等高线图 

等高线的数据是三维数据,X,Y为自变量,Z为因变量函数值,根据函数值的不同显示相同的值作为等高线 

通过plt.contourf()函数进行颜色的填充,前三个参数为对应地X、Y、Z的值,cmap为填充的颜色,这里使用了matlabplot提供的一个颜色映射方案,根据值的由小到大映射为从蓝到红色 

plt.contour()进行等高线的绘制,colors='black'线条颜色为黑色,linewidth=.5线条宽度为0.5 

通过clabel()绘制文本,inline将文本填充到线条内 

通过colorbar()函数可以为图片添加一个函数值对应颜色条 

n = 256

x = np.linspace(-3, 3, n)

y = np.linspace(-3, 3, n)

X,Y = np.meshgrid(x, y)     # 编制为256×256的网格,并把对应的坐标值返回给X、Y数组

def fun(x,y):               # 定义函数值Z,是一个三维函数椭圆抛物面

    return x**2+y**2

 

F = plt.contourf(X, Y, fun(X, Y), 8, alpha=.75,cmap='RdBu')             # 进行颜色填充

C = plt.contour(X, Y, fun(X, Y), 8, colors='black', linewidth=.5)       # 绘制等高线

plt.clabel(C, inline=True, fontsize=10)                                 # 标注文本

plt.colorbar(F)                                                         # 添加一个colorbar

plt.show() 

 

三维图像 

在绘制3D图形前需要额外引入一个包Axes3D,通过它来将当前的图像转化为3D图 

同样3D图需要三维数据,X、Y编制为网格是自变量,Z是函数值 

通过plt.plot_surface()绘制3D图形,属性rstride 和 cstride 分别代表 row 和 column 的跨度,跨度越小,图形上的网格越密集,cmap为函数值的配色映射方案 

通过等高线的绘制函数plt.contour()可以为3D图形在平面绘制投影,zdir='z'代表沿着Z轴进行投影,这样投影会出现在X-Y平面上,offset代表投影的偏移位置 

 

import matplotlib.pyplot as plt

import numpy as np

from mpl_toolkits.mplot3d import Axes3D         #引入3D绘图库

%matplotlib inline

 

fig = plt.figure()

ax = Axes3D(fig)                                # 将当前图像转化为3D

 

X = np.arange(-10, 10, 0.5)

Y = np.arange(-10, 10, 0.5)

X, Y = np.meshgrid(X, Y)            # 编制 X-Y 平面的网格

Z = np.sqrt(X ** 2 + Y ** 2)        # Z值,定义为抛物面图形

ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='hsv')  # 绘制3D图

ax.contourf(X, Y, Z, zdir='z', offset=0, cmap='hsv')        # 添加沿Z轴方向的投影

plt.show() 

 

绘制动画 

绘制动画需要从matplotlib中额外引入animation库 

之后先绘制其中一帧的图像,比如这里要绘制sinx的动画,先在0~2Π取自变量x数组,再绘制其sinx的曲线line 

接着定义动画初始帧的显示函数init(),返回初始的line对象。然后定义其每一帧的图像显示函数animate,其参数i代表第i帧,根据i返回不同的line对象。 

最后通过animation.FuncAnimation()绘制图像,其参数fig为之前创建的图片对象,init_func为初始化显示函数,func为每一帧的显示函数,interval为更新频率(单位ms),frames为动画一共有多少帧,blit为True代表每次只更新有变化的点 

最后将返回的ani对象的save()方法将其保存为gif,这里使用的writer为imagemagick 

import numpy as np

from matplotlib import pyplot as plt

from matplotlib import animation                 # 引入动画库

%matplotlib inline

 

fig,ax=plt.subplots()                            # 创建画布

 

x=np.arange(0,2*np.pi,0.01)                      # 从0~2Π每隔0.01取一个数

line,=ax.plot(x,np.sin(x))                       # 绘制sinx的图像

 

def init():                                      # 定义初始帧显示函数

    line.set_ydata(np.sin(x))

    return line,

def animate(i):                                  # 定义每一帧的显示函数

    line.set_ydata(np.sin(x+i/10))

    return line,

 

# 绘制动画

ani=animation.FuncAnimation(fig=fig,init_func=init,func=animate,interval=20,frames=100,blit=True)

ani.save('sinx.gif',writer='imagemagick')        # 保存动画为gif

 

plt.show() 

 

5、多张图片 

通过plt.subplot()可以划分为多个子图并选中其中的某个位置,例如subplot(2,2,1)代表创建2×2的子图,并且选中其中的第一个子图,也可以省略中间的逗号:subplot(224)代表选中2×2个子图中的第四个。除了直接通过plt对象绘制子图外,subplot可以返回子图对象,可以通过子图对象调用plot()来绘图。 

import matplotlib.pyplot as plt

%matplotlib inline

 

plt.figure()

 

# 选中2×2子图中的第一个并画一条线

plt.subplot(2,2,1)

plt.plot([0,1],[2,3])

# 选中2×2子图的第四个画一条线

ax2=plt.subplot(224)

ax2.plt.plot([2,1],[3,4])

 

plt.show() 

 

注意这里的划分并不是真正的分割图像,只是为了定位子图而假定将整个图像进行划分。例如下面的代码首先将画布认为2行1列选中第一块,就是上面的一行大的,再将其认为2行3列选择第四块,那就是第二行的第一个。通过不同的划分和选择可以得到不同大小与不同位置的子图。如果涉及到冲突的区域,后面的子图会将之前的子图覆盖掉。 

# 划分为2行1列,选中第一块

plt.subplot(2,1,1)

plt.plot([0,1],[2,3])

# 划分为2行3列,选中第四块

plt.subplot(234)

plt.plot([2,1],[3,4]) 

     

通过subplot2grid()方法可以更加方便的划分和选择子图,如下所示subplot2grid((3, 3), (0, 0), colspan=3)表示将图片分为3×3区域,从第0行0列开始,横向跨越colspan列数为3,纵向跨越rowspan行数默认为1。 

注意在一整张图中可以通过title()、xlabel()、ylabel()来设置标题和坐标名,但是在子图中需要在函数名之前加一个set_ 

ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)

ax1.plot([1, 2], [1, 2])    # 画小图

ax1.set_title('ax1_title')  # 设置小图的标题

 

ax2 = plt.subplot2grid((3,3), (2,1),colspan=2)

ax2.plot([2,1],[1,0])

ax2.set_xlabel('ax2_x')    # 设置小图的坐标轴名

ax2.set_ylabel('ax2_y') 

 

gridspec()函数可以让我们像使用python数组那样方便地选择子图区域。使用前先从matplotlib中引入该模块,通过Gridspec()函数将图像划分为区域,然后返回gs对象,通过gs对象可以像数组那样选择子区域。例如gs[1, :2],逗号之前代表对行序号的选择,如果只有一个数字代表选中全部序号为1的行,逗号之后为列,这里0:2代表选中从0到2列之前的所有列,其中从0开始可以省略。对应地如果选中指导结尾的话也可以省略,即gs[1, : ]。如果序号为-2,代表选中倒数第二个 

import matplotlib.pyplot as plt

import matplotlib.gridspec as gridspec      # 引入库

%matplotlib inline

 

plt.figure()

gs = gridspec.GridSpec(3, 3)                # 将图像划分为3×3个区域

ax1 = plt.subplot(gs[0, :])                 # 选中第0行,所有列

ax2 = plt.subplot(gs[-1, -2])               # 选中倒数第1行,倒数第2列

plt.show() 

 通过subplots()可以一次性创建并返回多个子图对象,如下所示为划分四个子图并且依次返回给ax11~ax22四个对象,并且四个对象的位置不能乱。其中sharex代表图像共享X坐标轴。plt.tight_layout()代表紧凑显示 

f, ((ax11, ax12), (ax21, ax22)) = plt.subplots(2, 2, sharex=True, sharey=True)

ax11.scatter([1,2], [1,2])

plt.tight_layout()

plt.show() 

 

画中画:通过figure对象的add_axes()可以在图片中添加另一个图片,其传入的参数为图片所在画布的四个边框的位置比例,返回创建的子图对象ax,利用ax进行绘制 

x=[0,1]

y=[2,3]

fig = plt.figure()

 

ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8])    # 创建一个大图对象

ax1.plot(x, y, 'r')                         # 大图绘制

ax2 = fig.add_axes([0.2, 0.6, 0.25, 0.25])  # 创建小图

ax2.plot(x, y, 'b')                         # 小图绘制

 

plt.show() 

 

子图拷贝:通过子图对象ax的twinx()函数可以在相同位置拷贝x轴相同的另一个重叠的ax对象,只不过y轴放到了对称的位置,最后两个子图会重叠显示 

fig, ax1 = plt.subplots()

ax2 = ax1.twinx()                       # 拷贝ax对象

 

ax1.plot([0,1], [2,3], 'g-')            # 在原图中绘制

ax1.set_xlabel('X data')

ax1.set_ylabel('Y1 data', color='g')    # 原图的y轴在左侧

ax2.plot([0,1], [3,2], 'b-')            # 拷贝对象中绘图

ax2.set_ylabel('Y2 data', color='b')    # 拷贝子图的y轴在右侧

plt.show()

你可能感兴趣的:([转载] 在Python中使用Matplotlib绘制常见图表)