Matplotlib 1 - Pyplot、图像、图表


Pyplot 教程

https://matplotlib.org/stable/tutorials/pyplot.html

本文介绍 pyplot 接口的使用方法。建议同时参阅:


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])

pyplot


设置绘图样式

对于每一对 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()

pyplot


使用分类变量绘图

我们也可以利用分类变量来创建图表。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_boxmatplotlib.transform.Bbox 实例
clip_on[True
clip_pathPath 实例和 Transform 实例,或 Patch
color 或 c任意 matplotlib 颜色
contains命中检测函数
dash_capstyle['butt'
dash_joinstyle['miter'
dashes以点为单位的墨水开关序列
data(np.array xdata, np.array ydata)
figurematplotlib.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'
transformmatplotlib.transforms.Transform 实例
visible[True
xdatanp.array
ydatanp.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<10subplot 调用中的逗号可以省略。因此,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 可用于在任意位置添加文本,而 xlabelylabeltitle 则用于在指定位置添加文本(更详细的示例请参阅 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()

pyplot

在这个基础示例中,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库来加载图像数据。

以下是我们要操作的图像:


_images/stinkbug.png


这是一张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")

images

双三次插值常用于放大照片——人们通常更喜欢模糊效果而非像素化的效果。

脚本总运行时间: (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教程

大多数术语都很直观,但需要重点记住:

  • Figure 是最终图像,可能包含一个或多个 Axes
  • Axes 表示单个绘图区域(不要与表示x/y/z轴的 Axis 混淆)

我们直接从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.Figureaxes.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.FigureCanvasmatplotlib.backend_bases.Renderer 负责处理与用户界面工具包(如 wxPython)或绘图语言(如 PostScript®)交互的所有底层细节,而 Artist 则处理所有高级结构,如图形表示、布局、文本和线条。典型用户 95% 的时间都会与 Artists 打交道。

Artists 分为两类:图元(primitives)和容器(containers)。图元代表我们想在画布上绘制的标准图形对象:Line2DRectangleTextAxesImage 等;容器则是放置这些图元的位置(AxisAxesFigure)。

标准用法是创建一个 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())来创建常见图形基元(分别对应Line2DTextRectangleAxesImage)。

这些辅助方法会自动处理输入数据(例如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 时,它会将信息传递给 XAxisText 实例。每个 Axes 实例都包含一个 XAxisYAxis 实例,这些实例负责处理刻度线、刻度标签和轴标签的布局与绘制。

尝试创建下图。


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.patchAxes.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派生的类,例如FigureRectangle。以下是上述提到的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 = [[  00.]  [6400.]  [640480.]  [  0480....
  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的位置。


图形容器

顶级容器 Artistmatplotlib.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.gcaFigure.sca)以支持pylab/pyplot状态机,因此不应直接从坐标轴列表中插入或删除坐标轴,而应使用 add_subplot()add_axes() 方法进行插入,以及 Axes.remove 方法进行删除。不过,您可以自由地遍历坐标轴列表或通过索引访问需要自定义的 Axes 实例。下面是一个开启所有坐标轴网格线的示例:

for ax in fig.axes:
    ax.grid(True)

该图形还拥有自己的imageslinespatchestext属性,您可以直接通过这些属性添加图元。但需注意,此时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

以下是该图表中包含的Artists(图形元素)概述:

图表属性描述
axesAxes实例的列表
patch背景的Rectangle矩形
imagesFigureImage图像块的列表 - 用于原始像素显示
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.linesAxes.patches 列表中,因为 Axes 在创建和添加对象时需要完成以下操作:

  • 设置 Artistfigureaxes 属性;
  • 设置默认的 Axes 变换(除非已存在变换设置);
  • 检查 Artist 中包含的数据,以更新控制自动缩放的数据结构,从而调整视图范围以包含绘制的数据。

不过,您可以自行创建对象,并通过 add_lineadd_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(
                            [[10000.]
                             [  01000.]
                             [  001.]])))))))

# 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(
                            [[10000.]
                             [  01000.]
                             [  001.]])))))))

# 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 - 文本标注Annotationax.texts
bar - 柱状图Rectangleax.patches
errorbar - 误差线图Line2DRectangleax.lines 和 ax.patches
fill - 共享区域Polygonax.patches
hist - 直方图Rectangleax.patches
imshow - 图像数据AxesImageax.images
legend - 坐标轴图例Legendax.get_legend()
plot - xy坐标图Line2Dax.lines
scatter - 散点图PolyCollectionax.collections
text - 文本Textax.texts

除了上述所有ArtistsAxes还包含两个重要的Artist容器:XAxisYAxis,它们负责刻度线和标签的绘制。这些容器以实例变量matplotlib.axes.Axes.xaxismatplotlib.axes.Axes.yaxis的形式存储。下文将详述XAxisYAxis容器,但需注意Axes包含许多将调用转发给Axis实例的辅助方法,因此除非需要特殊控制,通常无需直接操作它们。例如,您可以通过Axes辅助方法设置XAxis刻度标签的字体颜色。


ax.tick_params(axis='x', labelcolor='orange')

以下是 Axes 包含的 Artists 类型总结:

坐标轴属性描述
artistsArtist 实例组成的 ArtistList
patch用于坐标轴背景的 Rectangle 实例
collectionsCollection 实例组成的 ArtistList
imagesAxesImage 实例组成的 ArtistList
linesLine2D 实例组成的 ArtistList
patchesPatch 实例组成的 ArtistList
textsText 实例组成的 ArtistList
xaxismatplotlib.axis.XAxis 实例
yaxismatplotlib.axis.YAxis 实例

可通过 get_legend 方法访问图例。


坐标轴容器

matplotlib.axis.Axis 实例负责绘制刻度线、网格线、刻度标签和轴标签。对于y轴,您可以分别配置左右刻度;对于x轴,则可以分别配置上下刻度。Axis 还存储了用于自动缩放、平移和缩放的数据区间与视图区间,以及控制刻度位置和字符串表示的 LocatorFormatter 实例。

每个 Axis 对象都包含一个 label 属性(这是 pyplot 在调用 xlabelylabel 时修改的内容),以及一组主刻度和次刻度列表。这些刻度是 axis.XTickaxis.YTick 实例,包含实际渲染刻度和刻度标签的线条和文本基元。由于刻度是动态创建的(例如在平移和缩放时),您应该通过访问器方法 axis.Axis.get_major_ticksaxis.Axis.get_minor_ticks 来获取主刻度和次刻度列表。虽然刻度包含所有基元(下文会详细介绍),但 Axis 实例提供了返回刻度线、刻度标签、刻度位置等的访问器方法:

fig, ax = plt.subplots()
axis = ax.xaxis
axis.get_ticklocs()

artists


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()

artists


刻度容器

matplotlib.axis.Tick 是我们从 FigureAxes,再到 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(五)

在使用 `matplotlib.pyplot` 绘图时,去除图像的外框线可以通过对坐标轴对象进行操作来实现。外框线通常指的是围绕图表的四条边线,可以通过设置坐标轴的可见性来控制这些边线是否显示。 以下是几种常见的方法来去除图像的外框线: ### 1. 去除所有边框线 如果需要去除图像的所有外框线,可以使用 `spines` 属性来隐藏所有的边框线: ```python import matplotlib.pyplot as plt # 创建一个简单的图像 plt.plot([1, 2, 3], [4, 5, 1]) # 获取当前的坐标轴对象 ax = plt.gca() # 隐藏所有边框线 for spine in ax.spines.values(): spine.set_visible(False) plt.show() ``` ### 2. 去除特定边框线 如果只需要去除某些边框线(例如顶部和右边的边框线),可以单独设置这些边框线的可见性: ```python import matplotlib.pyplot as plt # 创建一个简单的图像 plt.plot([1, 2, 3], [4, 5, 1]) # 获取当前的坐标轴对象 ax = plt.gca() # 隐藏顶部和右边的边框线 ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.show() ``` ### 3. 保留底部和左侧边框线 有时可能希望保留底部和左侧的边框线,而去除顶部和右边的边框线。这可以通过以下方式实现: ```python import matplotlib.pyplot as plt # 创建一个简单的图像 plt.plot([1, 2, 3], [4, 5, 1]) # 获取当前的坐标轴对象 ax = plt.gca() # 隐藏顶部和右边的边框线 ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) # 确保底部和左侧的边框线可见 ax.spines['bottom'].set_visible(True) ax.spines['left'].set_visible(True) plt.show() ``` ### 4. 自定义边框线样式 如果不想完全隐藏边框线,而是希望自定义其样式(例如颜色或宽度),可以使用以下方法: ```python import matplotlib.pyplot as plt # 创建一个简单的图像 plt.plot([1, 2, 3], [4, 5, 1]) # 获取当前的坐标轴对象 ax = plt.gca() # 自定义边框线的颜色和宽度 for spine in ax.spines.values(): spine.set_edgecolor('red') spine.set_linewidth(2) # 隐藏顶部和右边的边框线 ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.show() ``` ### 5. 使用面向对象的 API `matplotlib` 提供了面向对象的 API,可以直接通过 `Figure` 和 `Axes` 对象来操作图表。这种方法在处理复杂的图表时更加灵活和直观: ```python import matplotlib.pyplot as plt # 创建一个 Figure 和 Axes 对象 fig, ax = plt.subplots() # 绘制数据 ax.plot([1, 2, 3], [4, 5, 1]) # 隐藏顶部和右边的边框线 ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) plt.show() ``` 通过这些方法,可以根据具体需求灵活地控制图像的外框线,从而实现更美观的图表效果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EAI工程笔记

请我喝杯伯爵奶茶~!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值