气象绘图加强版(四)—坐标名、刻度、轴

我只是一个虾纸丫 提交于 2020-11-09 00:58:31

本节提要:前面已经陆陆续续有一些关于这三类的讲解,但是分散在各章中,不太方便大家查找,所以加强版做了这一期合集,来方便大家使用。




一、轴坐标名

这一节主要讲解图的坐标名的设置方法、常用的美化命令。

首先是设置坐标名称的命令【plt.xlabel (ylabel) 】或者【ax.set_xlabel (ylabel)】

在其中以引号输入你需要的标题文本,如:

ax.set_xlabel('x轴的名称')

这样就会生成x轴坐标名,y轴同理。当然,大多数时候这个最质朴的命令是无法满足我们的需求的。由于该命令完全是基于text模块的,所以他能使用text模块的关键字参数。下面列举了一些常用的设置关键字参数:

fontsize
修改文本的字号(大小)


alpha
修改文本的透明度
backgroundcolor
背景颜色


bbox
给标签加上多种样式的边框
color
标签文本的颜色
family
字体的样式,如黑体、仿宋、楷体等
ha、va
横向、纵向的位置,如center、left
rotation
文本旋转的角度,一般用数字来控制
position
标签的位置,(x,y)样式传入
loc
控制标签的位置,‘top’,‘left’等

下面这幅图使用了一些参数,需要注意的是bbox这个参数需要以字典的方式附带一些方框的参数(这个字典里的参数只控制这个方框的样式)。当然你也可以将这些参数进一步写到字典里,在下面程序段中,最后一个语句和第一个语句效果是一样的:

ax.set_xlabel('批次',color='k',backgroundcolor='tab:blue',rotation=45)ax.set_ylabel('产量',color='tab:orange',fontsize=20,              position=(0,0.225),family='FangSong',              bbox={'facecolor':'none','lw':2,'ls':'-.','edgecolor':'k'})ax.set_xlabel('批次',fontdict={'color':'k',               'backgroundcolor':'tab:blue','rotation':45})


二、刻度

刻度基本上绘制一幅图就要手动设置,因为matplotlib默认的刻度样式是比较丑的,我们的美化教程从刻度的生成开始。

首先介绍刻度默认的生成位置,由于大部分人的读图习惯,横纵轴的刻度一般是默认左-下分布,即横轴刻度在下,纵轴刻度在左。不过,某些时刻,我们一定要修改其位置,怎么做呢?有两个简单的办法:

ax.xaxis.tick_top( )#或者ax.xaxis.set_ticks_position('top')

下面这张图以不同方式修改了刻度显示的位置:

ax1.xaxis.tick_top()ax2.xaxis.set_ticks_position('top')ax3.yaxis.set_ticks_position('right')

接下来又有问题了,如果我想四边都要显示刻度怎么办呢?也有一个简单的命令:

ax1.tick_params(top=True,bottom=True,left=True,right=True)


那么,如何使刻度不显示呢?在设置刻度命令时传入空列表即可:

ax.set_xticks([ ])ax.set_yticks([ ])

这样就使四个边都显示出了刻度。接下来,我们学习修改刻度的样式。就比方说上面这个ax1,很明显,无论是刻度的长度宽度还是刻度标签都偏大、偏粗。matplotlib里有一个常用的调节刻度样式的命令——ax.tick_params( )。下面简要列举了一些常用参数:

axis
指定要修改的轴,如'x','y','both'


which
要修改的主副刻度,如'major''minor''both'
direction
刻度的小齿的方向,如'in''out'


length
刻度小齿的长度
width
刻度小齿的宽度
color
刻度小齿的颜色
pad
刻度标签与刻度小齿的距离
labelsize
刻度标签字体的大小
labelcolor
刻度标签字体的颜色
rotation 旋转刻度标签

我们通过一个简单的图片来操作这个命令:

ax.tick_params(axis='x',which='major',direction='in',               width=2,color='tab:orange',labelcolor='tab:blue',labelsize=5)ax.tick_params(axis='y',which='major',direction='in',               width=0.5,length=2,labelsize=5,pad=20,rotation=45)


学习完了修改刻度的样式,接下来就是非常实用的刻度值的修改了。刻度值关系到我们绘制出来的成品的效果,一图抵千言的前提是你的图片的质量合格,突显了你需要讲明的内容,而忽略一些在当前语境下不重要的内容。比如,一张连续性的,整体值偏大的数据:

上面这张的刻度值是系统随机生成的,下面这张是经过修饰的,哪一张更能抓住要点、捕获眼球呢?毫无疑问第二张图胜出了,固然其不能展示从0-2000的形势,但我们的分析本来也不需要从0开始。另外我们需要集中展示某一个区间或特定值的样式,默认的刻度也不能完成我们的需求,显然也要另加命令以做调整。

首先,是限制刻度值范围:

ax.set_xlim(10,20)#横轴只会显示10-20范围ax.set_ylim(100,500)#纵轴只会显示100-500范围

一般来说,刻度值都是从小到大的,我们还可以颠倒其走向:

ax.set_xlim(20,10)#横轴从20开始走到10ax.invert_xaxis( )#也是颠倒方向,但是不能限定范围

某些时候,我们需要让刻度显示的比较特殊,这个时候可以通过改设刻度命令实现,这时仅会显示出我们设定的刻度:

ax.set_xticks([0.1,0.2,0.3,0.55])


在某些时候,我们不需要数值,而是数值对应的某个表征量,如分数在90-100是优秀,累计降雨量在250毫米以上是特大暴雨。这个时候不再需要理性的数字,而是感性的描述性文字,通过如下命令,即可完成替换,替换的内容可以是各种形式的。但是请注意,pandas等是支持时间格式的,时间格式可以直接标注在坐标上,所以不要使用x=range(1,20),然后再用下面的命令改为时间格式的笨办法:

ax.set_yticks([0.1,0.2,0.55,0.9])ax.set_yticklabels(['一般般','挺不错','映象深刻','非常好'])

除了ax.tick_params( )语句外,在axisartist下生成的子图,还可以用ax.axis[  ]语句改变刻度的样式(常用的fig.add_axes(),subplot()生成的子图无法使用)。

ax.axis['left'].set_axis_direction('right')#使纵坐标放在右边ax.axis['bottom'].set_axis_direction('top')#使横坐标放在上边ax.axis[:].major_ticks.set_tick_out(True)#使刻度向外ax.axis['left'].label.set_text('纵轴标签名')ax.axis['left'].label.set_pad(0)#调节标签与轴的距离

最后,进入关键的刻度格式环节,这个环节是颇为重要的,可以省去很多力气。刻度格式生成器和刻度样式生成器是两个非常重要的模块。当然,其最强大的样式生成部分,我们多数时候只能用到经纬度标签这种,其实的比如金融、数学、物理等部分我们很少使用,也不多介绍。

在matplotlib的ticker模块中,提供了专门的刻度格式化命令。首先导入库包:

import matplotlib.ticker as mticker

首先使用刻度格式生成器,这个命令需要调用ax.xaxis.set。

一。无刻度格式(Nulllocator)

顾名思义,这个会使轴上面没有刻度显示。

ax.yaxis.set_major_locator(mticker.NullLocator())


二。等距刻度命令(MultipleLocator)

在这个命令下,刻度将会等距均匀分布。

ax.yaxis.set_major_locator(mticker.MultipleLocator(0.25))


三。抑制刻度数量命令(MaxNLocator)

在这个命令下,轴上的刻度将被限制在你设定的数量之下,剩下的刻度将会均匀分布。

ax.xaxis.set_major_locator(mticker.MaxNLocator(5))ax.yaxis.set_major_locator(mticker.MaxNLocator(2))


横轴除开零刻度只有五个刻度,纵轴除开0刻度只有两个。

4.均匀刻度命令(LinearLocator)

该命令使刻度按划分数量均匀显示。

ax.yaxis.set_major_locator(mticker.LinearLocator(10))


5.刻度固定(FixedLocator)

在该命令下,只会显示固定的刻度,即你指定要显示哪些刻度,其余的不显示。

ax.yaxis.set_major_locator(mticker.FixedLocator(np.arange(0,0.71,0.1)))ax.yaxis.set_major_locator(mticker.FixedLocator([0,0.1,0.2,0.3,0.4,0.5,0.6,0.7]))


然后,进入到实用的刻度样式环节。前面已经说过,经纬度是我们最常用的刻度样式,目前在绘制地图时,有两种常用的方法——一种是通过魔改matplotlib实现,一种是通过cartopy里的gridlines实现。

先讲魔改matplotlib的,这种实际上就是将子图坐标样式修改为经纬度,这种以后还可以用ax.tick_params( )来修改刻度的艺术样式。

import matplotlib.pyplot as pltimport numpy as npimport matplotlib.ticker as mtickerimport cartopy.crs as ccrsimport cartopy.io.shapereader as shpreaderfrom cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTERfrom cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatterplt.rcParams['font.sans-serif']=['SimHei']#中文extent=[108.3,109.35,29.7,30.7]reader = shpreader.Reader(r'E:\家园\利川市地图\利川.shp')fig=plt.figure(figsize=(4.5,2),dpi=700)#######添加两个子图###################ax1=fig.add_axes([0,0,0.5,1],projection=ccrs.PlateCarree())ax2=fig.add_axes([0.55,0,0.5,1],projection=ccrs.PlateCarree())######子图1的修饰##########################ax1.add_geometries(reader.geometries(),crs=ccrs.PlateCarree(),lw=0.5,edgecolor='k')ax1.set_extent(extent)ax1.set_xticks([108.5,108.73,108.94,109.15,109.349])ax1.set_yticks(np.arange(extent[2], extent[3]+0.2, 0.2))ax1.xaxis.set_major_formatter(LongitudeFormatter())ax1.yaxis.set_major_formatter(LatitudeFormatter())ax1.tick_params(axis='both',labelsize=5,direction='in')ax1.grid(linewidth=0.6, color='k', alpha=0.45, linestyle='--')ax1.set_title('通过魔改matplotlib的方式')######子图2的修饰##########################ax2.add_geometries(reader.geometries(),crs=ccrs.PlateCarree(),lw=0.5,edgecolor='k')ax2.set_extent(extent)gl = ax2.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,linewidth=0.6, color='k', alpha=0.45, linestyle='--')gl.xlabels_top = False gl.ylabels_left = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlocator = mticker.FixedLocator([108.3,108.5,108.73,108.94,109.15,109.349,109.5])gl.ylocator = mticker.FixedLocator(np.arange(extent[2], extent[3]+0.2, 0.2))gl.xlabel_style={'size':5}#修改经纬度字体大小gl.ylabel_style={'size':5}ax2.set_title('通过gridlines方式')plt.show()

gridlines方式设置比较简便,但是目前我好像没发现他能调出小刻度齿,经纬度线直接连接到边框。魔改matplotlib方式基于axis方式,只要能掌握前面提到的那些命令,修饰语句更多,还有经纬度的小刻度齿。常规使用我推荐gridlines语句,如果还需要修饰美化,就推荐魔改方式。

当然,这里都只是涉及到PlateCarree投影方式。目前0.17版本的cartopy是没办法在其他投影中使用gridlines来绘制经纬度标签的。

三、边框(轴)

边框(轴)是子图中比较重要的一部分,下面简要介绍一些实用的边框操作。

A、边框的隐现

对普通的子图

ax.axis('off')#该命令使全部框线和刻度消失

对地图

ax.background_patch.set_visible(False) #使框线全部消失ax.outline_patch.set_visible(False)

对普通的子图,仅对某一边或几边去框线

ax.spines['top'].set_linewidth(0)#框线宽度为0,则在视觉效果上为无框线ax.spines['right'].set_color('None')#框线无颜色,在在视觉效果上为无框

对地图

ax1.outline_patch.set_visible(False)#关闭GeoAxes框线ax1.spines['left'].set_visible(True)#开启Axes框线ax1.spines['left'].set_linewidth(0)#框线宽度为0,则在视觉效果上为无框线

B、边框的粗细

参考上一节的关于边框粗细语句。

C、坐标轴仅显示一部分

ax.spines['top'].set_linewidth(0)ax.spines['right'].set_linewidth(0)ax.spines['left'].set_bounds(-10,10)ax.yaxis.set_major_locator(mticker.FixedLocator([-10,0,10]))ax.spines['bottom'].set_bounds(0,50)

D、使坐标轴和子图内容物有一定的距离

ax.spines['left'].set_position(('outward',10))ax.spines['bottom'].set_position(('outward',10))

E、使轴生成箭头

import matplotlib.pyplot as pltimport mpl_toolkits.axisartist as axisartistdef setup_axes(fig, rect):    ax = axisartist.Subplot(fig, rect)    fig.add_axes(ax)    ax.set_ylim(-0.1, 1.5)    ax.set_yticks([01])    ax.axis[:].set_visible(False)    ax.axis["x"] = ax.new_floating_axis(1, 0.5)    ax.axis["x"].set_axisline_style("->", size=1.5)    return axfig = plt.figure(figsize=(3, 2.5),dpi=200)fig.subplots_adjust(top=0.8)ax1 = setup_axes(fig, "111")ax1.axis["x"].set_axis_direction("left")plt.show()

四、在色标中运用刻度与轴的知识

色标是等值线填色图中最重要的一部分,很多时候需要进一步设置使图像美观,现在就这章内容进行联系讲解。

通过下面语句在色标内调用刻度命令:

cb=fig.colorbar(......)cb.ax.tick_params( )

这样就进入到上面提到的流程,只要在括号中修改参数即可。

import matplotlib as mplimport matplotlib.pyplot as pltimport matplotlib.ticker as mtickerimport numpy as npfig=plt.figure(figsize=(2,1),dpi=500)cmap=mpl.cm.viridisnorm=mpl.colors.Normalize(vmin=6.0,vmax=9)position=plt.axes([0.,0.,1,0.1])cb=fig.colorbar(mpl.cm.ScalarMappable(norm=norm,cmap=cmap),cax=position,                extend='both',shrink=0.4,label='label气温标题',orientation='horizontal')cb.ax.set_title('title气温标题',fontsize=11)cb.ax.tick_params(axis='both',which='major',direction='in',labelsize=7,length=7.4,width=0.5)plt.show()

如何设置色条外框的粗?通过下面这个语句修改:

cb=fig.colorbar(......)cb.outline.set_linewidth(0.1)

谢谢阅读!

欢迎关注云台书使公众号获取更多资讯


本文分享自微信公众号 - 气象学家(Meteorologist2019)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!