《scikit-learn机器学习常用算法原理及编程实战》—2.5.2 图形对象
2.5.2 图形对象
在Matplotlib里,一个图形(figure)是指图片的全部可视区域,可以使用plt.figure()来创建。在一个图形里,可以包含多个子图(subplot),可以使用plt.subplot()来创建子图。子图按照网格形状排列显示在图形里,可以在每个子图上单独作画。坐标轴(Axes)和子图类似,唯一不同的是,坐标轴可以在图形上任意摆放,而不需要按照网格排列,这样显示起来更灵活,可以使用plt.axes()来创建坐标轴。
当我们使用默认配置进行作画时,Matplotlib调用 plt.gca() 函数来获取当前的坐标轴,并在当前坐标轴上作画。plt.gca()函数调用plt.gcf()函数来获取当前图形对象,如果当前不存在图形对象,则会调用plt.figure()函数创建一个图形对象。
plt.figure()函数有以下几个常用的参数。
* num:图形对象的标识符,可以是数字或字符串。当num所指定的图形存在时,直接返回这个图形的引用,如果不存在,则创建一个以这个num为标识符的新图形。最后把当前作画的图形切换到这个图形上。
* figsize:以英寸为单位的图形大小(width, height),是一个元组。
* dpi:指定图形的质量,每英寸多少个点。
下面的代码创建了两个图形,一个是'sin',并且把正弦曲线画在这个图形上。然后创建了另外一个名称是'cos'的图形,并把余弦曲线画在这个图形上。接着切换到之前创建的'sin'图形上,把余弦图片也画在这个图形上。
%matplotlib inline
from matplotlib import pyplot as plt
import numpy as np
X = np.linspace(-np.pi, np.pi, 200, endpoint=True)
C, S = np.cos(X), np.sin(X)
plt.figure(num='sin', figsize=(16, 4)) # 创建 'sin' 图形
plt.plot(X, S) # 把正弦画在这个图形上
plt.figure(num='cos', figsize=(16, 4)) # 创建 'cos' 图形
plt.plot(X, C) # 把余弦画在这个图形上
plt.figure(num='sin') # 切换到 'sin' 图形上
plt.plot(X, C) # 在原来的基础上,把余弦曲线也画在这个图形上
print plt.figure(num='sin').number
print plt.figure(num='cos').number
执行结果如图2-9和图2-10所示。
图2-9 正弦曲线
图2-10 余弦曲线
不同的图形可以单独保存为一个图片文件,但子图是指一个图形里分成几个区域,在不同的区域里单独作画,所有的子图最终都保存在一个文件里。plt.subplot()函数的关键参数是一个包含3个元素的元组,分别代表子图的行、列以及当前激活的子图序号。比如plt.subplot(2, 2, 1)表示把图表对象分成两行两列,激活第一个子图来作画。我们看一个网格状的子图的例子:
%matplotlib inline
from matplotlib import pyplot as plt
plt.figure(figsize=(18, 4))
plt.subplot(2, 2, 1)
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'subplot(2,2,1)', ha='center', va='center',
size=20, alpha=.5)
plt.subplot(2, 2, 2)
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'subplot(2,2,2)', ha='center', va='center',
size=20, alpha=.5)
plt.subplot(2, 2, 3)
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'subplot(2,2,3)', ha='center', va='center',
size=20, alpha=.5)
plt.subplot(2, 2, 4)
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'subplot(2,2,4)', ha='center', va='center',
size=20, alpha=.5)
plt.tight_layout()
plt.show()
输出的图形如图2-11所示。
图2-11 subplot输出的子图
更复杂的子图布局,可以使用gridspec来实现,其优点是可以指定某个子图横跨多个列或多个行。
%matplotlib inline
from matplotlib import pyplot as plt
import matplotlib.gridspec as gridspec
plt.figure(figsize=(18, 4))
G = gridspec.GridSpec(3, 3)
axes_1 = plt.subplot(G[0, :]) # 占用第一行,所有的列
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'Axes 1', ha='center', va='center', size=24, alpha=.5)
axes_2 = plt.subplot(G[1:, 0]) # 占用第二行开始之后的所有行,第一列
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'Axes 2', ha='center', va='center', size=24, alpha=.5)
axes_3 = plt.subplot(G[1:, -1]) # 占用第二行开始之后的所有行,最后一列
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'Axes 3', ha='center', va='center', size=24, alpha=.5)
axes_4 = plt.subplot(G[1, -2]) # 占用第二行,倒数第二列
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'Axes 4', ha='center', va='center', size=24, alpha=.5)
axes_5 = plt.subplot(G[-1, -2]) # 占用倒数第一行,倒数第二列
plt.xticks(())
plt.yticks(())
plt.text(0.5, 0.5, 'Axes 5', ha='center', va='center', size=24, alpha=.5)
plt.tight_layout()
plt.show()
画出来的子图布局如图2-12所示。
图2-12 GridSpec
坐标轴使用plt.axes()来创建,它用一个矩形来给坐标轴定位,矩形使用[left, bottom, width, height]来表达。其数据为图形对象对应坐标轴长度的百分比。
%matplotlib inline
from matplotlib import pyplot as plt
plt.figure(figsize=(18, 4))
plt.axes([.1, .1, .8, .8])
plt.xticks(())
plt.yticks(())
plt.text(.2, .5, 'axes([0.1, 0.1, .8, .8])', ha='center', va='center',
size=20, alpha=.5)
plt.axes([.5, .5, .3, .3])
plt.xticks(())
plt.yticks(())
plt.text(.5, .5, 'axes([.5, .5, .3, .3])', ha='center', va='center',
size=16, alpha=.5)
plt.show()
画出来的图形如图2-13所示。
图2-13 坐标轴
一个优美而恰当的坐标刻度对理解数据异常重要,Matplotlib内置提供了以下几个坐标刻度。
* NullLocater:不显示坐标刻度标签,只显示坐标刻度。
* MultipleLocator:以固定的步长显示多个坐标标签。
* FixedLocator:以列表形式显示固定的坐标标签。
* IndexLocator:以offset为启始位置,每隔base步长就画一个坐标标签。
* LinearLocator:把坐标轴的长度均分为numticks个数,显示坐标标签。
* LogLocator:以对数为步长显示刻度标签。
* MaxNLocator:从提供的刻度标签列表里,显示出最大不超过nbins个数的标签。
* AutoLocator:自动显示刻度标签。
除了内置标签外,我们也可以继承matplotlib.ticker.Locator类来实现自定义样式的刻度标签。
通过下面的代码把内置坐标刻度全部画出来,可以直观地观察到内置坐标刻度的样式。具体可参阅随书代码ch02.04.ipynb。
%matplotlib inline
from matplotlib import pyplot as plt
import numpy as np
def tickline():
plt.xlim(0, 10), plt.ylim(-1, 1), plt.yticks([])
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('none')
ax.xaxis.set_minor_locator(plt.MultipleLocator(0.1))
# 设置刻度标签的文本字体大小
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(16)
ax.plot(np.arange(11), np.zeros(11))
return ax
locators = [
'plt.NullLocator()',
'plt.MultipleLocator(base=1.0)',
'plt.FixedLocator(locs=[0, 2, 8, 9, 10])',
'plt.IndexLocator(base=3, offset=1)',
'plt.LinearLocator(numticks=5)',
'plt.LogLocator(base=2, subs=[1.0])',
'plt.MaxNLocator(nbins=3, steps=[1, 3, 5, 7, 9, 10])',
'plt.AutoLocator()',
]
n_locators = len(locators)
# 计算图形对象的大小
size = 1024, 60 * n_locators
dpi = 72.0
figsize = size[0] / float(dpi), size[1] / float(dpi)
fig = plt.figure(figsize=figsize, dpi=dpi)
fig.patch.set_alpha(0)
for i, locator in enumerate(locators):
plt.subplot(n_locators, 1, i + 1)
ax = tickline()
ax.xaxis.set_major_locator(eval(locator)) # 使用 eval 表达式:eval is evil
plt.text(5, 0.3, locator[3:], ha='center', size=16)
plt.subplots_adjust(bottom=.01, top=.99, left=.01, right=.99)
plt.show()
运用效果如图2-14所示。
图2-14 内置坐标刻度
- 点赞
- 收藏
- 关注作者
评论(0)