matplotlib notes - 9dian/Index GitHub Wiki
matplotlib架构分层总览
matplotlib 架构上分为三层,这是matplotlib 能用不同方式来实现同一功能的原因。
中层:artist layer
最高层:scripting layer
在任意一层操作都能够实现画图的目的,而且画出来还都一样。但越底层的操作越细节话,越高层越易于人机交互。
.plt 对应的就是最高层 scripting layer。这就是为什么它简单上手,但要调细节就不灵了。
ax.plot 是在 artist layer 上操作。基本上可以实现任何细节的调试。
backend layer, 至今,我还没有见有人在这个layer上操作过。
另外,对于axes (翻译就是 坐标系),我看到有个评论写了很多,说的没有错,但也没说到点子上。
如果大家学过大学物理的话,会知道每一个物体都有一个独立的坐标系。而matplotlib 就是引用这一理念。所以在artist layer上画多条曲线时,你会用 ax1.plot, ax2.plot ... 而最后显示在一张图上是因为所有独立坐标系对齐的结果。
Figure, Axes, Axis介绍
-
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() 方法中。