matplotlib必会|使用OffsetBox尽情的添加自定义元素!
大家好,我是早起。
如果你对数据可视化感兴趣,可以点击上方「可视化图鉴」关注!
我们都知道,如果想要在matplotlib中添加文字注释可以使用plt.text
根据坐标来添加,如果想要添加箭头也同样可以使用plt.arrow
根据坐标完成。
那如果想要添加自定义的图片呢?
在matplotlib中添加自定义图片有多种方法,本文将基于matplotlib中的Artists
容器类讲解,如何在我们制作的图中添加任意自已想要的元素。
作为示例,和以前的文章一样,本文不罗列各种参数,用下图作为示例,step by step的介绍每部分制作流程
一句话看懂原理
关于Artists
类的中文参考文章并不多,为了方便后面解释,我从官方文档中找到一张比较容易理解的图👇
如上图所示,我们使用的是Artists
类中的OffsetBox
模块,我们将想要展示的元素(文字、图片等)放在这个模块中,并使用AnnotationBbox
根据坐标放在指定位置。
那么和类似plt.text直接添加文字等操作有什么区别呢,本文这个方法要求你先创建一个需要放置的元素,本质上是两个步骤,而plt.xxxx
则是简单调用API,一步完成。
因为此时我们将制作元素和防止元素分隔开,所以就可以有更多的细节支持调整,下面我们来基于例子讲解。
导入与初始化
老规矩,首先我们需要导入相关库,并创建一张画布
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
from matplotlib.offsetbox import (TextArea, DrawingArea, OffsetImage,
AnnotationBbox)
from matplotlib.cbook import get_sample_data
fig, ax = plt.subplots(figsize = (9,7),dpi = 150)
ax.set_xlim(0,1)
ax.set_ylim(0,1)
其中TextArea=用于创建文字元素,OffsetImage用于创建图片元素,导入之后我们创建画布并调整了坐标轴范围。
添加自定义图片
现在我们来讲解如何添加自定义图片到画布中,其实很简单,总共分两步,根据路径打开一张图片-->根据坐标添加到画布中
先是打开一张图片,在仿制官方文档图中我们使用mpimg.imread
打开
arr_lena = mpimg.imread('/Users/liuhuanshuo/Desktop/WechatIMG2278.png')
这里我们也可以使用with语句
with get_sample_data("/Users/liuhuanshuo/Desktop/可视化图鉴/多媒体素材/logo/高清图/水印.png") as file:
arr_img = plt.imread(file, format='png')
这里不多解释,两种方法等价,就是根据路径打开一张图片,接下来将图片放在OffsetBox容器中
imagebox = OffsetImage(arr_img, zoom=0.2)
imagebox.image.axes = ax
接下来使用AnnotationBbox添加到画布中
ab = AnnotationBbox(imagebox, [0.15,0.5],
xybox=(170., -50.),
xycoords='data',
boxcoords="offset points",
pad=0.5
)
这个AnnotationBbox接收的参数比较多,也比较复杂,这里我们仅说下常用的几个参数。
首先第一个参数是你要添加到画布的元素,这里就是刚刚存储图片的imagebox
,之后总要告诉它放在哪里,所以接下来是一个坐标。
后面的xybox、xycoords、boxcoords是什么呢?
注意到我们可以发现在初始化时,我有这样一行代码imagebox.image.axes = ax
其实这里的ax并不是我们看到画布中的坐标系,而是这个元素自己有一个坐标系,为什么要新建一个坐标系,就是为了方便调整!
比如若沿用画布原有坐标系,我要是想将元素放置到坐标系外,就没有办法了,所以我们元素自己有一个坐标系这样就没有限制了!
所以我们用xycoords、boxcoords来控制这个新坐标系的位置,而xybox就是在这个坐标系中的偏移量,比如data
就是沿用原有坐标系,其他位置参数参考如下:
参数 | 说明 |
---|---|
'figure points' | 距离图形左下角的点数量 |
'figure pixels' | 距离图形左下角的像素数量 |
'figure fraction' | 0,0 是图形左下角,1,1 是右上角 |
'axes points' | 距离轴域左下角的点数量 |
'axes pixels' | 距离轴域左下角的像素数量 |
'axes fraction' | 0,0 是轴域左下角,1,1 是右上角 |
'data' | 使用轴域数据坐标系 |
这一块理解起来是比较抽象的,我建议如果想搞明白,可以一边修改参数,一边观察图片变化来加深理解!
最后用ax.add_artist(ab)
应用,我们的图片就成功加入到画布中了!
添加文字、箭头
下面介绍如何添加文字和箭头,其实和添加图片一样,把字写好加上去呗!我们直接看代码,使用的是TextArea
存储需要展示的文字
offsetbox = TextArea("这是我的公众号",textprops = dict(fontsize = 15))
ab = AnnotationBbox(offsetbox, [0.73, 0.5],
xybox=(1.05, 0.5),
xycoords='data',
boxcoords=("axes fraction", "data"),
box_alignment=(0., 0.5),
arrowprops=dict(arrowstyle="->"))
ax.add_artist(ab)
offsetbox = TextArea("微信搜索:可视化图鉴",textprops = dict(fontsize = 15))
ab = AnnotationBbox(offsetbox,[0.53, 0.72],
xybox=(-20, 70),
xycoords='data',
boxcoords="offset points",
arrowprops=dict(arrowstyle="->",color = 'deeppink'))
ax.add_artist(ab)
可以看到,我先使用TextArea
创建文字,和其他要出现文字的方法一样,支持调整字体、大小等参数,传给textprops即可,不多解释。
接下来使用AnnotationBbox添加文字,这里和刚刚是一样的,指定坐标、指定坐标系、指定偏移量。
注意这里我在添加这是我的公众号
几个字的时候,指定的坐标系就是boxcoords=("axes fraction", "data")
,一个是画布坐标系data另一个一个是自己的坐标系axes fraction,这样我就能够根据偏移量来将文字添加到原有画布坐标系之外。
大家可以自己体会一下,如果不明白还是建议可以一边修改参数,一边观察图片变化来加深理解!
最后是添加箭头,这里添加箭头是在添加文字同时完成的,只需要设定arrowprops
就能根据上面的坐标添加箭头了!
箭头的样式除了图中的还有更多的样式可以通过arrowprops进行调整,大家可以自行参考来修改上面的箭头形状、颜色,关于箭头的详细设置我会在下一篇的箭头专题中单独讲解!
现在我们的图案就是这样,注意这里其实是有两个坐标系(可以这么理解):一个是原有画布的(利用坐标值的绝对量控制)另一个是用于放置元素的(利用相对偏移量控制)!
彩蛋
最后想说一下,offsetbox
的用法远不止添加文字、图片,比如使用offsetbox
设置箭头除了可以调整颜色、大小、位置,还有更多的样式可以实现👇
这个就是可以自定义箭头的类型、角度,比如我们进一步设置弯的箭头,就是在添加图片哪里额外增加一个箭头样式参数connectionstyle="angle3,angleA=0,angleB=30")
接着添加新如下文字
offsetbox = TextArea("专注于数据可视化",textprops = dict(fontsize = 12))
ab = AnnotationBbox(offsetbox,[0.13, 0.57],
)
ax.add_artist(ab)
小结
到这里,有关offsetbox
我要讲解的就结束了,大家应该可以看到使用offsetbox
添加元素时,对细节的调整更加丰富,所以如果你在matplotlib绘图路上走的更远,这个模块你必须要会使用!
最后早起想说的是,本文介绍的库还是比较复杂的,我已经尽可能努力的解释,如果你还是感觉抽象,那就撸起袖子写代码(完整代码全部在文中!),一边修改参数,一边观察图片变化来加深理解!有任何疑问也可以给我留言,谢谢!
最后还是厚着脸皮说一下,如果大家喜欢本文,希望看到更多本系列文章,可以帮忙点赞、在看、转发,谢谢!
如果你也对数据可视化感兴趣,可以长按扫描下方二维码关注!