前言
上一篇博客中说到,matplotlib中所有画图元素(artist)分为两类:基本型和容器型。容器型元素包括三种:figure、axes、axis。一次画图的必经流程就是先创建好figure实例,接着由figure去创建一个或者多个axes,然后通过axes实例调用各种方法来添加各种基本型元素,最后通过axes实例本身的各种方法亦或者通过axes获取axis实例实现对各种元素的细节操控。
本篇博客继续上一节的内容,展开介绍三大容器元素创建即通过三大容器可以完成的常用设置。
1、figure
1.1 创建figure
在上文中我们一直提到的figure指的是Figure类的实例化对象,当然我们一般不会直接去实例化Figure类,因为这样创建的Figure实例对象不能纳入序列中共同管理。matplotlib中提供了多种方法创建figure,其中属pyplot模块中的figure()方法最常用也最方便,下面我们来说说这个方法。
figure方法参数如下:
num:整型或字符串类型,可选参数,默认为None。这个参数课可以理解为是figure的身份标识,即id。当值为None时,会创建一个figure实例,该实例的num值会在已有基础上自增;当该参数不为None时,如果与已有的num值重复,则会切换到该figure使其处于激活状态,并返回一个该figure的引用;如果传入的参数为字符串,该字符串将会被设置为figure的标题。
figsize:tuple类型,可选参数,默认为None。通过figsize参数可以设置figure的size,即(width, height),单位为inch。当值为None时,采用默认size。
dpi:整型,可选参数,用于设置图片像素。
facecolor:可选参数,用于设置前景色,默认为白色。
edgecolor:可选参数,用于设置边框颜色,默认为黑色。
frameon:bool类型,可选参数,表示是否绘制窗口的图框,默认是。
FigureClass:传入一个类名,当使用自定义的类实例化figure时使用,默认为matplotlib.figure.Figure。
clear:bool类型,可选参数,默认为False。如果值为True的话,如果figure已存在,则会清除该figure的全部内容。
from matplotlib import pyplot as plt
import matplotlib as mpl
import numpy as np
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 中文字体支持
fig = plt.figure(figsize=(4,2), facecolor='grey') # 创建figure
fig.add_axes((0,0,1,1)) # 必须添加axes后才能显示
plt.show()
在jupyter编辑器中,空白的figure是不会显示的,所以必须在figure中至少添加一个axes。
1.2 figure的常用设置
1.2.1 set方法通用设置
创建figure时的各个参数基本都可以通过figure实例对象中对应的对应的set方法进行修改,例如set_facecolor()用来设置前景色,set_size_inches()用来设置大小等。
设置前景色:
fig = plt.figure(figsize=(4,2))
fig.set_facecolor('grey') # 设置前景色
plt.plot()
plt.show()
fig = plt.figure()
fig.set_size_inches(2,3) # 设置大小
plt.plot()
plt.show()
1.2.2 设置figure标题
fig = plt.figure(figsize=(4,2))
fig.suptitle("figure title", color='red') # 设置figure标题
plt.plot()
plt.show()
1.2.3 添加文本
fig = plt.figure(figsize=(4,2))
fig.text(0.5,0.5,"figure text",color='red') # 设置figure标题,前两个参数分别表示到左边框和上边框的百分比距离
plt.plot()
plt.show()
1.2.4 设置图例
fig = plt.figure(figsize=(5,3))
axes = fig.add_axes((0,0,0.8,1))
x = np.linspace(0, 10, 1000)
line1, = axes.plot(x, np.sin(x)) # 注意,line1后面有个逗号,因为plot()方法返回值是一个列表
line2, = axes.plot(x, np.cos(x))
fig.legend([line1, line2],['sin', 'cos'])
plt.show()
1.2.5 设置子图间距
fig, axes = plt.subplots(2,2,facecolor='grey')
fig.subplots_adjust(left=None, # 设置画图区域与figure上下左右边框的比例距离
bottom=None,
right=None,
top=None,
wspace=0.3, # 子图间水平方向距离
hspace=1) # 子图间垂直方向距离
plt.show()
2、axes
axes可以认为是figure这张画图上的子图,因为子图上一般都是坐标图,所以我更愿意理解为轴域或者坐标系。
2.1 创建axes
一个figure可以有多个axes, 无论是pyplot模块还是figure实例内都定义有多种创建axes的方法。 (1) plt.axes()
plt.axes()是指pyplot模块中的axes()方法,该方法会在当前激活的figure中创建一个axes,并使创建好的axes处于激活状态。当传入的第一个位置参数为空时,该方法会创建一个占满整个figure的axes;通常我们可以传入一个tuple参数(left, botton, width, height)作为第一个位置参数,tuple中四个元素分别表示与figure左边框比例距离,边框宽度占figure宽度的比例,宽度比例,高度占figure高度的比例。通过这种方式添加axes时,matplotlib会自动创建一个axes,然后将创建好的axes按照给定的位置和size添加到figure中,最后返回一个axes的引用。
fig1 = plt.figure(figsize=(4,2), facecolor='grey')
ax1 = plt.axes((0.1, 0.1, 0.8, 0.7), facecolor='green')
fig2 = plt.figure(figsize=(4,2), facecolor='yellow')
ax2 = plt.axes((0.1, 0.1, 0.8, 0.8), facecolor='red') # 这个axes将会被覆盖在下面
plt.show()
注意,如果在相同区域添加axes,后面添加的axes会把前面添加的axes覆盖。
fig = plt.figure(figsize=(4,2), facecolor='grey')
ax1 = plt.axes((0.1, 0.1, 0.8, 0.8), facecolor='green')
ax2 = plt.axes((0.1, 0.1, 0.8, 0.7), facecolor='red') # 这个axes将会被覆盖在下面
plt.show()
(2) figure.add_axes()
figure.add_axes()方法的作用是将一个axes添加到figure中,这一方法可以传入一个已创建好的axes作为第一个参数,add_axes会将传入的axes添加到figure中,但这种情况使用不多。在大多数情况下,我们会如同上述在plt.axes()方法中那样传递一个tuple参数(left, botton, width, height)作为第一个位置参数。同样,如果在相同区域添加axes,后面添加的axes会把前面添加的axes覆盖。
fig = plt.figure(figsize=(4,2), facecolor='grey')
fig.add_axes((0.1, 0.1, 0.3, 0.7), facecolor='green') # 这个axes将会被覆盖在下面
fig.add_axes((0.5, 0.1, 0.3, 0.7), facecolor='red')
plt.show()
(3) plt.subplot与plt.subplots()
plt.subplot和plt.subplots()是在pyplot模块中定义的两个方法,两个方法都是将figure划分为多行多列的网格,然后添加axes,但功能和用法却有些许不同。
plt.subplot()
plt.subplot主要包括三个参数(nrows, ncols, index),分别表示行数、列数和索引,该方法会根据指定的行列数对figure划分为网格,让后在指定索引的网格中创建axes,并返回该axes的引用。索引是从1开始从左往右,从上到下递增,例如plt.subplot(2,2,4)表示将figure划分为两行两列的4个网格,并在第4个子网格中创建一个axes然后返回。注意,每一次调用plt.subplot()方法只会在指定索引的子网格中创建axes,而不是在所有子网格中都创建axes,如果需要在多个子网格中创建axes,那么就需要多次调用plt.subplot()指定不同的索引。另外,如果nrows, ncols, index三个参数都小于10,可以将这三个参数合并成一个3位整数来写,例如plt.subplot(2,2,4)与plt.subplot(224)是完全等效的。
fig = plt.figure(figsize=(4,4), facecolor='grey')
ax1 = plt.subplot(221,facecolor='green')
ax2 = plt.subplot(224,facecolor='red')
plt.show()
plt.subplots()
与plt.subplot()不同的是,plt.subplots()会重新创建一个figure,然后将创建好的figure按照指定的行列数划分为网格,并在每一个子网格中各创建一个axes,最终同时返回figure和所有子网格中axes组成的numpy数组中。
fig, axes = plt.subplots(2,2,facecolor='grey')
fig.suptitle('figure title')
print(type(axes))
axes[0,0].set_facecolor('green')
axes[1,1].set_facecolor('red')
plt.show()
plt.subplots()还有一对参数sharex, sharey用于设置是否共享x轴或y轴,这对参数有取值可以使bool型或'none', 'all', 'row', 'col'这4个字符串中的一个,分别有以下含义:
False 和 'none'表示不共享,任何子图中的x轴或y轴都是相互独立的;
True 和 'all'表示所有子图共享x轴或y轴;
'row' 表示同一行的子图共享x轴或y轴;
'col' 表示同一列的子图共享x轴或y轴;
fig, axes = plt.subplots(2,2,sharex=True,sharey=True,facecolor='grey')
fig.suptitle('figure title')
axes[0,0].set_facecolor('green')
axes[1,1].set_facecolor('red')
plt.show()
(4) figure.add_subplot()与figure.subplots()
figure.add_subplot与上文中介绍过的plt.subplot()无论是功能还是使用方法上都是几乎一样的,唯一区别就是plt.subplot()的目标是在当前激活的figure,而figure.add_subplot()是调用add_subplot()方法的figure。
fig = plt.figure(figsize=(4,4), facecolor='grey')
ax1 = fig.add_subplot(221,facecolor='green')
ax2 = fig.add_subplot(224,facecolor='red')
plt.show()
figure.subplots()的功能、用法又与上文中介绍过的plt.subplots()很相似,区别在于figure.subplots()不会重新创建一个figure,而是对当前的figure进行划分网格并在每一个网格中都创建一个axes。
fig = plt.figure(facecolor='grey')
axes = fig.subplots(2,2)
axes[0, 0].set_facecolor('green')
axes[1, 1].set_facecolor('red')
plt.show()
2.2 axes的常用设置
axes是matplotlib作图中众多元素的核心,可以说,大多数的设置都可以通过axes来完成。
2.2.1 设置标题
fig = plt.figure(facecolor='grey')
fig.suptitle("figure 标题", color='red')
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
ax1.set_title(' 图 1') # 设置标题
ax2.set_title(' 图 2')
plt.show()
2.2.2 设置图例
fig = plt.figure(figsize=(5,3))
axes = fig.add_axes((0,0,0.8,1))
x = np.linspace(0, 10, 1000)
line1, = axes.plot(x, np.sin(x))
line2, = axes.plot(x, np.cos(x))
axes.legend([line1, line2],['正弦', '余弦'])
plt.show()
2.2.3 设置坐标轴名称
fig = plt.figure(figsize=(4,1))
axes = fig.add_axes((0,0,1,1))
axes.set_xlabel('x轴', fontsize=15)
axes.set_ylabel('y轴', fontsize=15, color='red')
plt.show()
2.2.4 设置坐标轴范围
fig = plt.figure(figsize=(6,2))
axes = fig.add_axes((0,0,0.8,1))
x = np.linspace(-3, 5, 1000)
line1, = axes.plot(x, np.sin(x))
axes.set_xlim((-3,5)) # 设置横坐标范围
axes.set_ylim((-3,3)) # 设置纵坐标范围
plt.show()
2.2.5 隐藏边框
fig = plt.figure(figsize=(6,2))
axes = fig.add_axes((0,0,0.8,1))
x = np.linspace(-10, 10, 1000)
line1, = axes.plot(x, np.sin(x))
axes.set_xlim((-10,10)) # 设置横坐标范围
axes.set_ylim((-2,2)) # 设置纵坐标范围
axes.spines['right'].set_color('none') #隐藏掉右边框线
axes.spines['top'].set_color('none') #隐藏掉左边框线
plt.show()
2.2.6 显示网格
fig = plt.figure(figsize=(6,2))
axes = fig.add_axes((0,0,0.8,1))
x = np.linspace(-10, 10, 1000)
line1, = axes.plot(x, np.sin(x))
axes.set_xlim((-10,10)) # 设置横坐标范围
axes.set_ylim((-2,2)) # 设置纵坐标范围
axes.grid(True)
plt.show()
2.2.7 添加注释
fig = plt.figure(figsize=(6,2))
axes = fig.add_axes((0,0,0.8,1))
x = np.linspace(-10, 10, 1000)
line1, = axes.plot(x, np.sin(x))
axes.set_xlim((-10,10)) # 设置横坐标范围
axes.set_ylim((-2,2)) # 设置纵坐标范围
axes.grid(True)
axes.annotate('原点', xy=(0, 0), # xy是指向点的坐标
xytext=(2.5, -1.5), # xytext注释文字的坐标
arrowprops=dict(facecolor='red'))
plt.show()
3、axis
axis在matplotlib中是一种类似于坐标轴的概念,负责处理轴标签、刻度线、刻度标签、网格线的绘制。在大多数情况下,axis我们手动创建,在创建axes时会一并创建axis,通过axes的实例对象即可调用axes内的axis实例。通过axis实例,我们可以实现更加多样化、细微的图标操作。
通过axes实例可以调用get_xaxis()方法获取axis实例,然后实现对label等对象的操作。
3.1 axis常用设置
3.1.1 设置坐标轴名称
fig = plt.figure(figsize=(4,2), facecolor='grey')
axes = fig.add_axes((0, 0,1,1))
# x轴
axes.get_xaxis().get_label().set_text('x axis')
axes.get_xaxis().get_label().set_color('red')
axes.get_xaxis().get_label().set_fontsize(16)
# y轴
axes.yaxis.get_label().set_text('y axis')
axes.yaxis.get_label().set_color('blue')
axes.yaxis.get_label().set_fontsize(16)
plt.show()
3.1.2 设置坐标轴刻度标签样式
fig = plt.figure(figsize=(4,2), facecolor='grey')
axes = fig.add_axes((0, 0,1,1))
# 设置x轴刻度标签
for tl in axes.get_xaxis().get_ticklabels():
tl.set_color('red')
tl.set_rotation(45)
tl.set_fontsize(16)
plt.show()
3.1.3 设置坐标轴刻度位置
import matplotlib.ticker as ticker
# Fixing random state for reproducibility
np.random.seed(19680801)
fig, ax = plt.subplots()
ax.plot(100*np.random.rand(20))
formatter = ticker.FormatStrFormatter('$%1.2f')
ax.yaxis.set_major_formatter(formatter)
for tick in ax.yaxis.get_major_ticks():
tick.label1.set_visible(False)
tick.label2.set_visible(True)
tick.label2.set_color('green')
plt.show()
3.1.4 设置坐标轴位置
fig = plt.figure(figsize=(6,2))
axes = fig.add_axes((0,0,0.8,1))
x = np.linspace(-10, 10, 1000)
line1, = axes.plot(x, np.sin(x))
axes.set_xlim((-10,10)) # 设置横坐标范围
axes.set_ylim((-2,2)) # 设置纵坐标范围
axes.spines['right'].set_color('none') #隐藏掉右边框线
axes.spines['top'].set_color('none') #隐藏掉左边框线
axes.xaxis.set_ticks_position('bottom') #设置坐标轴位置
axes.yaxis.set_ticks_position('left') #设置坐标轴位置
axes.spines['bottom'].set_position(('data', 0)) #绑定坐标轴位置,data为根据数据自己判断
axes.spines['left'].set_position(('data', 0))
plt.show()
4、总结
本文主要介绍matplotlib图表的三种容器元素:figure、axes、axis。figure是最底层的容器,相当于一张画布,在画布上,我们可以画多个axes,axes就是figure上的子图,每个axes都是一张独立的图表,每个axes包含多个axis,通过axis我们可以实现对图表更多细节上的操作。
理解了matplotlib图表三个层次的布局,我们就可以通过figure -> axes --> axis的流程完成图表在宏观层面的创建。在后续的博客中,将会继续介绍对图表更多更加细节化的设置以及如何画各种不同的统计图表。