上一节我们提到,matplotlib绘图有两种风格
显式创建图形与轴空间,并在其上调用方法的OO风格依靠pyplot自动创建和管理图形和轴,并使用pyplot函数进行绘图的plt风格。
我们上一节中的示例代码一第一种方式为主,这一节我们介绍第二种方式,也就是pyplot
pyplot介绍matplotlib.pyplot是一些函数的集合,使matplotlib像MATLAB一样工作。每个绘图函数对图形(figure)进行一些更改:例如,创建图形,在图形中创建绘图区域,在绘图区域绘制一些线条,使用标签装饰绘图等。
在matplotlib.pyplot中,多种状态通过函数之间的调用来保存,以便跟踪诸如当前图形和绘图区域之类的东西。并且绘图函数始终指向当前轴域(请注意,这里和文档中的大多数位置中的『轴域』(axes)是指图形的一部分(坐标轴围成的区域),而不是指代多于一个轴的严格数学术语)。
通过pyplot绘制图像是非常迅速的。plt.plot 是有返回值的,返回的是线的实例列表。只不过这里我们并不需要获得返回值
import matplotlib.pyplot as pltplt.plot([1, 2, 3, 4])plt.ylabel('some numbers')plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DdyFhxV5-1644763593009)(D:2021-autumnmatplotlib图像pyplotoutput.png)]
我们明明只传入了一个列表,为什么绘制出了 x 的范围和 y 的范围呢?如果我们向plot中只传入了一个列表或数组,matplotlib会认为这个序列代表的是 y 的值,并且为我们自动产生 x 的值。因为 python 中的范围是从 0 开始的,且默认的 x 向量与 y 向量具有相同的长度。因此,生成的 x 是[0,1,2,3]。
plot是一个通用函数,并且可以接受任意数量的参数。如果要绘制 x 和 y,我们可以写成
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plot只能画二维图像,我们绘制 x-y 时需要成对输入(每一对是一条线)。如果有单个的序列,则会被认为是 y 的值,并且自动生成 x。
plt.plot([1, 2, 3, 4], [1, 4, 9, 16],[1, 2, 3, 4],[1, 2, 3, 4])
设置plot的风格对于每一对 x,y 参数,都有可选的第三个参数(格式字符串)来控制颜色和绘制的线的类型。格式字符串的字母和符号来自 MATLAB,并且将颜色字符串与线型字符串连接在一起。默认格式字符串为"b-",它是一条蓝色实线。例如,要绘制红色圆圈,我们可以写成
plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro')plt.axis([0, 6, 0, 20])plt.show()
例子中的axis()函数的输入是[xmin, xmax, ymin, ymax],用于指定轴域的可视范围。
如果matplotlib仅限于使用列表,它对于数字处理是相当无用的。通常,我们将会使用numpy数组。事实上,所有序列都会在内部被转换成numpy数组。
下面的例子演示了使用数组在一个函数调用中绘制具有不同格式样式的几条线。
import numpy as np# evenly sampled time at 200ms intervalst = np.arange(0., 5., 0.2)# red dashes, blue squares and green trianglesplt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')plt.show()
通过关键词字符串绘制在某些情况下,数据的格式允许我们使用字符串访问特定的变量。比如numpy.recarray或者pandas.Dataframe。
Matplotlib允许我们使用data关键字参数提供这样的对象。如果提供,那么我们可以用这些变量对应的字符串生成图形。
data = {'a': np.arange(50), 'c': np.random.randint(0, 50, 50), 'd': np.random.randn(50)}data['b'] = data['a'] + 10 * np.random.randn(50)data['d'] = np.abs(data['d']) * 100plt.scatter('a', 'b', c='c', s='d', data=data) #c:color s:sizeplt.xlabel('entry a')plt.ylabel('entry b')plt.show()
通过类别变量绘图names = ['group_a', 'group_b', 'group_c']values = [1, 10, 100]plt.figure(figsize=(9, 3))plt.subplot(131)plt.bar(names, values)plt.subplot(132)plt.scatter(names, values)plt.subplot(133)plt.plot(names, values)plt.suptitle('Categorical Plotting')plt.show()
plt.bar()函数绘制条形图,各种参数如下(上面的names是x参数)
线条有很多可以控制的属性:线宽,线条样式,反锯齿化等。下面有几种可以控制线条属性的方式
使用关键词参数
plt.plot(x, y, linewidth=2.0)
使用二维直线实例的设定方法。plot 返回二维直线对象的列表,例如 line1,line2 = plot(x1,y1,x2,y2)。在下面的代码中,我们假设只有一行,因此返回的列表长度为1(也就是只返回一个二维直线实例)。我们对line使用元组解构,得到该列表的第一个元素:
line, = plt.plot(x, y, '-') #该 line 是一个 Line2D 实例line.set_antialiased(False) # turn off antialiasing
x = [1, 2, 3]y = [1, 2, 3]line = plt.plot(x, y) #该 line 是一个列表print(type(line))>>
使用setp()命令。下面的示例使用 MATLAB 风格的命令来设置线条列表上的多个属性。setp()显而易见地对对象列表或者单个对象工作。我们可以使用python关键词参数或者MATLAB风格的字符串/值对:
lines = plt.plot(x1, y1, x2, y2) #线的对象列表# use keyword argumentsplt.setp(lines, color='r', linewidth=2.0)# or MATLAB style string value pairsplt.setp(lines, 'color', 'r', 'linewidth', 2.0)
下面是可用的二维直线的属性
要获取一个线的可设置的属性列表,可以使用line或lines作为参数调用setp函数
In [69]: lines = plt.plot([1, 2, 3])In [70]: plt.setp(lines) alpha: float animated: [True | False] antialiased or aa: [True | False] ...snip
处理多个图形和轴域MATLAB和pyplot具有当前图像和当前轴域的概念。所有的绘图函数都应用在当前的轴域上。函数gca()返回当前轴域(一个matplotlib.axes.Axes实例),函数gcf()返回当前图像(一个matplotlib.figure.Figure实例)。通常,你不必担心这一点,因为它都是在幕后处理。 下面是一个创建两个子图的脚本。
def f(t): return np.exp(-t) * np.cos(2*np.pi*t)t1 = np.arange(0.0, 5.0, 0.1)t2 = np.arange(0.0, 5.0, 0.02)plt.figure()plt.subplot(211) #两行一列的第一个图plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')plt.subplot(212) #两行一列的第二个图plt.plot(t2, np.cos(2*np.pi*t2), 'r--')plt.show()
figure函数的调用是可选的,因为如果不存在图像的话会创建一个图像。就像没有轴域存在的时候会自动创建一个一样(等价于显式调用subplot函数)。subplot函数调用指定 numrows(行数),numcols(列数),plot_number(图的序号)。plot_number的范围是1~numrows*numcols。 如果numrows * numcols <10,则subplot命令中的逗号是可选的。 因此,子图subplot(211)与subplot(2, 1, 1)相同。我们可以创建任意数量的子图和轴。如果要手动放置轴域,即不在矩形网格上,请使用axes()命令,该命令允许你将axes([left, bottom, width, height])指定为位置,其中所有值都使用小数(0 到 1)坐标。 手动放置轴域的示例请参见pylab_examples示例代码:axes_demo.py,具有大量子图的示例请参见pylab_examples示例代码:subplots_demo.py。
我们可以通过利用递增的图像序号,来多次调用figure函数,从而创建多个图像。当然,每个图都可以包含任意多的轴域和子图:
import matplotlib.pyplot as pltplt.figure(1) # the first figureplt.subplot(211) # the first subplot in the first figureplt.plot([1, 2, 3])plt.subplot(212) # the second subplot in the first figureplt.plot([4, 5, 6])plt.figure(2) # a second figureplt.plot([4, 5, 6]) # creates a subplot() by defaultplt.figure(1) # figure 1 current; subplot(212) still currentplt.subplot(211) # make subplot(211) in figure1 currentplt.title('Easy as 1, 2, 3') # subplot 211 title
我们可以使用clf清除当前图形,使用cla清除当前轴域。
如果你正在制作大量的图形,你需要注意一件事:在一个图形用close()显式关闭之前,该图所需的内存不会完全释放。 删除对图形的所有引用,或使用窗口管理器杀死屏幕上出现的图形的窗口是不够的,因为在调用close()之前,pyplot会维护内部引用
处理文本使用text可以在任何位置添加文本。xlabel(),ylabel()和title()用于在指定的位置添加文本。
mu, sigma = 100, 15x = mu + sigma * np.random.randn(10000)# the histogram of the datan, bins, patches = plt.hist(x, 50, density=1, facecolor='g', alpha=0.75)plt.xlabel('Smarts')plt.ylabel('Probability')plt.title('Histogram of IQ')plt.text(60, .025, r'$mu=100, sigma=15$')plt.axis([40, 160, 0, 0.03])plt.grid(True)plt.show()
plt.text用法介绍
坐标是根据坐标轴确定的二维空间确定的位置,而不是根据图的尺寸来定义的
# 第一个参数是x轴坐标# 第二个参数是y轴坐标# 第三个参数是要显式的内容# alpha 设置字体的透明度# family 设置字体# size 设置字体的大小# style 设置字体的风格# wight 字体的粗细# bbox 给字体添加框,alpha 设置框体的透明度, facecolor 设置框体的颜色
所有的text()命令返回一个matplotlib.text.Text实例。 与上面一样,我们可以通过将关键字参数传递到text函数或使用setp()来自定义属性:
t = plt.xlabel('my data', fontsize=14, color='red')
在文本中使用数学表达式matplotlib在任何文本表达式中接受 TeX 方程表达式。 例如,要在标题中写入表达式,可以编写一个由 $ 包围的 TeX 表达式:
plt.title(r'$sigma_i=15$')
标题字符串之前的r很重要 - 它表示该字符串是一个原始字符串,而不是将反斜杠作为 python 转义处理。matplotlib有一个内置的 TeX 表达式解析器和布局引擎,并且自带了自己的数学字体。因此,我们可以跨平台使用数学文本,而无需安装 TeX。
文本标注上面的text()基本命令将文本放置在轴域的任意位置。 文本的一个常见用法是对图的某些特征执行标注,而annotate()方法提供一些辅助功能,使标注变得容易。 在标注中,有两个要考虑的点:由参数xy表示的标注位置和xytext表示的文本位置。 这两个参数都是(x, y)元组。
ax = plt.subplot()t = np.arange(0.0, 5.0, 0.01)s = np.cos(2*np.pi*t)line, = plt.plot(t, s, lw=2)plt.annotate('local max', xy=(2, 1), xytext=(3, 1.5), arrowprops=dict(facecolor='black', shrink=0.05), )plt.ylim(-2, 2)plt.show()
在本基本样例中,xy(箭头提示)和xytext位置(文本位置)都在数据坐标中。还有其他很多种坐标系可供选择。详细信息请参阅标注文本和标注轴域。 更多示例可以在pylab_examples示例代码:annotation_demo.py中找到。
对数和其它非线性轴matplotlib.pyplot不仅支持线性轴刻度,还支持对数和对数刻度。 如果数据跨越许多数量级,通常会使用它。 更改轴的刻度很容易:
plt.xscale('log')
下面示例显示了四个图,具有相同数据和不同刻度的y轴。
# Fixing random state for reproducibilitynp.random.seed(19680801)# make up some data in the open interval (0, 1)y = np.random.normal(loc=0.5, scale=0.4, size=1000)y = y[(y > 0) & (y < 1)]y.sort()x = np.arange(len(y))# plot with various axes scalesplt.figure()# linearplt.subplot(221)plt.plot(x, y)plt.yscale('linear')plt.title('linear')plt.grid(True)# logplt.subplot(222)plt.plot(x, y)plt.yscale('log')plt.title('log')plt.grid(True)# symmetric logplt.subplot(223)plt.plot(x, y - y.mean())plt.yscale('symlog', linthresh=0.01)plt.title('symlog')plt.grid(True)# logitplt.subplot(224)plt.plot(x, y)plt.yscale('logit')plt.title('logit')plt.grid(True)# Adjust the subplot layout, because the logit one may take more space# than usual, due to y-tick labels like "1 - 10^{-3}"plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25, wspace=0.35)plt.show()