Matplotlib基础(1):图的组成元素

绘图技能是我一直想要拓展和延伸的一个技能。这一方面需要通过大量的输入来学习别人对图表的设计和呈现,学习色彩、布局等等……另一方面还要能够用代码来实现,而需要基于代码的可视化是一个比较繁琐的内容,需要学习和积累。故在此开始记录自己Python可视化的学习过程,当然,也便于代码的复用。本文主要涉及内容:

  1. Matplotlib中Figure的组成要素
  2. 主要元素的常用方法汇总
  3. 其他的诸如风格、字体、网格、图例、色带陆续总结……

一张好看的学术图表不仅能够更优雅简洁地传递信息,也能给人予美的享受。在撰写学术论文的过程,耗费大量时间的除了做实验,另一个一定是作图了,要通过几张图把信息很好地呈现出来,需要费不少功夫。

本系列笔记主要参考:Matplotlib usage, Matplotlibapi文档Matplotlib Gallery,部分参考Rougier老师的开源书

另外,快速绘图备忘录下载,该备忘录有两张大图(基础绘图;色彩及文字等),可以快速查看常见的绘图操作/函数,函数右侧的api还可以点击直达官网api文档详细介绍。

上图即通过matplotlib代码制作,详见book

图的组成

matplotlib最新版的文档做了较大的改版,提供了更全的api参考

下图是Matplotlib官方文档中提供的一张介绍图组成元素的图,很整洁,左图为旧版anatomy,右图为最新的文档anatomy里的图,我稍作改动放到了一起:

组成总览

  • Figure:所有绘图元素的顶级容器,大致可以理解为画布canvas。我们可以设置它的尺寸(figsize)、标题(suptile)、x标签(supxlabel)、背景颜色(facecolor )等属性,背景默认是透明 transparent=True。

  • Axes:相当于Subplot,子图,是我们实际的绘图区域,为矩形。一张图可以有多个子图(Axes),如上图

    • Spines: 图边,每个子图都有4条边,每条边有主副刻度线(Tick)+主副刻度标签(Tick labels)+边标签(Label),默认只显示左+下的Spine。
    • Axis:默认显示的左和下方的两条Spines分别为yaxis,xaxis,属性同Spines。
    • Line points...:绘制的图形,也就是我们要在axes上画的东西
    • Legend:图例,每个axes都可以根据其上绘制的图形生成图例,也可以不依赖图形单独创建。
    • Grid:网格线,自行选择是否添加(按照主副刻度线生成)
    • Text:文本,可以作为注释说明添加到图上
      • Annotation:可以添加连接线/箭头的文本,注释
  • Artist : Everything on the figure, including Figure, Axes, and Axis objects, is an artist. 理解为图元素。组成

了解了组成部件,之后我们的学习任务主要就是了解和属性各个部件繁多的属性和属性调整的方法,以及组合。下一节即有针对性地看一下各个元素的属性方法等。

教程; 绘图思路快速入门

图的基本单元

任意的一张图,本质上是由以下三种要素的组合(莫明想起了GIS里的点线面hh):

  • patchs:块,如background bars ……
  • lines:线,如tick,line……
  • texts:文本,如label title……

多数情况下我们都是使用绘图自带的默认设置,但是实际上,一张图的任一组成部分即上述部件都能够被访问和调整如我们可以像下面这样直接设置每个label加粗,这些方法都能够在文档中快速找到

1
2
3
4
fig, ax = plt.subplots(figsize=(5,2))
for label in ax.get_xaxis().get_ticklabels():
label.set_fontweight("bold")
plt.show()

🔥想强调的是,每个部件在我们创建了一个图形之后就有了对应的实例(对类不熟悉的可以移步Python中的类),通过查阅文档我们可以看到该对象的所有属性及方法,进一步地我们可以按需检索并实现我们对图形想要进行的任意设置或调整,下面开始介绍并举例:

主要部件详解

虽然有文档,但是我还是要熟悉一些常见的属性方法,以使我们能够快速出图,至于最终成图的细节则可以再细扣。另外,以下所有均来自Matplotlib3.5官方文档,一些参数细节暂不展开讲,在后续的总结中再慢慢铺开

Figure

class matplotlib.figure.Figure, 类的属性及方法

1
2
3
4
import matplotlib.pyplot as plt
# 创建一个 fig实例
fig = plt.figure(figsize=(5, 4))
fig, ax = plt.subplots()

常用属性及方法/函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 创建时即可传参
class matplotlib.figure.Figure(figsize=None, dpi=None, facecolor=None, edgecolor=None, linewidth=0.0, frameon=None, subplotpars=None, tight_layout=None, constrained_layout=None, *, layout=None, **kwargs)
# 添加子图
.add_subplot()
.add_axes()
.subplots()
.add_gridspec() #复杂布局时使用
# 日期ticklabels自动调整,自动旋转以免叠盖
.autofmt_xdate(bottom=0.2, rotation=30, ha='right', which='major')
# 添加色带
.colorbar(mappable, cax=None, ax=None, use_gridspec=True, **kw)
# 放置图例
.legend()
# 设置标题、文本
.suptitle()
.supxlabel(); .supylabel()
.text(x, y, s, fontdict=None, **kwargs)
# 保存,常用,常用设置会在另一篇文章展开
.savefig(fname, *, dpi='figure', format=None, metadata=None,
bbox_inches=None, pad_inches=0.1,
facecolor='auto', edgecolor='auto',
backend=None, **kwargs)
# 设置各种属性,可以一次性设置多个参数,详见文档
.set(*...)
.set_label(s)
.set_alpha(alpha)
.set_constrained_layout(constrained)
.set_constrained_layout_pads(*, w_pad=None, h_pad=None, wspace=None, hspace=None)
.set_dpi(); .set_edgecolor; .set_facecolor()...
# 获取
.gca() #当前axes
.get_axes()
.get_children()
.get_edgecolor(); .get_facecolor()
.get_figheight(); .get_figwidth()

🔥Axes-绘图区

class matplotlib.axes.Axes类的属性及方法

创建,有很多种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#常用
fig, ax = plt.subplots(ncols=2, nrows=3, figsize=(12,8), sharex=True)
axs[2, 0].plot([1,2,3,4,5]) #在第三行第一列绘图
ax_list = ax.flatten() #可以遍历获取各个axes

# 创建一张图,一个axes,
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(1, 1, 1, aspect=1)# aspect是xy横纵比
ax = fig.add_subplot(111, aspect=1)
#创建两个axes,一行两列
fig = plt.figure()
ax1,ax2 = fig.add_subplot(1, 2, 1, aspect=1),fig.add_subplot(1, 2, 2, aspect=1)
plt.show()
#创建两个axes,两行一列
fig = plt.figure()
ax1,ax2 = fig.add_subplot(1, 2, 1, aspect=1),fig.add_subplot(1, 2, 2, aspect=1)
plt.show()

#创建共享x、y轴的axes,左右双图
axes.twinx()
axes.twiny()
.sharex()# 也可以手动设置/绑定axes

# 大小不一多子图的复杂布局,使用gridspec,具体查阅文档
fig = plt.figure(constrained_layout=True)
gs = fig.add_gridspec(3, 3) #初始九个图
f_ax1 = fig.add_subplot(gs[0, :]) #合并了第一行的三个图,现在变成7张图
...

绘图(快速绘图)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.plot() #折线图
.scatter() #散点图
.bar() #柱状图
.pie() #饼图
.hist() #直方图
.boxplot() # 箱线图
.hexbin(); .hist2d() #二维直方图,√大量数据的相关性展示可用
.stackplot() #堆积柱状图
.violinplot() #小提琴图
.imshow() #绘制图片,二维矩阵栅格
# ...接口很多,还可以绘制洋流图、等高线、频谱图等

# 绘制x y辅助线
.vlines() #竖线
.hlines() #横线
# 水平填充、垂直填充、任意填充
.fill_between()
.fill_betweenx()
.fill()

添加注释

1
2
3
4
5
6
7
.annotate() #添加注释
.text() #添加注释
.secondary_xaxis() #添加水平轴;可以实现上下双刻度线,具体见文档
.secondary_yaxis() #添加垂直边;可以实现左右双刻度线
.arrow() #添加箭头
.inset_axes() #添加注释,插入子图
.table() #添加注释

要素属性设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.set_xlim(); .get_xlim()# 设置显示的范围,有set一般都有get
.set_ylim()
.set_xbound(); .set_ybound()# 设置上下界
.set_xlabel();.set_ylabel() #设置标签

.set_title() #设置标题
.set_xticks(); y... #设置刻度值
.set_xticklabels() #设置刻度标签
.minorticks_off(); .minorticks_on() #次刻度的显示设置
.ticklabel_format() #格式化labels,如可以设置科学计数法显示
.tick_params() # 各种参数包括网格线等的设置
.locator_params() #设置主刻度线,高级自定义
.set_position() #设置图像在图中的位置,比如可以设置绘图左下角起点

.set_xscale() #设置刻度变换
.set_yscale()
.set_xmargin() #设置绘制图形距离边/spines的距离,变相裁剪
.set_ymargin()
.set_aspect() #设置轴缩放的横纵比

.legend() #设置图例
h, l = ax.get_legend_handles_labels() #获取图例句柄及标签
.invert_xaxis();.invert_yaxis() #设置轴的增大方向

外观开关设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 隐藏
.set_axis_off()
.set_axis_on()
.grid()
.get_facecolor()
.set_facecolor()
.get_xaxis() #获取XAxis实例
.get_yaxis()
# 隐藏轴及标签
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
ax.xaxis.set_ticklabels([])
ax.yaxis.set_ticklabels([])

元素添加及参考系变换等,我们可以自行创建任意的图像然后添加到axes中

1
2
3
4
5
6
7
8
9
10
.add_artist()
.add_child_axes()
.add_collection()
.add_image()
.add_line()
.add_patch()
.add_table()
# 轴的标准化坐标0-1和实际坐标的变换可能用到,具体用法在另一篇展开
.get_xaxis_transform
.get_yaxis_transform

Spines-边框

class matplotlib.spines.Spine类的属性及方法

属性设置

1
2
3
4
5
6
7
8
9
10
11
12
13
#获取和设置显示/隐藏边框
ax.spines['top'].set_visible(False)
ax.spines.top.set_visible(False)
ax.spines[['top', 'right']].set_visible(False)
ax.spines[:].set_visible(False)
# 其他
.set_bounds(low=None, high=None)
.set_color(c) # 设置颜色
.set_position(position)#常用,设置位置

# 更改边界线的形状,实际上axes依旧是矩形
.set_patch_circle() # 设置为圆形
set_patch_arc(center, radius, theta1, theta2)

Text-文本

class matplotlib.text.Text类的属性及方法

1
2
3
4
5
class matplotlib.text.Text(x=0, y=0, text='', color=None, ...)
# 先添加文本
text = ax.text(s = "注释",x,y,c = 'r'...)# 可以通过这样的方式获取文本示例再设置属性
# 批量设置
.set(*, agg_filter=<UNSET>, alpha=<UNSET>, animated=<UNSET>,...)

属性具体设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.set_text(s) #设置字的内容 
.set_position((x,y))#设置字的位置
.set_x(x)
.set_bbox(rectprops) #设置字体外边框
.set_color(color); .set_c(color)
# 字体及大小
.set_font(fp); .set_fontproperties()
.set_family.(); .set_fontfamily()
.set_fontsize(fontsize)
# 设置加粗倾斜等
.set_fontstyle(fontstyle);#设置斜体{'normal', 'italic', 'oblique'}
.set_fontweight(weight) #字体粗细,{a numeric value in range 0-1000, 'ultralight', 'light', 'normal', 'regular', 'book', 'medium', 'roman', 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black'}
# 对齐方式
.set_ha(align);
.set_horizontalalignment(align)# align{'center', 'right', 'left'}
# 旋转角度
.set_rotation(s) #float or {'vertical', 'horizontal'}

# 行间距,默认1.2
.set_linespacing(spacing)
# 数学公式,生效的前提是未设置全局Tex,(usetex=True).
.set_math_fontfamily(fontfamily)
.set_usetex(usetex=True)

.update(kwargs) #dict,传入字典更新其属性
.update_from(other)

后续

待办

  1. 绘图逻辑与思路
  2. Matplotlib绘图初始设置模板(包含风格、字体等等的初始化)
  3. Matplotlib图片输出设置,空间占用与dpi的权衡……
  4. 绘图布局详解及案例
  5. 色彩及色带详解及案例
  6. 时间序列刻度详解及案例
  7. 文本及注释详解
  8. 其他绘图库了解及探索
  9. 地图绘制……
  10. ……