一. Matplotlib基础知识
通常情况下,我们可以将一副Matplotlib图像分成三层结构:
- 第一层是底层的容器层,主要包括Canvas(画板)、Figure(画布、图片)、Axes(图表); 一个axes代表一个图表,包含一个plot,一个figure代表一张画布绘制一张图片,一张图片或一张画布可以有多个图表;canvas画板,摆放画布的工具。关系:画板→画布或图片→线条、饼图等图片;
- 第二层是辅助显示层,主要包括Axis(坐标轴)、Spines(绘图区边框线)、Tick(坐标刻度)、Grid(网格)、Legend(图例)、Title(标题)等,该层可通过set_axis_off()或set_frame_on(False)等方法设置不显示;
- 第三层是图像层,即通过plot、contour、scatter等方法绘制的图像。
Matplotlib绘制图表的构成如下图所示:
(一)底层容器层
容器层主要由Canvas、Figure、Axes组成:
- Canvas是位于最底层的系统层,在绘图的过程中充当画板的角色,即放置画布的工具。通常情况下,我们并不需要对Canvas特别的声明,但是当我需要在其他模块如PyQt中调用Matplotlib模块绘图时,就需要首先声明Canvas,这就相当于我们在自家画室画画不用强调要用画板,出去写生时要特意带一块画板。
- Figure是Canvas上方的第一层,也是需要用户来操作的应用层的第一层,在绘图的过程中充当画布的角色。当我们对Figure大小、背景色彩等进行设置的时候,就相当于是选择画布大小、材质的过程。因此,每当我们绘图的时候,写的第一行就是创建Figure的代码。
- Axes是应用层的第二层,在绘图的过程中相当于画布上的绘图区的角色。一个Figure对象可以包含多个Axes对象,每个Axes都是一个独立的坐标系,绘图过程中的所有图像都是基于坐标系绘制的。
1. 画布Figure
在Matplotlib中,整个图表是一个figure对象。我们可以用plt.figure
创建一个新的Figure,创建完之后会弹出一个空窗口。figure函数的调用方式如下:
matplotlib.pyplot.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True, FigureClass=<class'matplotlib.figure.Figure'>, **kwargs)
主要参数说明:
参数 | 属性 | 描述 |
---|---|---|
num | 整数或字符串,可选参数 | Num=n 选择图表 n 或创建图表 n |
figsize | 二维元组 | 创建指定大小的图像,单位:尺寸 |
dpi | 整数值 | 每英寸的像素数,默认 80 |
facecolor | 字符串 | 背景颜色 |
edgecolor | 字符串 | 边框颜色 |
frameon | 布尔值 | 是否显示边框 |
plt.figure有一些选项,特别是figsize,它用于确保当图片保存到磁盘时具有一定大小和横纵比,通过plt.gcf()函数即可得到当前Figure的引用。
(1)plt.subplot()
Figure只是弹出一个空白的窗口,不能通过Figure绘图,必须使用subplot()函数创建一个或多个subplot才行,如下示例:
ax1 = plt.subplot(2,2,1)
这条代码的意思是:创建的2×2的subplot,且当前选中的是4个subplot中的第一个(编号从1开始)。
subplot函数的具体调用方式如下:
matplotlib.pyplot.subplot(*args, **kwargs)
在一个图表中绘制多个子图时,此函数调用时传递的参数如下:
matplotlib.pyplot.subplot(nrows, ncols, plot_number, axisbg, polar, projection)
参数说明如下:
参数 | 描述 |
---|---|
nrows | nrows 表示图的行数 |
ncols | ncols 表示图的列数 |
plot_number | plot_number 表示第几个子图 |
axisbg | axisbg=color,表示所选子图背景颜色 |
polar | polar=False,是否为极地投影,默认值为False |
projection | 使用指定的投影方式,该方式使用之前需要已经注册(registered) |
绘图区分为 nrows 行和 ncols 列,从左到右、从上到下顺序对每个区域进行编号,左上区编号为 1。上述三个参数均小于 10 时,中间逗号可以省略,也可以保留。例如:
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import randn
plt.Figure()
ax1 = plt.subplot(2,2,1)
ax2 = plt.subplot(2,2,2)
ax3 = plt.subplot(2,2,3)
ax1.hist(randn(100), bins=20, color='k', alpha=0.3)
ax2.scatter(np.arange(30), np.arange(30)+3*randn(30))
ax3.plot(randn(50).cumsum(), 'k--')
plt.show()
(2)plt.subplots()
另外,我们也可以使用plt.subplots()函数,它可以创建一个新的Figure,并返回一个包含已创建的subplot对象的Numpy数组,可以轻松地对axes数组进行索引,就好像一个二维数组一样。如果用 subplots 创建了多个子图,那么 axes
就是一个列表,用索引列表元素的方法就能获取到每一个 axes,所以 axes 也能够写入循环中。plt.subplots()调用格式如下:
matplotlib.pyplot.subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
参数说明如下:
参数 | 属性 | 描述 |
---|---|---|
nrows | 整数 | subplot 网格行数,默认值为1 |
ncols | 整数 | subplot 网格列数,默认值为1 |
sharex | 布尔参量或字符串(“row”, “col”, “all”, 或“none”) | 若为 True:对所有子图共用 x 轴(最后一行除外),'all’等同于 True;‘None’等同于 False;若为‘col’每列子图共享 x 轴;若为’row’每行子图共享 x 轴 |
sharey | 布尔参量或字符串(“row”, “col”, “all”, 或“none”) | 若为 True:对所有子图共用 y 轴(最后一行除外),'all’等同于 True;‘None’等同于 False;若为‘col’每列子图共享 y 轴;若为’row’每行子图共享 y 轴 |
squeeze | 布尔参量 | 若为 True,额外维度被剔除:若为 False,没有改变,返回二维数组 |
subplot_kw | 字典数据 | 查询 add_subplot() |
fig_kw | 字典数据 | figure() |
在默认情况下,matplotlib会在subplot外围留下一定的边距,并在subplot之间留下一定的间距,间距与图像的高度和宽度有关,如果你调整了图像的大小其间距也会调整。我们可以利用Figure的subplot_adjust()函数可以轻而易举地修改间距。
matplotlib.pyplot.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
各个参数取值范围为[0-1]
。wspace和hspace用于控制宽度和高度的百分比,可以用作subplot之间的间距调整。例如:
import matplotlib.pyplot as plt
from numpy.random import randn
fig, axes = plt.subplots(2,2,sharex=True,sharey=True)
for i in range(2):
for j in range(2):
axes[i,j].hist(randn(50),bins=50,color='k',alpha=0.5)
plt.subplots_adjust(wspace=0,hspace=0)
plt.show()
(3)fig.add_subplot()
通常我们创建图形时,首先会用 fig = plt.figure()
创建一个 “画板”,并定义画板名称为 fig
,此时画板是空白的,通过 ax = fig.add_subplot()
向画板中添加新的画布,并为画布指定名字为 “ax”,然后就可以单独给这个画布设置各种属性了。例如:
import matplotlib.pyplot as plt
import numpy as np
from pandas import Series
data = Series([1.47,1.62,1.78,1.94,2.38,2.60],index=['2012','2013','2014','2015','2016','2017'])
fig = plt.figure(facecolor='w')
ax1 = fig.add_subplot(111)
ax1.plot(data,label='income', color = 'r', linestyle=':', marker = 's')
ax1.set_title('Income chart')
ax1.set_xlabel('Year')
ax1.set_ylabel('Income')
ax1.annotate('Largest point',xy=(5,2.60),xytext=(3,2.5), arrowprops=dict(arrowstyle='->'))
plt.show()
当我们利用 add_subplot()
函数绘制多幅子图时,分别定义每个子图。例如:
import matplotlib.pyplot as plt
import numpy as np
x1 = np.arange(1, 6)
x2 = np.arange(1, 11)
y1 = x1 ** 2
y2 = x1 ** 3
y3 = x2 ** 2
# create figure and axes
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212)
ax1.bar(x1, y1)
ax2.scatter(x1, y2)
ax3.plot(x2, y3)
plt.show()
2. 图表Axes
Axis 指 x、y 坐标轴等(如果有三维那就还有 z 轴),代表的是 “坐标轴”。而 Axes 在英文里是 Axis 的复数形式,也就是说 axes 代表的其实是 figure 当中的一套坐标轴。之所以说一套而不是两个坐标轴,是因为如果你画三维的图,axes 就代表 3 根坐标轴了。所以,在一个 figure 当中,每添加一次 subplot ,其实就是添加了一套坐标轴,也就是添加了一个 axes,放在二维坐标里就是你添加了两根坐标轴,分别是 x 轴和 y 轴。所以当你只画一个图的时候,plt.xxx 与 ax.xxx 其实都是作用在相同的图上的。
简言之,figure 是作图时的一个大画板,而 axes 是在这个画板上的很多幅画布(子图),绘制的所有图都在画布(axes)上。例如下面这副漫画,定义 4 个 subplot,自然就有 4 个Axes
。
很多地方说 plt.plot()
、plt.scatter()
、plt.bar()
,其实本质上还是在 axes 上画图,可以将他们理解为:先在 figure(画板)上获取一个当前要操作的 axes(画布),如果没有 axes 就自动创建一个并将其设为当前的 axes,然后在当前这个 axes 上执行各种绘图功能。
(二)辅助显示层
辅助显示层显示Axes内除了根据数据绘制出的图像以外的内容,主要包括外观(facecolor)、边框线(spines)、坐标轴(axis)、坐标轴名称(axis label)、坐标轴刻度(tick)、坐标轴刻度标签(tick label)、网格线(grid)、图例(legend)、标题(title)等内容。该层的设置可使图像显示更加直观更加容易被用户理解,但又并不会对图像产生实质的影响。
1. 标题Title
(1)plt.title()
Matplotlib中设置图表标题的函数是plt.title(),该函数的调用方式如下:
matplotlib.pyplot.title(label, fontdict=None, loc=None, pad=None, *, y=None, **kwargs)
参数说明如下:
参数 | 属性 | 描述 |
---|---|---|
label | 字符串 | 标题文本 |
fontdict | 字典类型 | 控制文本的字体属性 |
loc | 取值范围为{'left', 'center', 'right'} |
控制标题的位置,默认值为rcParams["axes.titlelocation"] ('center' ) |
y | 浮点数 | 设置标题在子图中的垂直距离,单位为% ,1.0 代表在子图最顶部,None 则自动确定标题位置,避免与其他元素重叠。默认值为rcParams["axes.titley"] (None) |
pad | 浮点数 | 设置标题与子图的填充距离(内边距),默认值为default: rcParams["axes.titlepad"] (6.0) |
**kwargs | Text 对象关键字属性 |
用于控制文本的外观属性,如字体、文本颜色等 |
上述参数中,fontdict的默认值为:
{
'fontsize': rcParams['axes.titlesize'],
'fontweight': rcParams['axes.titleweight'],
'color': rcParams['axes.titlecolor'],
'verticalalignment': 'baseline',
'horizontalalignment': loc}
例如:绘制心形线
import matplotlib.pyplot as plt
import numpy as np
t = np.linspace(0, np.math.pi, 1000)
x = np.sin(t)
y = np.cos(t) + np.power(x, 2.0 / 3)
plt.plot(x, y, color='red', linewidth=2)
plt.plot(-x, y, color='red', linewidth=2)
plt.title("Heart", fontdict={
'fontsize': 15, 'color': 'darkgreen',}, pad=15)
plt.ylim(-2, 2)
plt.xlim(-2, 2)
plt.show()
(2)plt.suptitle()
plt.suptitle() 函数用于设置整个Figure的标题,该函数的调用格式如下:
matplotlib.pyplot.suptitle(t, **kwargs)
函数主要参数如下:
参数 | 属性 | 描述 |
---|---|---|
t | 字符串类型 | 设置标题文本 |
x | 浮点数 | 设置标题在图像水平方向相对位置,默认值为0.5 |
y | 浮点数 | 设置标题在图像垂直方向相对位置,默认值为0.98 |
fontdict | 字典类型 | 控制文本的字体属性 |
horizontalalignment(缩写ha ) |
字符串类型,取值范围{'center', 'left', right'} |
设置相对于(x,y) 的水平方向对齐方式,默认值为'center' |
verticalalignment(缩写va ) |
字符串类型,取值范围{'top', 'center', 'bottom', 'baseline'} |
设置相对于(x,y) 的垂直方向对齐方式,默认值为'top' |
fontsize(缩写size ) |
浮点数或{'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'} |
设置文本的字体大小,默认值为rcParams["figure.titlesize"] ('large') |
fontweight(缩写weight ) |
0-1000的整数或{'ultralight', 'light', 'normal', 'regular', 'book', 'medium', 'roman', 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black'} |
设置文本的字重 |
**kwargs | Text 对象关键字属性 |
用于控制文本的外观属性,如字体、文本颜色等 |
例如:绘制三角函数Sine、Cosine和Tangent的图形
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams["font.family"]="sans-serif"
mpl.rcParams['axes.unicode_minus'] = False
x = np.arange(-0.49 * np.pi, 0.49 * np.pi, 0.01)
y_sin = np.sin(x)
y_cos = np.cos(x)
y_tan = np.tan(x)
# 绘制正弦图
plt.subplot(2, 2, 1)
plt.plot(x, y_sin, "--")
plt