matplotlib notes - 9dian/Index GitHub Wiki

matplotlib架构分层总览

matplotlib 架构上分为三层,这是matplotlib 能用不同方式来实现同一功能的原因。

底层:backend layer

中层:artist layer

最高层:scripting layer

在任意一层操作都能够实现画图的目的,而且画出来还都一样。但越底层的操作越细节话,越高层越易于人机交互。

.plt 对应的就是最高层 scripting layer。这就是为什么它简单上手,但要调细节就不灵了。

ax.plot 是在 artist layer 上操作。基本上可以实现任何细节的调试。

backend layer, 至今,我还没有见有人在这个layer上操作过。

另外,对于axes (翻译就是 坐标系),我看到有个评论写了很多,说的没有错,但也没说到点子上。

如果大家学过大学物理的话,会知道每一个物体都有一个独立的坐标系。而matplotlib 就是引用这一理念。所以在artist layer上画多条曲线时,你会用 ax1.plot, ax2.plot ... 而最后显示在一张图上是因为所有独立坐标系对齐的结果。

matplotlib组建示意图

Figure, Axes, Axis介绍

Parts of a Figure

  • Figure fig = plt.figure(): 可以解释为画布。 画图的第一件事,就是创建一个画布figure,然后在这个画布上加各种元素。

  • Axes ax = fig.add_subplot(1,1,1): 不想定义,没法定义,就叫他axes! 首先,这个不是你画图的xy坐标抽! 希望当初写这个lib的时候他们用一个更好的名字。。。 可以把axes理解为你要放到画布上的各个物体。比如你要画一个太阳,一个房子,一个车在画布上,那么太阳是一个axes,房子是一个axes,etc。 如果你的figure只有一张图,那么你只有一个axes。如果你的figure有subplot,那么每一个subplot就是一个axes axes是matlibplot的宇宙中心!axes下可以修改编辑的变量非常多,基本上能包含你的所有需求。

  • Axis ax.xaxis/ax.yaxis: 对,这才是你的xy坐标轴。 每个坐标轴实际上也是由竖线和数字组成的,每一个竖线其实也是一个axis的subplot,因此ax.xaxis也存在axes这个对象。对这个axes进行编辑就会修改xaxis图像上的表现。

要为 figure 和 axes 添加边框线,可以通过以下方式实现:

为 figure 添加边框:

Matplotlib 中没有直接的方法为 figure 添加边框线,但你可以通过在 figure 周围创建一个额外的 axes 来实现这一点。这种方法可以模拟边框的效果。

为 axes 添加边框:

axes 本身有一个 spines 属性,表示坐标轴周围的四条边框线。你可以通过设置这些 spines 的颜色和宽度来为 axes 添加边框。

下面是为 figure 和 axes 添加边框的代码示

import matplotlib.pyplot as plt

# 创建 figure
fig, ax = plt.subplots(figsize=(6, 4))

# 绘制示例数据
ax.plot([0, 1, 2], [0, 1, 4])

# 为 axes 添加边框
for spine in ax.spines.values():
    spine.set_edgecolor('red')  # 边框颜色
    spine.set_linewidth(2)      # 边框宽度

# 为 figure 添加边框:通过添加一个 axes 作为边框
# border_ax = fig.add_axes([0.05, 0.05, 0.9, 0.9])  # 创建一个与 figure 大小接近的 axes
border_ax = fig.add_axes([0, 0, 1, 1])  # 创建一个与 figure 大小接近的 axeszz
for spine in border_ax.spines.values():
    spine.set_edgecolor('blue')  # 边框颜色
    spine.set_linewidth(3)       # 边框宽度
border_ax.set_xticks([])  # 移除X轴刻度
border_ax.set_yticks([])  # 移除Y轴刻度
border_ax.patch.set_alpha(0)  # 设置背景为透明

plt.show()

为 figure 添加边框:通过 fig.add_axes() 创建一个几乎覆盖整个 figure 的 axes,并设置其 spines 属性来模拟边框效果。add_axes([left, bottom, width, height]) 参数控制新 axes 的位置和大小。

移除刻度:为了让这个额外的 axes 仅表现为边框,你可以通过 set_xticks([]) 和 set_yticks([]) 移除刻度,同时设置 patch.set_alpha(0) 使背景透明。

通过这种方法,你可以在 figure 和 axes 上绘制边框线并自定义它们的外观。

开发步骤示例

import matplotlib.pyplot as plt
import numpy as np

A = np.arange(1,11)
B = A**2
C = A**3

首先,搞个画布

我喜欢用这个命令来开始画图。哪怕你没有subplot,也可以用这个subplots来创建一个画布。

这个function创建了一个大小为(14,7)的画布,把这个画布赋值给变量fig,同时在这个画布上创建了一个axes,把这个axes赋值给ax。这样,所有未来的都是对这个画布的操作,所有都是对这个axes的操作。

如果你有两个图,那么ax是一个有两个元素ax[0],ax[1] 的list。ax[0]就对应第一个subplot的ax。

fig, ax = plt.subplots(figsize=(12,8))

好了画布搞好了,画数据。

注意,我们这里依然不使用plt!因为我们要在这个axes上画数据,因此就用ax.plot()来画。画完第一个再call一次,再画第二个。

ax.plot(A,B)
ax.plot(B,A)


下面开始细节的处理

数据画好了就可以各种细调坐标轴啊,tick啊之类的。

首先把标题和xy坐标轴的标题搞定。

Again, 不用plt。直接在axes上进行设定。

ax.set_title('Title',fontsize=18)
ax.set_xlabel('xlabel', fontsize=18,fontfamily = 'sans-serif',fontstyle='italic')
ax.set_ylabel('ylabel', fontsize='x-large',fontstyle='oblique')
ax.legend()

然后是xy坐标轴的一些属性设定, 也是在axes level上完成的

ax.set_aspect('equal') 
ax.minorticks_on() 
ax.set_xlim(0,16) 
ax.grid(which='minor', axis='both')

最后是坐标轴tick和细节,这个在axes.xaxis or axes.yaxis上完成。

ax.xaxis.set_tick_params(rotation=45,labelsize=18,colors='w') 
start, end = ax.get_xlim() 
ax.xaxis.set_ticks(np.arange(start, end,1)) 
ax.yaxis.tick_right()

这样一个丑陋的基本图的绘画和编辑就完成了。如果有一些其他的细节调整,在搜索的时候,尽量选择不用plt的答案。

原则上来说,plt和ax画图两者是可以互相转换的,然而转换过程让你的代码更复杂,有时还会产生难以理解的bug。

ref: https://matplotlib.org/stable/tutorials/introductory/quick_start.html

https://www.geeksforgeeks.org/matplotlib-pyplot-subplots-in-python/

https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots.html

性能

官方有性能优化的提示。比如散点图,推荐用 plot(marker='o') 而不是 scatter;以及利用 Rasterization 方法将数据喂入 plot() 方法中。