数据可视化~matplotlib显示多个子图

原文链接:http://www.juzicode.com/archives/2532

在matploblib中,绘图操作通常可以用pyplot.plot()实现,但是如果需要在一个画布上绘制多张图片,则需要用到subplots()或subplot()方法。

1、subplots()

1.1、生成单个子图

利用pyplot.subplots(),不带参数时,默认参数nrows=1,ncols=1,表示生成1行1列的1个子图,绘图效果同pyplot.plot():

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

if __name__ == '__main__':
    plt.rc('font',family='Youyuan',size='15')
    plt.rc('axes',unicode_minus='False')
    t = np.arange(-2.0, 2.0, 0.01)
    s = np.sin(2 * np.pi * t)

    fig, ax = plt.subplots() #单次调用同时生成图像、画图
    ax.plot(t, s,'--g')#注意,这里用ax.plot(),不再是pyplot.plot(),不能使用xlabel,ylabel等
    ax.set(xlabel='t', ylabel='s',title='y=sin(x) by 桔子code ')
    ax.grid()#添加grid

    fig.savefig("matplot-sin.png")#保存图片
    plt.show()

上面的例子是使用生成的ax实例操作画图,还可以直接利用pyploy.plot()画图:

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

if __name__ == '__main__':
    plt.rc('font',family='Youyuan',size='15')
    plt.rc('axes',unicode_minus='False')
    t = np.arange(-2.0, 2.0, 0.01)
    s = np.sin(2 * np.pi * t)

    fig, ax = plt.subplots() 
    plt.plot(t,s,'--g') #这时plt.plot操作画图的对象仍然是ax
    plt.xlabel('t')
    plt.ylabel('s')
    plt.title('y=sin(x) by 桔子code')
    plt.grid()
    plt.savefig('matplot-subplot-sinx.jpg')
    plt.show()

2段代码绘图效果是一样的:

ax.plot()用法同pyplot.plot(),内部使用的参数用法一致。

可以利用pyplot.subslots()生成的fig实例,使用fig.savefig()方法保存图像到本地。

1.2、生成多个子图

如果在subplots()入参中传入第1位置参数nrows和第2个位置参数ncols,表示要生成nrows*ncols个子图,下面的例子中生成nrows=2,ncols=2的4个子图,fig,ax = plt.subplots(2,2):

print('\n-----欢迎来到juzicode.com')
print('-----公众号: 桔子code/juzicode \n')   

import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
    plt.rc('font',family='Youyuan',size='9')
    plt.rc('axes',unicode_minus='False')
    
    t=np.arange(0.0,2.0,0.1)
    s=np.sin(t*np.pi)
    
    fig,ax = plt.subplots(2,2) #生成2行2列4个子图,子图ax是从[0,0] 开始编号的
    ax[0,0].plot(t,s,'r--')    #第0行第0列,本例子中左上角
    ax[0,0].set_title('第1个子图 by juzicode.com')
    ax[0,1].plot(t,s,'g-')     # 
    ax[0,1].set_title('第2个子图 ')    
    ax[1,0].plot(t,s,'b-.')    # 
    ax[1,0].set_title('第3个子图 ')
    ax[1,1].plot(t,s,'y:')     # #第1行第1列,本例子中右下角
    ax[1,1].set_title('第4个子图 by 桔子code')

使用fig,ax = plt.subplots(2,2)生成的ax实例,使用时其行、列下标是从0开始的,这点和后面的subplot()生成的子图位置下标从1开始是有差异的。

需要和后面介绍的subplot()方法区分的是,使用subplots()方法构建的子图,不指定某个ax而直接使用pyplot.title()设置单个子图中的标题是无效的,下面这个错误的例子中可以看到前面3个子图的title并没有生效(第21,24,27行):

import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
    plt.rc('font',family='Youyuan',size='9')
    plt.rc('axes',unicode_minus='False')
    
    t=np.arange(0.0,2.0,0.1)
    s=np.sin(t*np.pi)
    
    fig,ax = plt.subplots(2,2) #生成2行2列4个子图,子图ax是从[0,0] 开始编号的
    ax[0,0].plot(t,s,'r--')    #第0行第0列,本例子中左上角
    plt.title('第1个子图 by juzicode.com')   #第1张子图标题未生效
    
    ax[0,1].plot(t,s,'g-')     # 
    plt.title('第2个子图 ')    #第2张子图标题未生效
    
    ax[1,0].plot(t,s,'b-.')    # 
    plt.title('第3个子图 ')    #第3张子图标题未生效
    
    ax[1,1].plot(t,s,'y:')     # #第1行第1列,本例子中右下角
    plt.title('第4个子图 by 桔子code') #仅仅该子图标题生效

    plt.savefig('matplot-subplots-4grid2a.jpg')
    plt.show()

2、subplot()

subplot()和subplots()相比仅仅少了个字母s,用法差别较大,subplot()方法的调用方法有如下几种形式:

subplot(nrows, ncols, index, **kwargs)
subplot(pos, **kwargs)
subplot(**kwargs)
subplot(ax)

比较常用的是第1种和第2种,第1种形式表示要画nrows行、ncols列的子图,其中index表示从1开始的第z个子图。该方法第一次调用时就会自动生成nrows行ncols列的图框。第2种形式用3位数pos=xyz表示,x表示水平方向划分的ncols,y表示垂直方向的nrows,其中z<=x*y,且z取值只能从1~9,这里是一个z值大于9的错误示例:Python错误集锦:ValueError: Single argument to subplot must be a three-digit integer, not 3411

subslot()生成的实例ax也可以用变量保存供后面使用。

调用subslot(xyz)后,表示当前要操作的对象是第z个子图,这之后的pyplot.plot()的画图对象就是第z个子图,可以用pyplot.title()设置第z个子图的标题,pyplot.xlabel()设置第z个子图的x标签,pyplot.ylabel()设置第z个子图的y标签。但pyplot.savefig()保存的是整个图片,而不是某个子图。

1.1、生成多个子图

假设要生成2行2列4个规则子图,其pos参数就是如下图设置,x=2,y=2,z=1~4从左上角开始:

示例代码:

import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
    plt.rc('font',family='Youyuan',size='9')
    plt.rc('axes',unicode_minus='False')
    t=np.arange(0.0,2.0,0.1)
    s=np.sin(t*np.pi)
    
    ax1 = plt.subplot(221) #ax1对应的是2行2列中的第1个grid子图    
    plt.plot(t,s,'g-') 
    plt.title('第1个子图 by juzicode.com')
    
    ax2 = plt.subplot(222) #单入参形式指定第2个子图
    plt.plot(t,s,'r--')    #虽然没有指明画图对象,紧邻最近的是“222”,对应的第2个grid
    plt.xlabel('t2') #设置只对第2个grid有效
    plt.ylabel('s2') #设置只对第2个grid有效        
    plt.title('第2个子图 ')
    
    plt.subplot(223) #
    plt.plot(t,s,'y:')
    plt.title('第3个子图 by 桔子code')
    
    plt.subplot(224, facecolor='yellow')
    plt.plot(t,s,'b*')     #画第4个grid
    plt.xlabel('t') #设置只对第4个grid有效
    plt.ylabel('s=sin(t)')

    plt.savefig('matplot-subplot-4grid.jpg')
    plt.show()

plt.show()运行显示图片和pyplot.savefig()保存的图片效果:

1.2、生成不规则子图

前面的方法生成的子图是规则的m行n列,有时候可能在第1行需要2个子图,而第2行只需要1个子图,在调用plt.subplot(221)和 plt.subplot(222)之后,如果要在第2行只放一个子图,需要重新计算pos,前面2个调用可以合起来看成plt.subplot(211),所以在第2行的子图就是plt.subplot(212):

print('\n-----欢迎来到juzicode.com')
print('-----公众号: 桔子code/juzicode \n')   

import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
    plt.rc('font',family='Youyuan',size='9')
    plt.rc('axes',unicode_minus='False')
    t=np.arange(0.0,2.0,0.1)
    s=np.sin(t*np.pi)
    
    ax1 = plt.subplot(221) #ax1对应的是2行2列中的第1个grid子图   
    plt.plot(t,s,'g-') 
    plt.title('第1个子图 by juzicode.com')
    
    ax2 = plt.subplot(222) #单入参形式指定第2个子图
    plt.plot(t,s,'r--')    #虽然没有指明画图对象,紧邻最近的是“222”,对应的第2个grid
    plt.xlabel('t2') #设置只对第2个grid有效
    plt.ylabel('s2') #设置只对第2个grid有效        
    plt.title('第2个子图 ')
    
    plt.subplot(212) # 第2行重新规划为1个子图,xyz需要重新计算,这里看成是第2行的第1列,x=2,y=1,z=2
    plt.plot(t,s,'y:')
    plt.title('第3个子图 by 桔子code')

    plt.show()

接下来再看下另外一种情况:第1行放第1张子图,第2行放第2,3,4张子图。

首先确定一共画2行,所以x=2;第1行只有1张子图,所以y=1,z=1;第2行放置3张子图,所以y=2,这个时候z需要按照3列的方式来确定,第1行也要看成是3列,所以第2行开始的第1个图是z=4,第2个图是5,第3个图是6,完整的布局就是下图这样:

代码如下:

print('\n-----欢迎来到juzicode.com')
print('-----公众号: 桔子code/juzicode \n')   

import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
    plt.rc('font',family='Youyuan',size='9')
    plt.rc('axes',unicode_minus='False')
    t=np.arange(0.0,2.0,0.1)
    s=np.sin(t*np.pi)
    
    ax1 = plt.subplot(211) #ax1对应的是2行2列中的第1个grid子图   
    plt.plot(t,s,'g-') 
    plt.title('第1个子图 by juzicode.com')
    
    ax2 = plt.subplot(234) #单入参形式指定第2个子图
    plt.plot(t,s,'r--')    #虽然没有指明画图对象,紧邻最近的是“222”,对应的第2个grid      
    plt.title('第2个子图 ')
    
    plt.subplot(235) # 第2行重新规划为1个子图,xyz需要重新计算,这里看成是第2行的第1列,x=2,y=1,z=2
    plt.plot(t,s,'y:')
    plt.title('第3个子图 by 桔子code')
    
    plt.subplot(236, facecolor='yellow')
    plt.plot(t,s,'b*')     #画第4个grid
 
    plt.show()

发表评论

电子邮件地址不会被公开。 必填项已用*标注