文章目录
Pyplot 教程
https://matplotlib.org/stable/tutorials/pyplot.html
本文介绍 pyplot 接口的使用方法。建议同时参阅:
- 快速入门指南 了解 Matplotlib 的基本工作原理
- Matplotlib 应用程序接口(APIs) 了解不同用户 API 之间的权衡比较
pyplot 简介
matplotlib.pyplot
是一个函数集合,它使 matplotlib 的工作方式类似于 MATLAB。每个 pyplot
函数都会对图形进行一些修改:例如创建图形、在图形中创建绘图区域、在绘图区域中绘制线条、用标签装饰图形等。
在 matplotlib.pyplot
中,各种状态会在函数调用之间保留,因此它会跟踪当前图形和绘图区域等信息,并且绘图函数会定向到当前的 Axes(请注意,我们使用大写字母 Axes 来指代 Axes
概念,这是图形的重要组成部分,而不仅仅是 axis 的复数形式)。
注意:隐式 pyplot API 通常较为简洁,但不如显式 API 灵活。您在这里看到的大多数函数调用也可以作为 Axes
对象的方法调用。我们建议浏览教程和示例以了解其工作原理。有关支持的用户 API 的权衡说明,请参阅 Matplotlib 应用程序接口 (APIs)。
使用 pyplot 生成可视化效果非常快速:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
!pyplot函数提供一个单独的列表或数组,matplotlib会默认将其视为y值序列,并自动为你生成对应的x值。由于Python的计数从0开始,默认的x向量长度与y相同但起始值为0,因此x数据实际上是[0, 1, 2, 3]
。
plot
是一个多功能函数,可以接受任意数量的参数。例如,要绘制x对y的图形,你可以这样编写代码:
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
设置绘图样式
对于每一对 x、y 参数,都可以添加可选的第三个参数作为格式字符串,用于指定绘图的颜色和线条类型。格式字符串的字母和符号源自 MATLAB,您可以将颜色字符串与线条样式字符串连接使用。默认格式字符串是 ‘b-’,表示蓝色实线。例如,要使用红色圆圈绘制上述图形,您可以输入:
plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro')
plt.axis((0, 6, 0, 20))
plt.show()
!pyplot 文档可获取完整的线型与格式字符串列表。上例中的 axis
函数接收 [xmin, xmax, ymin, ymax]
列表参数,用于指定坐标轴的显示范围。
如果 matplotlib 只能处理列表,其数值处理能力将非常有限。通常我们会使用 numpy 数组进行运算。实际上,所有序列在内部都会被转换为 numpy 数组。下面的示例展示了如何通过数组在一次函数调用中绘制多条不同样式的线条。
import numpy as np
# evenly sampled time at 200ms intervals
t = np.arange(0., 5., 0.2)
# red dashes, blue squares and green triangles
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.show()
[外链图片转存中…(img-D46UxLRG-1755770917636)]
使用字符串关键字绘图
在某些情况下,您的数据格式允许通过字符串访问特定变量。例如使用$1时。
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']) * 100
plt.scatter('a', 'b', c='c', s='d', data=data)
plt.xlabel('entry a')
plt.ylabel('entry b')
plt.show()
使用分类变量绘图
我们也可以利用分类变量来创建图表。Matplotlib 允许直接将分类变量传递给许多绘图函数。例如:
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()
[外链图片转存中…(img-s4bm8anO-1755770917636)]
控制线条属性
线条具有多种可设置的属性:线宽(linewidth)、虚线样式(dash style)、抗锯齿(antialiased)等;具体可参考 matplotlib.lines.Line2D
。设置线条属性的方法包括:
- 使用关键字参数:
plt.plot(x, y, linewidth=2.0)
- 使用
Line2D
实例的 setter 方法。plot
会返回一个包含Line2D
对象的列表;例如,line1, line2 = plot(x1, y1, x2, y2)
。在接下来的代码中,我们假设只绘制了一条线,因此返回的列表长度为 1。我们通过元组解包line,
来获取该列表的第一个元素:
line, = plt.plot(x, y, '-')
line.set_antialiased(False) # turn off antialiasing
- 使用
setp
方法。以下示例展示了如何通过 MATLAB 风格的函数一次性设置多条线的多个属性。setp
可以透明地处理对象列表或单个对象,支持使用 Python 关键字参数或 MATLAB 风格的字符串/值对进行设置。
lines = plt.plot(x1, y1, x2, y2)
# use keyword arguments
plt.setp(lines, color='r', linewidth=2.0)
# or MATLAB style string value pairs
plt.setp(lines, 'color', 'r', 'linewidth', 2.0)
以下是可用的 Line2D
属性。
属性 | 值类型 |
---|---|
alpha | 浮点数 |
animated | [True |
antialiased 或 aa | [True |
clip_box | matplotlib.transform.Bbox 实例 |
clip_on | [True |
clip_path | Path 实例和 Transform 实例,或 Patch |
color 或 c | 任意 matplotlib 颜色 |
contains | 命中检测函数 |
dash_capstyle | ['butt' |
dash_joinstyle | ['miter' |
dashes | 以点为单位的墨水开关序列 |
data | (np.array xdata, np.array ydata) |
figure | matplotlib.figure.Figure 实例 |
label | 任意字符串 |
linestyle 或 ls | [ '-' |
linewidth 或 lw | 以点为单位的浮点值 |
marker | [ '+' |
markeredgecolor 或 mec | 任意 matplotlib 颜色 |
markeredgewidth 或 mew | 以点为单位的浮点值 |
markerfacecolor 或 mfc | 任意 matplotlib 颜色 |
markersize 或 ms | 浮点数 |
markevery | [ None |
picker | 用于交互式线条选择 |
pickradius | 线条选择半径 |
solid_capstyle | ['butt' |
solid_joinstyle | ['miter' |
transform | matplotlib.transforms.Transform 实例 |
visible | [True |
xdata | np.array |
ydata | np.array |
zorder | 任意数字 |
要获取可设置的线条属性列表,请调用 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
具有当前图形(current figure)和当前坐标轴(current Axes)的概念。所有绘图函数都作用于当前坐标轴。函数 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()
!pyplot 调用是可选的,因为如果不存在图形,系统会自动创建一个(就像当不存在坐标轴时,会自动执行等效于显式 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 的分数坐标。手动放置坐标轴的示例可参考 Axes Demo,大量子图示例可查看 Multiple subplots。
通过多次调用 figure
并递增图形编号,您可以创建多个图形。当然,每个图形可以包含任意数量的坐标轴和子图。
import matplotlib.pyplot as plt
plt.figure(1) # the first figure
plt.subplot(211) # the first subplot in the first figure
plt.plot([1, 2, 3])
plt.subplot(212) # the second subplot in the first figure
plt.plot([4, 5, 6])
plt.figure(2) # a second figure
plt.plot([4, 5, 6]) # creates a subplot() by default
plt.figure(1) # first figure current;
# subplot(212) still current
plt.subplot(211) # make subplot(211) in the first figure
# current
plt.title('Easy as 1, 2, 3') # subplot 211 title
你可以使用 clf
清除当前图形,使用 cla
清除当前坐标轴。如果发现后台自动维护的状态(尤其是当前图像、图形和坐标轴)让你困扰,别担心:这只是面向对象 API 的一个轻量级有状态封装,你也可以直接使用底层 API(参见 Artist 教程)。
当创建大量图形时,还需注意:只有显式调用 close
关闭图形后,其占用的内存才会完全释放。仅删除所有图形引用或通过窗口管理器关闭图形窗口是不够的,因为 pyplot 会一直保持内部引用,直到调用 close
。
文本处理
text
可用于在任意位置添加文本,而 xlabel
、ylabel
和 title
则用于在指定位置添加文本(更详细的示例请参阅 Matplotlib 中的文本)。
mu, sigma = 100, 15
x= mu + sigma * np.random.randn(10000)
# the histogram of the data
n, bins, patches = plt.hist(x, 50, density=True, 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()
!$1函数都会返回一个matplotlib.text.Text
实例。与之前处理线条的方式类似,您可以通过两种方式自定义属性:
1、向文本函数传递关键字参数
2、使用setp
方法
t = plt.xlabel('my data', fontsize=14, color='red')
这些属性在文本属性与布局中有更详细的说明。
在文本中使用数学表达式
Matplotlib 支持在任何文本表达式中使用 TeX 数学公式。例如,要在标题中写入表达式 \(\sigma_i=15),你可以用美元符号包裹 TeX 表达式:
plt.title(r'$\sigma_i=15$')
标题字符串前的 r
很重要——它表示该字符串是一个原始字符串,不会将反斜杠视为 Python 转义字符。matplotlib 内置了 TeX 表达式解析器和布局引擎,并自带数学字体——详情请参阅编写数学表达式。因此,您可以跨平台使用数学文本而无需安装 TeX。对于已安装 LaTeX 和 dvipng 的用户,还可以使用 LaTeX 格式化文本,并将输出直接嵌入显示图形或保存的 PostScript 文件中——参见使用 LaTeX 渲染文本。
文本标注
上述基础 text
函数的主要用途是在坐标轴上的任意位置放置文本。文本的一个常见用途是为图表中的某些特征添加标注,而 annotate
方法提供了便捷的辅助功能来简化标注操作。
在标注过程中,需要考虑两个关键点:
1、被标注对象的位置,由参数 xy
表示
2、文本标注的位置,由参数 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
(文本位置)都采用数据坐标系。用户还可以选择多种其他坐标系——具体可参阅基础标注和高级标注文档。更多示例可在图表标注章节查看。
对数轴与其他非线性坐标轴
matplotlib.pyplot
不仅支持线性坐标轴刻度,还支持对数和分对数(logit)刻度。当数据跨越多个数量级时,这种刻度尤为常用。修改坐标轴刻度比例非常简单:
plt.xscale('log')
以下展示了四幅使用相同数据但y轴比例不同的示例图。
# Fixing random state for reproducibility
np.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 scales
plt.figure()
# linear
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)
# log
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)
# symmetric log
plt.subplot(223)
plt.plot(x, y- y.mean())
plt.yscale('symlog', linthresh=0.01)
plt.title('symlog')
plt.grid(True)
# logit
plt.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()
!$1。
脚本总运行时间: (0 分 3.950 秒)
图像教程
https://matplotlib.org/stable/tutorials/images.html
一个关于使用 Matplotlib 绘制图像的简短教程。
启动命令
首先,我们启动IPython。这是对标准Python提示符的绝佳增强,尤其与Matplotlib配合得天衣无缝。你可以直接在终端中启动IPython,或者通过Jupyter Notebook(其中IPython作为运行内核)启动。
启动IPython后,我们需要连接到一个GUI事件循环。这会告诉IPython在何处(以及如何)显示图表。要连接GUI循环,请在IPython提示符下执行**%matplotlib**魔法命令。关于这个命令的具体作用,可以参考IPython关于GUI事件循环的文档。
如果你使用Jupyter Notebook,同样可以使用这些命令,但人们通常会给%matplotlib魔法命令指定一个特定参数:
In [1]: %matplotlib inline
这将启用内联绘图功能,绘图图形会直接显示在笔记本中。这对交互性有重要影响:在内联绘图模式下,输出绘图单元格下方的单元格命令不会影响该绘图。例如,无法通过创建绘图单元格下方的单元格来更改色彩映射表。
不过,对于其他后端(如Qt)会打开独立窗口的情况,创建绘图单元格下方的单元格将能修改绘图——因为这是内存中的实时对象。
本教程将使用Matplotlib的隐式绘图接口pyplot。该接口维护全局状态,非常适合快速轻松地试验各种绘图设置。另一种显式接口则更适用于大型应用程序开发。有关隐式与显式接口权衡的说明,请参阅Matplotlib应用程序接口(APIs)以及快速入门指南开始使用显式接口。
现在,让我们继续使用隐式方法:
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
将图像数据导入Numpy数组
Matplotlib依赖Pillow库来加载图像数据。
以下是我们要操作的图像:
这是一张24位RGB PNG图像(R、G、B各占8位)。根据数据来源不同,您可能还会遇到支持透明度的RGBA图像,或是单通道灰度(亮度)图像。请将[stinkbug.png](https://raw.githubusercontent.com/matplotlib/matplotlib/main/doc/_static/stinkbug.png =400x)
下载到本地以便后续教程使用。
我们使用Pillow打开图像(通过PIL.Image.open
方法),并立即将PIL.Image.Image
对象转换为8位(dtype=uint8
)的numpy数组。
img = np.asarray(Image.open('../../doc/_static/stinkbug.png'))
print(repr(img))
array([[[104, 104, 104],
[104, 104, 104],
[104, 104, 104],
...,
[109, 109, 109],
[109, 109, 109],
[109, 109, 109]],
[[105, 105, 105],
[105, 105, 105],
[105, 105, 105],
...,
[109, 109, 109],
[109, 109, 109],
[109, 109, 109]],
[[107, 107, 107],
[106, 106, 106],
[106, 106, 106],
...,
[110, 110, 110],
[110, 110, 110],
[110, 110, 110]],
...,
[[112, 112, 112],
[111, 111, 111],
[110, 110, 110],
...,
[116, 116, 116],
[115, 115, 115],
[115, 115, 115]],
[[113, 113, 113],
[113, 113, 113],
[112, 112, 112],
...,
[115, 115, 115],
[114, 114, 114],
[114, 114, 114]],
[[113, 113, 113],
[115, 115, 115],
[115, 115, 115],
...,
[114, 114, 114],
[114, 114, 114],
[113, 113, 113]]], shape=(375, 500, 3), dtype=uint8)
每个内部列表代表一个像素。对于RGB图像,每个像素包含3个值。由于这是黑白图像,R、G、B三个通道的值都相近。如果是RGBA图像(A代表alpha通道,即透明度),每个内部列表会有4个值;而简单的亮度图像只需一个值(因此是二维数组,而非三维数组)。
对于RGB和RGBA图像,Matplotlib支持float32和uint8数据类型。对于灰度图像,Matplotlib仅支持float32类型。如果您的数组数据不符合上述任一描述,就需要重新调整其格式。
将NumPy数组绘制为图像
假设你已将数据存储在NumPy数组中(无论是通过导入还是生成)。现在我们来可视化这些数据。在Matplotlib中,可以使用imshow()
函数实现这一功能。这里我们将获取绘图对象,该对象提供了从命令行轻松操作绘图的方法。
imgplot = plt.imshow(img)
[外链图片转存中…(img-9PjkJGf0-1755770917637)]你也可以绘制任何NumPy数组。
为图像绘制应用伪彩色方案
伪彩色是一种增强对比度、使数据更易可视化的有效工具。这在通过投影仪展示数据时尤为实用——因为投影仪的对比度通常较差。
伪彩色仅适用于单通道灰度亮度图像。当前我们处理的是RGB图像。由于R、G、B三个通道数值相近(可通过上文或实际数据验证),我们可以直接通过数组切片选取其中一个通道(更多细节可参阅Numpy教程):
lum_img = img[:, :, 0]
plt.imshow(lum_img)
[外链图片转存中…(img-WtOo4uBF-1755770917637)]对于一张亮度(二维,无色彩)图像,系统会默认应用颜色映射表(即查找表LUT)。默认采用名为viridis的配色方案,此外还提供多种其他可选方案。
plt.imshow(lum_img, cmap="hot")
[外链图片转存中…(img-6ZXECBAI-1755770917637)]
请注意,您还可以使用 set_cmap()
方法来更改现有绘图对象的色彩映射表:
imgplot = plt.imshow(lum_img)
imgplot.set_cmap('nipy_spectral')
[外链图片转存中…(img-wGyscWkI-1755770917637)]
注意:在启用内联后端(inline backend)的Jupyter Notebook中,请记住无法修改已渲染的绘图。如果你在某个单元格中创建了imgplot对象,后续单元格中调用set_cmap()方法将不会改变先前生成的图像。请确保将所有相关命令集中在同一个单元格内执行——plt命令不会影响之前单元格生成的图像。
Matplotlib还提供了多种其他色彩映射方案。具体可参阅色彩映射列表与示例图。
色阶参考
了解颜色所代表的数值很有帮助。我们可以通过在图表中添加颜色条来实现这一点。
imgplot = plt.imshow(lum_img)
plt.colorbar()
[外链图片转存中…(img-F06YIS5D-1755770917637)]
检查特定数据范围
有时您希望增强图像的对比度,或者扩展特定区域的对比度,同时牺牲那些变化不大或不重要的颜色细节。直方图是寻找感兴趣区域的实用工具。要创建图像数据的直方图,我们可以使用 hist()
函数。
plt.hist(lum_img.ravel(), bins=range(256), fc='k', ec='k')
[外链图片转存中…(img-6kci5ILB-1755770917637)]通常来说,图像中最"有趣"的部分集中在峰值区域附近。
通过裁剪峰值上方和/或下方的区域,可以增强对比度。从直方图来看,高端区域似乎没有太多有用信息(图像中白色物体不多)。让我们调整上限值,实际上相当于"放大"直方图的特定部分。这可以通过设置clim(色图范围限制)参数来实现。
具体操作时,可以在调用imshow
函数时传入clim关键字参数。
plt.imshow(lum_img, clim=(0, 175))
!images 方法来实现,但请注意:在使用 Jupyter Notebook 时,必须确保该操作与绘图命令位于同一个单元格中——它不会改变之前单元格中的绘图。
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0, 175)
[外链图片转存中…(img-GHc4aX3I-1755770917637)]
数组插值方案
插值通过不同的数学方案计算像素"应该"呈现的颜色或数值。这种情况常见于调整图像尺寸时:像素数量发生变化,但需要保留相同的信息。由于像素是离散的,中间会存在空缺区域,而插值正是填补这些空缺的方法。这就是为什么放大图像时有时会出现像素化现象——当原始图像与放大图像的尺寸差异越大时,这种效果就越明显。
假设我们缩小一张图像,实际上是在丢弃像素,只保留精选的少数像素。当重新显示时,这些数据会被放大到屏幕尺寸。由于原始像素已不存在,计算机必须绘制新像素来填补空缺区域。
我们将使用之前加载图像时用过的Pillow库来调整图像尺寸。
img = Image.open('../../doc/_static/stinkbug.png')
img.thumbnail((64, 64)) # resizes image in-place
imgplot = plt.imshow(img)
!$1,因为我们没有为imshow()
提供任何插值参数。
让我们尝试其他方法。这是"bilinear"(双线性插值):
imgplot = plt.imshow(img, interpolation="bilinear")
[外链图片转存中…(img-H0bDbxWD-1755770917637)]和双三次:
imgplot = plt.imshow(img, interpolation="bicubic")
双三次插值常用于放大照片——人们通常更喜欢模糊效果而非像素化的效果。
脚本总运行时间: (0 分钟 8.955 秒)
图表生命周期教程
https://matplotlib.org/stable/tutorials/lifecycle.html
本教程旨在展示使用Matplotlib完成单个可视化的完整流程。我们将从原始数据开始,最终保存一张定制化可视化图表。在此过程中,我们会重点演示Matplotlib的一些实用功能和最佳实践。
注:本教程改编自Chris Moffitt的这篇优秀博客文章,由Chris Holdgraf整理成教程形式。
关于显式与隐式接口的说明
Matplotlib 提供两种接口。关于显式与隐式接口的权衡分析,请参阅 Matplotlib 应用接口(APIs)。
在显式的面向对象(OO)接口中,我们直接使用 axes.Axes
实例在 figure.Figure
实例上构建可视化。而受MATLAB启发的隐式接口则采用基于全局状态的接口,通过 pyplot
模块在"当前坐标轴"上绘图。关于pyplot接口的深入探讨,请参考 pyplot教程。
大多数术语都很直观,但需要重点记住:
我们直接从Axes对象调用绘图方法,这种方式为图形定制提供了更高的灵活性和控制力。
注意:通常建议优先使用显式接口而非隐式的pyplot接口进行绘图。
我们的数据
我们将使用本教程所基于的博文中的数据。
该数据集包含多家公司的销售信息。
import matplotlib.pyplot as plt
import numpy as np
data = {'Barton LLC': 109438.50,
'Frami, Hills and Schmidt': 103569.59,
'Fritsch, Russel and Anderson': 112214.71,
'Jerde-Hilpert': 112591.43,
'Keeling LLC': 100934.30,
'Koepp Ltd': 103660.54,
'Kulas Inc': 137351.96,
'Trantow-Barrows': 123381.38,
'White-Trantow': 135841.99,
'Will LLC': 104437.60}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)
入门指南
这些数据天然适合用条形图来可视化,每组数据对应一个条形。若采用面向对象的方法实现,我们首先生成一个 figure.Figure
和 axes.Axes
的实例。Figure 如同画布,而 Axes 则是该画布上用于绘制特定可视化的区域。
注意:一个 Figure 上可以包含多个 Axes。关于如何实现这一点,请参阅 紧凑布局教程。
fig, ax = plt.subplots()
[外链图片转存中…(img-5vZHiMHn-1755770917638)]现在我们有了一个Axes实例,就可以在其基础上进行绘图了。
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
[外链图片转存中…(img-11dwpmdm-1755770917638)]
控制样式
Matplotlib 提供了多种样式选项,让您能够根据需求定制可视化效果。要查看可用样式列表,可以使用 style
模块。
print(plt.style.available)
['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'petroff10', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10']
您可以通过以下方式激活样式:
plt.style.use('fivethirtyeight')
现在让我们重新绘制上面的图表,看看效果如何:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
[外链图片转存中…(img-8U4bPxrK-1755770917638)]样式控制着诸多元素,例如颜色、线宽、背景等。
定制图表样式
现在我们已经得到了大致符合需求的图表,接下来需要进行微调,使其达到可印刷的标准。首先旋转x轴上的标签,让它们显示得更清晰。我们可以通过 axes.Axes.get_xticklabels()
方法来获取这些标签:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
!lifecycle 函数会很方便。该函数可以接收一个(或多个)Matplotlib对象列表,并尝试为每个对象设置样式属性。
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
[外链图片转存中…(img-NYpiaWZ1-1755770917638)]看起来底部部分标签被截断了。我们可以让Matplotlib自动为图表中的元素留出空间。为此,我们需要设置rcParams中的autolayout
参数值。关于通过rcParams控制绘图样式、布局及其他特性的更多信息,请参阅使用样式表和rcParams自定义Matplotlib。
plt.rcParams.update({'figure.autolayout': True})
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
!$1 方法设置该坐标轴对象的属性。
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
!$1函数来调整这个图表的大小。通过figsize关键字参数即可实现。
注意:虽然NumPy中的索引遵循(行,列)的形式,但figsize关键字参数遵循(宽度,高度)的形式。这遵循了可视化领域的惯例,遗憾的是与线性代数的惯例有所不同。
fig, ax = plt.subplots(figsize=(8, 4))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
!$1 或 Axis.set_minor_formatter
一起使用时,它们会自动创建并使用 ticker.FuncFormatter
类。
在这个函数中,x
参数是原始的刻度标签,pos
是刻度位置。这里我们只会用到 x
,但这两个参数都是必需的。
def currency(x, pos):
"""The two arguments are the value and tick position"""
if x >= 1e6:
s = f'${x*1e-6:1.1f}M'
else:
s = f'${x*1e-3:1.0f}K'
return s
然后我们可以将这个函数应用到图表中的标签上。为此,我们使用 Axes 的 xaxis
属性,这允许你对图表上的特定坐标轴进行操作。
fig, ax = plt.subplots(figsize=(6, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
[外链图片转存中…(img-e7W2p0lQ-1755770917638)]
组合多种可视化效果
可以在同一个 axes.Axes
实例上绘制多个图表元素。要实现这一点,我们只需在该 Axes 对象上调用其他绘图方法即可。
fig, ax = plt.subplots(figsize=(8, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
# Add a vertical line, here we set the style in the function call
ax.axvline(group_mean, ls='--', color='r')
# Annotate new companies
for group in [3, 5, 8]:
ax.text(145000, group, "New Company", fontsize=10,
verticalalignment="center")
# Now we move our title up since it's getting a little cramped
ax.title.set(y=1.05)
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
fig.subplots_adjust(right=.1)
plt.show()
[外链图片转存中…(img-r4jCnExm-1755770917638)]
保存我们的绘图
现在我们对绘图结果感到满意,想要将其保存到磁盘。Matplotlib 支持多种文件格式保存。要查看可用选项列表,可以使用:
print(fig.canvas.get_supported_filetypes())
{'eps': 'Encapsulated Postscript', 'jpg': 'Joint Photographic Experts Group', 'jpeg': 'Joint Photographic Experts Group', 'pdf': 'Portable Document Format', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'ps': 'Postscript', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg': 'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format', 'webp': 'WebP Image Format'}
我们可以使用 figure.Figure.savefig()
方法将图形保存到磁盘。以下是几个有用的参数说明:
transparent=True
使保存图形的背景透明(如果格式支持该特性)dpi=80
控制输出图像的分辨率(每英寸点数)bbox_inches="tight"
使图形边界紧密贴合绘图区域
# Uncomment this line to save the figure.
# fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")
脚本总运行时间:(0 分钟 3.734 秒)
Artist 教程
https://matplotlib.org/stable/tutorials/artists.html
使用 Artist 对象在画布上进行渲染。
Matplotlib API 分为三个层级:
matplotlib.backend_bases.FigureCanvas
是绘制图形的区域
matplotlib.backend_bases.Renderer
是知道如何在matplotlib.backend_bases.FigureCanvas
上绘制的对象matplotlib.artist.Artist
则是知道如何使用渲染器在画布上绘制的对象
matplotlib.backend_bases.FigureCanvas
和 matplotlib.backend_bases.Renderer
负责处理与用户界面工具包(如 wxPython)或绘图语言(如 PostScript®)交互的所有底层细节,而 Artist
则处理所有高级结构,如图形表示、布局、文本和线条。典型用户 95% 的时间都会与 Artists
打交道。
Artists
分为两类:图元(primitives)和容器(containers)。图元代表我们想在画布上绘制的标准图形对象:Line2D
、Rectangle
、Text
、AxesImage
等;容器则是放置这些图元的位置(Axis
、Axes
和 Figure
)。
标准用法是创建一个 Figure
实例,使用该 Figure
创建一个或多个 Axes
实例,然后通过 Axes
实例的辅助方法来创建图元。在下面的示例中,我们使用 matplotlib.pyplot.figure()
创建 Figure
实例——这是一个便捷方法,用于实例化 Figure
并将其与用户界面或绘图工具包的 FigureCanvas
连接。正如我们下文将讨论的,这并不是必须的——你可以直接使用 PostScript、PDF、Gtk+ 或 wxPython 的 FigureCanvas
实例,直接实例化你的 Figures
并自行连接它们——但由于我们这里主要关注 Artist
API,我们将让 pyplot
帮我们处理这些细节。
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1) # two rows, one column, first plot
Axes
可能是Matplotlib API中最重要的类,也是开发者最常使用的对象。因为Axes
作为绘图区域,承载了绝大多数图形元素,并且提供了许多专用辅助方法(如plot()
、text()
、hist()
、imshow()
)来创建常见图形基元(分别对应Line2D
、Text
、Rectangle
、AxesImage
)。
这些辅助方法会自动处理输入数据(例如numpy
数组和字符串),按需创建Artist
基元实例(如Line2D
),将其添加到对应容器中,并在需要时进行绘制。若需在任意位置创建Axes
,只需使用add_axes()
方法,该方法接受0-1相对坐标范围内的[left, bottom, width, height]
参数列表。
fig2 = plt.figure()
ax2 = fig2.add_axes([0.15, 0.1, 0.7, 0.3])
继续我们的示例:
import numpy as np
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax.plot(t, s, color='blue', lw=2)
在这个示例中,ax
是通过上方fig.add_subplot
调用创建的Axes
实例,当你调用ax.plot
时,它会创建一个Line2D
实例并将其添加到Axes
中。在下面的交互式IPython会话中,你可以看到Axes.lines
列表长度为1,其中包含与line, = ax.plot...
调用返回的相同线条:
In [101]: ax.lines[0]
Out[101]: <matplotlib.lines.Line2D at 0x19a95710>
In [102]: line
Out[102]: <matplotlib.lines.Line2D at 0x19a95710>
如果你后续再次调用ax.plot
(且保持状态为"on",这是默认设置),则会在列表中添加新的线条。
之后你可以通过调用线条的remove
方法来移除某条线。
line = ax.lines[0]
line.remove()
坐标轴还提供辅助方法来配置和装饰 x 轴与 y 轴的刻度线、刻度标签及轴标签:
xtext = ax.set_xlabel('my xdata') # returns a Text instance
ytext = ax.set_ylabel('my ydata')
当你调用 ax.set_xlabel
时,它会将信息传递给 XAxis
的 Text
实例。每个 Axes
实例都包含一个 XAxis
和 YAxis
实例,这些实例负责处理刻度线、刻度标签和轴标签的布局与绘制。
尝试创建下图。
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
fig.subplots_adjust(top=0.8)
ax1 = fig.add_subplot(211)
ax1.set_ylabel('Voltage [V]')
ax1.set_title('A sine wave')
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax1.plot(t, s, color='blue', lw=2)
# Fixing random state for reproducibility
np.random.seed(19680801)
ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3])
n, bins, patches = ax2.hist(np.random.randn(1000), 50,
facecolor='yellow', edgecolor='yellow')
ax2.set_xlabel('Time [s]')
plt.show()
[外链图片转存中…(img-P0YWdplu-1755770917638)]
自定义对象
图中的每个元素都由 Matplotlib 的 Artist
表示,每个对象都拥有大量可配置其外观的属性。图形本身包含一个与图形尺寸完全一致的 Rectangle
,可用于设置图形的背景颜色和透明度。同样,每个 Axes
的边界框(标准 Matplotlib 图表中带有黑色边框的白色方框)都有一个 Rectangle
实例,用于决定坐标轴的颜色、透明度等属性。这些实例分别存储为成员变量 Figure.patch
和 Axes.patch
(“Patch” 概念继承自 MATLAB,指代图形上的二维彩色"补丁",如矩形、圆形和多边形)。
所有 Matplotlib 的 Artist
对象都具备以下属性:
属性 | 描述 |
---|---|
alpha | 透明度 - 取值范围 0 到 1 的标量 |
animated | 布尔值,用于辅助动画绘制 |
axes | 对象所属的坐标轴,可能为 None |
clip_box | 用于裁剪对象的边界框 |
clip_on | 是否启用裁剪 |
clip_path | 对象被裁剪的路径 |
contains | 检测对象是否包含拾取点的函数 |
figure | 对象所属的图形实例,可能为 None |
label | 文本标签(例如用于自动标注) |
picker | 控制对象拾取的 Python 对象 |
transform | 变换矩阵 |
visible | 布尔值,决定对象是否被绘制 |
zorder | 决定绘制顺序的数值 |
rasterized | 布尔值;将矢量转为栅格图形(用于压缩和 EPS 透明度) |
所有属性都通过传统的 setter 或 getter 方法访问(我们知道这会令 Python 爱好者不快,计划未来支持通过属性或 traits 直接访问,但目前尚未实现)。例如,要将当前 alpha 值减半:
a = o.get_alpha()
o.set_alpha(0.5*a)
如果你想一次性设置多个属性,也可以使用带关键字参数的set
方法。例如:
o.set(alpha=0.5, zorder=2)
如果你在Python交互式shell中工作,检查Artist
属性的便捷方法是使用matplotlib.artist.getp()
函数(在pyplot中简写为getp()
),该函数会列出属性及其值。此方法同样适用于从Artist
派生的类,例如Figure
和Rectangle
。以下是上述提到的Figure
矩形属性:
In [149]: matplotlib.artist.getp(fig.patch)
agg_filter = None
alpha = None
animated = False
antialiased or aa = False
bbox = Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0)
capstyle = butt
children = []
clip_box = None
clip_on = True
clip_path = None
contains = None
data_transform = BboxTransformTo( TransformedBbox( Bbox...
edgecolor or ec = (1.0, 1.0, 1.0, 1.0)
extents = Bbox(x0=0.0, y0=0.0, x1=640.0, y1=480.0)
facecolor or fc = (1.0, 1.0, 1.0, 1.0)
figure = Figure(640x480)
fill = True
gid = None
hatch = None
height = 1
in_layout = False
joinstyle = miter
label =
linestyle or ls = solid
linewidth or lw = 0.0
patch_transform = CompositeGenericTransform( BboxTransformTo( ...
path = Path(array([[0., 0.], [1., 0.], [1.,...
path_effects = []
picker = None
rasterized = None
sketch_params = None
snap = None
transform = CompositeGenericTransform( CompositeGenericTra...
transformed_clip_path_and_affine = (None, None)
url = None
verts = [[ 0、 0.] [640、 0.] [640、480.] [ 0、480....
visible = True
width = 1
window_extent = Bbox(x0=0.0, y0=0.0, x1=640.0, y1=480.0)
x = 0
xy = (0, 0)
y = 0
zorder = 1
所有类的文档字符串都包含 Artist
属性,因此您可以通过交互式"help"功能或查阅 matplotlib.artist 来获取特定对象的属性列表。
对象容器
现在我们已经了解如何检查和设置目标对象的属性,接下来需要知道如何获取这些对象。如引言所述,对象分为两种类型:基本元素和容器。通常需要配置的是基本元素(例如Text
实例的字体、Line2D
的线宽),但容器也具备某些属性——例如Axes
Artist
作为容器,既包含绘图中的许多基本元素,也拥有像xscale
这样的属性来控制x轴是"线性"还是"对数"刻度。本节将介绍各类容器对象存储目标Artists
的位置。
图形容器
顶级容器 Artist
是 matplotlib.figure.Figure
,它包含了图形中的所有元素。图形的背景是一个 Rectangle
,存储在 Figure.patch
中。当你向图形中添加子图(add_subplot()
)和坐标轴(add_axes()
)时,这些元素会被追加到 Figure.axes
中。这些方法在创建元素时也会返回它们:
In [156]: fig = plt.figure()
In [157]: ax1 = fig.add_subplot(211)
In [158]: ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3])
In [159]: ax1
Out[159]: <Axes:>
In [160]: print(fig.axes)
[<Axes:>, <matplotlib.axes._axes.Axes object at 0x7f0768702be0>]
由于图形对象维护着"当前坐标轴"的概念(参见 Figure.gca
和 Figure.sca
)以支持pylab/pyplot状态机,因此不应直接从坐标轴列表中插入或删除坐标轴,而应使用 add_subplot()
和 add_axes()
方法进行插入,以及 Axes.remove
方法进行删除。不过,您可以自由地遍历坐标轴列表或通过索引访问需要自定义的 Axes
实例。下面是一个开启所有坐标轴网格线的示例:
for ax in fig.axes:
ax.grid(True)
该图形还拥有自己的images
、lines
、patches
和text
属性,您可以直接通过这些属性添加图元。但需注意,此时Figure
的默认坐标系会以像素为单位(通常不符合预期需求)。
如果改用Figure层级的方法来添加Artists(例如使用Figure.text
添加文本),默认坐标系将切换为"图形坐标系"——其中(0,0)表示图形左下角,(1,1)表示图形右上角。
与所有Artist
对象一样,您可以通过设置transform属性来控制坐标系。若需显式使用"图形坐标系",只需将Artist
的transform属性设为fig.transFigure
即可。
import matplotlib.lines as lines
fig = plt.figure()
l1 = lines.Line2D([0, 1], [0, 1], transform=fig.transFigure, figure=fig)
l2 = lines.Line2D([0, 1], [1, 0], transform=fig.transFigure, figure=fig)
fig.lines.extend([l1, l2])
plt.show()
以下是该图表中包含的Artists(图形元素)概述:
图表属性 | 描述 |
---|---|
axes | Axes 实例的列表 |
patch | 背景的Rectangle 矩形 |
images | FigureImage 图像块的列表 - 用于原始像素显示 |
legends | 图表Legend 图例实例的列表(不同于Axes.get_legend() ) |
lines | 图表Line2D 线段的列表(较少使用,参见Axes.lines ) |
patches | 图表Patch 图形块的列表(较少使用,参见Axes.patches ) |
texts | 图表Text 文本实例的列表 |
坐标轴容器
matplotlib.axes.Axes
是 Matplotlib 的核心——它包含了图表中使用的大部分 Artists
对象,并提供了众多辅助方法来创建这些 Artists
并将其添加到自身中,同时还包含访问和定制这些 Artists
的辅助方法。与 Figure
类似,它也包含一个 Patch
对象 matplotlib.axes.Axes.patch
,在笛卡尔坐标系中这个补丁是一个 Rectangle
,而在极坐标系中则是一个 Circle
;这个补丁决定了绘图区域的形状、背景和边框。
ax = fig.add_subplot()
rect = ax.patch # a Rectangle instance
rect.set_facecolor('green')
当你调用绘图方法时,例如标准的 plot
并传入数组或值列表时,该方法会创建一个 matplotlib.lines.Line2D
实例,用所有通过关键字参数传递的 Line2D
属性更新线条,将线条添加到 Axes
中,并将其返回给你:
In [213]: x, y = np.random.rand(2, 100)
In [214]: line, = ax.plot(x, y, '-', color='blue', linewidth=2)
plot
返回一个线条列表,因为你可以传入多组 x、y 值进行绘制。这里我们将长度为1的列表中的第一个元素解包到 line 变量中。该线条已被添加到 Axes.lines
列表中。
In [229]: print(ax.lines)
[<matplotlib.lines.Line2D at 0xd378b0c>]
类似地,创建图形补丁的方法,例如
bar()
会生成一个矩形列表,
这些补丁会被自动添加到 Axes.patches
列表中:
In [233]: n, bins, rectangles = ax.hist(np.random.randn(1000), 50)
In [234]: rectangles
Out[234]: <BarContainer object of 50 artists>
In [235]: print(len(ax.patches))
Out[235]: 50
不应直接将对象添加到 Axes.lines
或 Axes.patches
列表中,因为 Axes
在创建和添加对象时需要完成以下操作:
- 设置
Artist
的figure
和axes
属性;
- 设置默认的
Axes
变换(除非已存在变换设置); - 检查
Artist
中包含的数据,以更新控制自动缩放的数据结构,从而调整视图范围以包含绘制的数据。
不过,您可以自行创建对象,并通过 add_line
和 add_patch
等辅助方法直接将其添加到 Axes
中。以下是一个带注释的交互式会话示例,展示了具体过程:
In [262]: fig, ax = plt.subplots()
# create a rectangle instance
In [263]: rect = matplotlib.patches.Rectangle((1, 1), width=5, height=12)
# by default the Axes instance is None
In [264]: print(rect.axes)
None
# and the transformation instance is set to the "identity transform"
In [265]: print(rect.get_data_transform())
IdentityTransform()
# now we add the Rectangle to the Axes
In [266]: ax.add_patch(rect)
# and notice that the ax.add_patch method has set the Axes
# instance
In [267]: print(rect.axes)
Axes(0.125,0.1;0.775x0.8)
# and the transformation has been set too
In [268]: print(rect.get_data_transform())
CompositeGenericTransform(
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())),
CompositeGenericTransform(
BboxTransformFrom(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())))),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=0.88),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8),
Affine2D(
[[100、 0、 0.]
[ 0、100、 0.]
[ 0、 0、 1.]])))))))
# the default Axes transformation is ax.transData
In [269]: print(ax.transData)
CompositeGenericTransform(
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())),
CompositeGenericTransform(
BboxTransformFrom(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),
TransformWrapper(
BlendedAffine2D(
IdentityTransform(),
IdentityTransform())))),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=0.88),
BboxTransformTo(
TransformedBbox(
Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8),
Affine2D(
[[100、 0、 0.]
[ 0、100、 0.]
[ 0、 0、 1.]])))))))
# notice that the xlimits of the Axes have not been changed
In [270]: print(ax.get_xlim())
(0.0, 1.0)
# but the data limits have been updated to encompass the rectangle
In [271]: print(ax.dataLim.bounds)
(1.0, 1.0, 5.0, 12.0)
# we can manually invoke the auto-scaling machinery
In [272]: ax.autoscale_view()
# and now the xlim are updated to encompass the rectangle, plus margins
In [273]: print(ax.get_xlim())
(0.75, 6.25)
# we have to manually force a figure draw
In [274]: fig.canvas.draw()
存在大量用于创建基础Artists
并将其添加到对应容器的Axes
辅助方法。下表简要列举了部分方法、它们创建的Artist
类型及其存储位置:
Axes辅助方法 | Artist | 容器 |
---|---|---|
annotate - 文本标注 | Annotation | ax.texts |
bar - 柱状图 | Rectangle | ax.patches |
errorbar - 误差线图 | Line2D 和 Rectangle | ax.lines 和 ax.patches |
fill - 共享区域 | Polygon | ax.patches |
hist - 直方图 | Rectangle | ax.patches |
imshow - 图像数据 | AxesImage | ax.images |
legend - 坐标轴图例 | Legend | ax.get_legend() |
plot - xy坐标图 | Line2D | ax.lines |
scatter - 散点图 | PolyCollection | ax.collections |
text - 文本 | Text | ax.texts |
除了上述所有Artists
,Axes
还包含两个重要的Artist
容器:XAxis
和YAxis
,它们负责刻度线和标签的绘制。这些容器以实例变量matplotlib.axes.Axes.xaxis
和matplotlib.axes.Axes.yaxis
的形式存储。下文将详述XAxis
和YAxis
容器,但需注意Axes
包含许多将调用转发给Axis
实例的辅助方法,因此除非需要特殊控制,通常无需直接操作它们。例如,您可以通过Axes
辅助方法设置XAxis
刻度标签的字体颜色。
ax.tick_params(axis='x', labelcolor='orange')
以下是 Axes
包含的 Artists 类型总结:
坐标轴属性 | 描述 |
---|---|
artists | 由 Artist 实例组成的 ArtistList |
patch | 用于坐标轴背景的 Rectangle 实例 |
collections | 由 Collection 实例组成的 ArtistList |
images | 由 AxesImage 实例组成的 ArtistList |
lines | 由 Line2D 实例组成的 ArtistList |
patches | 由 Patch 实例组成的 ArtistList |
texts | 由 Text 实例组成的 ArtistList |
xaxis | matplotlib.axis.XAxis 实例 |
yaxis | matplotlib.axis.YAxis 实例 |
可通过 get_legend
方法访问图例。
坐标轴容器
matplotlib.axis.Axis
实例负责绘制刻度线、网格线、刻度标签和轴标签。对于y轴,您可以分别配置左右刻度;对于x轴,则可以分别配置上下刻度。Axis
还存储了用于自动缩放、平移和缩放的数据区间与视图区间,以及控制刻度位置和字符串表示的 Locator
和 Formatter
实例。
每个 Axis
对象都包含一个 label
属性(这是 pyplot
在调用 xlabel
和 ylabel
时修改的内容),以及一组主刻度和次刻度列表。这些刻度是 axis.XTick
和 axis.YTick
实例,包含实际渲染刻度和刻度标签的线条和文本基元。由于刻度是动态创建的(例如在平移和缩放时),您应该通过访问器方法 axis.Axis.get_major_ticks
和 axis.Axis.get_minor_ticks
来获取主刻度和次刻度列表。虽然刻度包含所有基元(下文会详细介绍),但 Axis
实例提供了返回刻度线、刻度标签、刻度位置等的访问器方法:
fig, ax = plt.subplots()
axis = ax.xaxis
axis.get_ticklocs()
array([0、, 0.2, 0.4, 0.6, 0.8, 1、])
axis.get_ticklabels()
[Text(0.0, 0, '0.0'), Text(0.2, 0, '0.2'), Text(0.4, 0, '0.4'), Text(0.6000000000000001, 0, '0.6'), Text(0.8, 0, '0.8'), Text(1.0, 0, '1.0')]
注意刻度线的数量是标签的两倍,因为默认情况下:
- 顶部和底部都有刻度线
- 但只有x轴下方显示刻度标签
不过这个设置是可以自定义调整的。
axis.get_ticklines()
<a list of 12 Line2D ticklines objects>
通过上述方法,默认情况下您只能获取主刻度线列表,但您也可以请求获取次刻度线:
axis.get_ticklabels(minor=True)
axis.get_ticklines(minor=True)
<a list of 0 Line2D ticklines objects>
以下是 Axis
类中一些实用访问器方法的总结(这些方法通常都有对应的设置器,例如 set_major_formatter()
)。
Axis 访问器方法 | 描述 |
---|---|
get_scale | 获取坐标轴的比例,例如 ‘log’ 或 ‘linear’ |
get_view_interval | 获取坐标轴视图限制的区间实例 |
get_data_interval | 获取坐标轴数据限制的区间实例 |
get_gridlines | 获取坐标轴的网格线列表 |
get_label | 获取坐标轴标签 - 一个 Text 实例 |
get_offset_text | 获取坐标轴偏移文本 - 一个 Text 实例 |
get_ticklabels | 获取刻度标签列表 - Text 实例,可通过关键字 minor=True |
get_ticklines | 获取刻度线列表 - Line2D 实例,可通过关键字 minor=True |
get_ticklocs | 获取刻度位置列表 - 可通过关键字 minor=True |
get_major_locator | 获取主刻度的 ticker.Locator 实例 |
get_major_formatter | 获取主刻度的 ticker.Formatter 实例 |
get_minor_locator | 获取次刻度的 ticker.Locator 实例 |
get_minor_formatter | 获取次刻度的 ticker.Formatter 实例 |
get_major_ticks | 获取主刻度的 Tick 实例列表 |
get_minor_ticks | 获取次刻度的 Tick 实例列表 |
grid | 控制主/次刻度网格线的显示开关 |
以下是一个自定义坐标轴和刻度属性的示例(虽然美观性不佳,但功能完整)。
# plt.figure creates a matplotlib.figure.Figure instance
fig = plt.figure()
rect = fig.patch # a rectangle instance
rect.set_facecolor('lightgoldenrodyellow')
ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4])
rect = ax1.patch
rect.set_facecolor('lightslategray')
for label in ax1.xaxis.get_ticklabels():
# label is a Text instance
label.set_color('red')
label.set_rotation(45)
label.set_fontsize(16)
for line in ax1.yaxis.get_ticklines():
# line is a Line2D instance
line.set_color('green')
line.set_markersize(25)
line.set_markeredgewidth(3)
plt.show()
刻度容器
matplotlib.axis.Tick
是我们从 Figure
到 Axes
,再到 Axis
,最后到 Tick
的最终容器对象。Tick
包含刻度线、网格线实例,以及上下刻度的标签实例。这些都可以直接作为 Tick
的属性进行访问。
刻度属性 | 描述 |
---|---|
tick1line | 一个 Line2D 实例 |
tick2line | 一个 Line2D 实例 |
gridline | 一个 Line2D 实例 |
label1 | 一个 Text 实例 |
label2 | 一个 Text 实例 |
以下是一个示例,它为 y 轴右侧的刻度设置美元符号格式,并将这些刻度标记为绿色。
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
fig, ax = plt.subplots()
ax.plot(100*np.random.rand(20))
# Use automatic StrMethodFormatter
ax.yaxis.set_major_formatter('${x:1.2f}')
ax.yaxis.set_tick_params(which='major', labelcolor='green',
labelleft=False, labelright=True)
plt.show()
脚本总运行时间: (0分钟1.044秒)
2025-08-22(五)