画出这张官方神图,你的Matplotlib就毕业了!
大家好,我是早起。
在昨天的文章人人都能看懂的Matplotlib绘图原理中,我们对Matplotlib的绘图机制进行了讲解,在弄清楚plt.xxxx
和ax.xxxx
中plt和ax区别之后,本文继续讲解xxxx
究竟是什么。
现在我们应该知道Matplotlib绘图其实很简单,不就是弄一块画布,然后往这块画布上添加我们要的图形,最后就是进行修饰。
如何添加画布/绘图区域已经讲过,如何添加图形,看我发的各种可视化图鉴就行了,而最需要花时间的就是对初步成型的图案进行修饰,先来看一张来自官方文档的图
我们可以看到,其实无非就是设置标题、图例、坐标轴、标记点等操作,这部分看起来简单,不过有时因为数据的原因,想要调整到一个合适的样式,是需要花费心思的。
但不论如何,能用到的Matplotlib修饰操作就这么多,本文将按照上图的顺序带大家手把手的绘制出图中的每一部分,希望以这种方式对常用的修饰语法进行讲解!
如果你能独立的,简单思考查询后能将这张图画出来,那么matplotlib基本就算毕业了!
请注意,由于篇幅原因,本文对大多数方法仅作简单介绍,因此并不适合作为速查手册使用,详细的matplotlib各组件设置,点击菜单栏查看专题文章。
标题
首先是标题,如果是使用plt.xxxx
那么就用plt.title()
,如果使用ax.xxxx
可以使用ax.set_title()
,现在我们把标题做成官方文档的样式,更多标题的修改方法可以查看matplotlib标题设置
plt.rc('font',family='Avenir')
plt.figure(figsize = (8,7), dpi=100)
plt.title('Anacomy of a figure',fontsize = 20,fontweight='heavy')
plt.show()
刻度
搞定了标题,下一步就是刻度了,根据我的了解,因为自己的数据原因,大多需要对刻度进行调整,但是修改刻度,相对复杂一点,所以很多人多会卡在刻度设置上。
其实设置刻度确实体育达标复杂,从图中我们可以看到又分为主、副刻度,再算上xy轴,一共就是4个刻度需要设置。
因为比较复杂,所以建议使用ax.xxxx
进行设置。这里我们首先需要把刻度读取出来,先使用的语法为
ax = plt.gca()
意思是Get Current Axes,获得当前绘图区域,接下来使用ax.set_xlim
设置x坐标轴范围,等同于plt.xlim()
,y轴同理
ax.set_xlim(0,4)
ax.set_ylim(0,4)
现在坐标轴范围搞定了,接下来就是比较复杂的刻度调整,我们可以看到,从官方示例图中,我们可以发现在matplotlib中,一个坐标轴,分为主副两个刻度。
关于坐标轴刻度的设置详情,可以参考matplotlib刻度设置文章,我们先来设置x、y轴的主刻度,只需要将间隔调整为1即可,通过修改locator
类完成
xmajorLocator = MultipleLocator(1)ax.xaxis.set_major_locator(xmajorLocator)
ymajorLocator = MultipleLocator(1)ax.yaxis.set_major_locator(ymajorLocator)
主刻度的调整就完成了,接下来是副刻度的调整,我们需要将x轴副刻度以0.25为单位分开,并显示数值,y轴副刻度同样为0.25但是不显示数值,以x轴为例,调整副刻度及数值显示可以通过·ax.xaxis.set_minor_formatter和
ax.yaxis.set_minor_locator`实现
xminorLocator = MultipleLocator(0.25)
ax.xaxis.set_minor_locator(xminorLocator)
yminorLocator = MultipleLocator(0.25)
ax.yaxis.set_minor_locator(yminorLocator)
xminorFormatter = FormatStrFormatter('%0.2f')
ax.xaxis.set_minor_formatter(xminorFormatter)
可以看打,现在的主副刻度已经做的差不多了,但是官方示例图中的刻度线更长一点,对刻度线进行调整可以使用tick_params
tick_params(which='major',length=8)tick_params(which='minor',length=4)
网格线
刻度线搞定之后,下一步添加网格线,我们可以使用ax.xaxis.grid
和ax.yaxis.grid
分别对指定x轴和y轴的网格线,可选参数非常多,详见matplotlib网格线设置
在这里,我们按照官方示例图的样式,两个坐标轴都添加主刻度网格线,并使用,linestyle = (0,(10,5))对线性进一步调整
ax.xaxis.grid(True, which='major',linestyle = (0,(8,4)))
ax.yaxis.grid(True, which='major',linestyle = (0,(8,4)))
现在看我们的图是不是和示例图有几分相似了呢👇
坐标轴文字
现在继续给坐标轴添加文字,这部分就比较简单了,当然我也写了详细的文档,这里使用ax.set_xlabel
或者plt.xlabel
都可以,我们使用如下代码
ax.set_xlabel('X axis label',fontsize = 12)ax.set_ylabel('Y axis label',fontsize = 12)
添加图像
现在对于画布的修饰部分,基本就结束了,下面添加图形,示例图中一共有两个折线图和一个散点图,我们拟合部分数据并制作进行,这里使用ax.plot
和ax.scatter
分别制作折线图和散点图,不知道怎么画的可以看我之前发的各种图鉴
x = list(np.arange(0.5,3.3,0.1))
y1 = [-0.04658*i**3+0.5494*i**2-1.3151*i + 1.415 for i in x]
ax.plot(x,y1,color = 'red',alpha = 0.7, linewidth=2.3)
x = list(np.arange(0.5,3.5,0.1))
y2 = [0.1545*i**3-0.799*i**2+0.4316*i + 3.744 for i in x]
ax.plot(x,y2,color = 'blue',alpha = 0.7, linewidth=2.3)
ax.scatter(A, B,marker = 'o',color='w',edgecolors='black')
现在,是不是感觉非常相似了!我们继续。
添加图例
整体还差最后一个图例就完成了,添加图例比较简单,使用plt.legend()
或者ax.legend()
都可以实现,不过需要在绘图是添加label标签才行
添加文字
其实图像主体部分已经完成了,但是原来的示例图中还有一些蓝色的文字,我们也添加进来,其实用到的就是plt.text(),也是非常常见的一个用法,我在matplotlib添加注释中有详细讲解,本文这里就是根据坐标添加文字,部分代码如下
ax.text(2.9,2.7,'Gird',family = 'DejaVu Sans',fontsize = 11,color = 'blue',weight='heavy')ax.text(3.45,3.45,'Legend',family = 'DejaVu Sans',fontsize = 10,color = 'blue',weight='heavy')ax.text(1.5,3.85,'Title',family = 'DejaVu Sans',fontsize = 11,color = 'blue',weight='heavy')ax.text(-0.25,3.75,'Major tick',family = 'DejaVu Sans',fontsize = 10,color = 'blue',weight='heavy')ax.text(-0.25,3.25,'Minor tick',family = 'DejaVu Sans',fontsize = 10,color = 'blue',weight='heavy')ax.text(-0.45,2.75,'Major tick label',family = 'DejaVu Sans',fontsize = 10,color = 'blue',weight='heavy')ax.text(0.12,-0.5,'Minor tick label',family = 'DejaVu Sans',fontsize = 10,color = 'blue',weight='heavy')
其中箭头是通过ax.arrow
做出来的,使用方法和ax.text
一样通过调整坐标控制
ax.arrow(3.3,0.41,-0.15,-0.33,ec='blue',head_width=0.04)
ax.arrow(3.6,0.41,0.32,-0.15,ec='blue',head_width=0.04)
现在我们的画的图和官方文档的示例图已经差不多一样了,唯一就是差了在不同组件旁的类似放大镜效果的图片。
添加自定义图片
最后,让我们和官方文档一样,在注释的位置添加指定图片,来达到一种放大的感觉。
在Matplotlib中,添加图片的方法有多种,这里我们选择使用ax.add_artist()
,详细讲解在后续文章中更新,简单来说就是打开一张图片,之后根据坐标添加到我们想要的位置就行了。
以左上角Major tick的圆为例,我们使用OffsetImage
打开一张图片
arr_lena = mpimg.imread('/Users/liuhuanshuo/Desktop/WechatIMG2278.png')imagebox = OffsetImage(arr_lena, zoom=0.38)
之后使用a1 = AnnotationBbox(imagebox, (0, 4), frameon = False)
设置图片位置,最后使用ax.add_artist(a1)
就能添加一个空心圆在左上角,之后如法炮制就可以了。
最终我们制作的仿官方文档效果图如下