原文链接: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()
推荐阅读:
编码: 一个隐藏了30多年的bug,Windows含蓄说过某通不行?