经纬度绘图_Python气象绘图教程(二十二)—mpl_toolkits.axes_grid1

本节提要:挑选了matplotlib.mpl_toolkits.axes_grid1部件中比较有意思的几个类和功能简单解决一点点绘图中的常见问题。



一、make_axes_locatable

首先我们先了解这个功能的位置,方便在后面的引用中使用,这个功能的具体定位和层级是这样的: mpl_toolkits.axes_grid1.axes_divider.make_axes_locatable,不过因为这个层级下只有这一个名是这样的,我们在引用时可以跳过中间:
from mpl_toolkits.axes_grid1 import make_axes_locatable
这个功能是干嘛的呢?请让我们先画一张混合着GeoAxes和Axes的图片来试试看:
import matplotlib.pyplot as pltimport cartopy.crs as ccrsimport cartopy.feature as cfpro=ccrs.PlateCarree()plt.figure(figsize=(2,2),dpi=500)ax1=plt.subplot(221,projection=proj)ax2=plt.subplot(222)ax1.add_feature(cf.OCEAN.with_scale('50m'))           ax1.add_feature(cf.COASTLINE.with_scale('50m'),lw=0.1)                 ax1.add_feature(cf.LAND.with_scale('50m'),edgecolor='none')                                                        ax1.add_feature(cf.RIVERS.with_scale('110m'),lw=0.1) ax1.spines['geo'].set_linewidth(0.3)x=[1,2,3,4,5,6,7,8,9,10]y=[10,2,19,4,8,9,2,11,14,15]ax2.plot(x,y,lw=0.5)ax2.set(xlim=(0,10),ylim=(0,20))ax2.tick_params(axis='both',direction='in',labelsize=3,length=1,width=0.3,left=True,right=True,top=True,pad=0.6)ax2.yaxis.tick_right()ax2.set_yticks([0,5,10,15,20])for i in ['left','right','top','bottom']:    ax2.spines[i].set_linewidth(0.3)plt.show()

经纬度绘图_Python气象绘图教程(二十二)—mpl_toolkits.axes_grid1_第1张图片

很明显,两张图一大一小很麻烦。这是subplot方式创建的同样子图,如果你再使用fig.add_axes方式强制指定长宽大小相同,也会遇到添加地图后变得大小不一的情况,这是因为地图的长宽比在转换投影时,会修改其长宽比,从而在视觉上引起大小不一。而手动调节图的大小和位置也很繁琐。这里就可以引入今天的第一个功能了。
import matplotlib.pyplot as pltimport cartopy.crs as ccrsimport cartopy.feature as cffrom mpl_toolkits.axes_grid1 import make_axes_locatablefrom cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatterplt.rcParams['font.sans-serif']=['Times New Roman']################################################################fig=plt.figure(figsize=(2,2),dpi=600)ax1=fig.add_axes([0,0.5,1,0.5],projection=ccrs.PlateCarree())ax1.add_feature(cf.LAND.with_scale('50m'),lw=0.1)ax1.add_feature(cf.COASTLINE.with_scale('50m'),lw=0.1)ax1.add_feature(cf.OCEAN.with_scale('50m'),edgecolor='none')ax1.add_feature(cf.RIVERS.with_scale('110m'),lw=0.1)ax1.set_xticks([-180,-150,-120,-90,-60,-30,0,30,60,90,120,150,180])#指定要显示的经纬度                      ax1.set_yticks([-90,-60,-30,0,30,60,90])                  ax1.xaxis.set_major_formatter(LongitudeFormatter())#刻度格式转换为经纬度样式                       ax1.yaxis.set_major_formatter(LatitudeFormatter())                        ax1.tick_params(axis='both',which='major',labelsize=1.7,direction='in',length=1,width=0.2,pad=0.6,top=True,right=True)ax1.grid(linewidth=0.15, color='k', alpha=0.7, linestyle='--')ax1.spines['geo'].set_linewidth(0.3)################################################################divider=make_axes_locatable(ax1)ax2=divider.new_horizontal(size='100%',                          pad=0.2,                          axes_class=plt.Axes)fig.add_axes(ax2)#################################################################x=[1,2,3,4,5,6,7,8,9,10]y=[10,2,19,4,8,9,2,11,14,15]ax2.plot(x,y,lw=0.5)ax2.set(xlim=(0,10),ylim=(0,20))ax2.tick_params(axis='both',direction='in',labelsize=3,length=1,width=0.3,left=True,right=True,top=True,pad=0.6)ax2.yaxis.tick_right()ax2.set_yticks([0,5,10,15,20])ax2.spines['left'].set_linewidth(0.3)ax2.spines['right'].set_linewidth(0.3)ax2.spines['top'].set_linewidth(0.3)ax2.spines['bottom'].set_linewidth(0.3)ax1.set_title('GeoAxes',fontsize=4,pad=0.5)ax2.set_title('Axes',fontsize=4,pad=0.5)

经纬度绘图_Python气象绘图教程(二十二)—mpl_toolkits.axes_grid1_第2张图片

在中间井号注释中间,就是这个功能的核心语句。基本上按照原理拷贝到你的程序中即可使用。 new_horizontal功能表示复制的子图和原本的子图是平行关系;size表示两个图的相对大小,100%表示两个图大小完全一样;pad表示两个子图的间距;axes_class指定复制的子图的类型,这里指定的是通常的axes。 使用另一个命令,即可形成垂直方向的相同样式的图片。
divider=make_axes_locatable(ax1)ax2=divider.new_vertical(size='100%',                          pad=0.15,                          pack_start=True,                          axes_class=plt.Axes)fig.add_axes(ax2)

经纬度绘图_Python气象绘图教程(二十二)—mpl_toolkits.axes_grid1_第3张图片

pack_start参数表示新建的子图是否在原图的下面(或右边)。这个参数在水平和竖直功能都可用。可以自行测试。 二、InsetPosition
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
本篇的第二个功能就是这个嵌入功能。该功能可以使两个子图之间的位置和大小强制固定。在前面介绍添加南海小地图时,我们使用的方式是直接添加子图,然后通过微调参数的方式将南海小地图挪动到合适的位置。但是一旦主图的参数变动,必须修改小图的参数,否则就会导致错位。而且四个南海小地图全部是以b变量的方式返回的,不能再南海小地图上绘制数据。本节的这个方法可以强制指定位置和相对大小,改变主图参数,连锁子图自动适配主图。
'''这个是模仿中科院的一篇论文中的图,在前面我们已经简单介绍了南海小地图的封装,   但那个小地图没办法绘图的,这个封装可以在八幅子图中都绘制数据,当然,这只是我混合各种方法的一个示例,   实际上可能没有用处,大家理解其原理即可自行发挥'''import matplotlib.pyplot as pltimport matplotlib.path as mpathfrom mpl_toolkits.axes_grid1.inset_locator import InsetPositionfrom cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatterimport cartopy.crs as ccrsimport cartopy.feature as cfplt.rcParams['font.sans-serif']=['Times New Roman']proj=ccrs.PlateCarree()proj2=ccrs.LambertConformal(central_longitude=105,central_latitude=35)fig=plt.figure(figsize=(2,2),dpi=500)def create_map(ax):#主图矩形投影的函数封装    ax.add_feature(cf.LAND.with_scale('50m'),lw=0.1)    ax.add_feature(cf.COASTLINE.with_scale('50m'),lw=0.1)    ax.add_feature(cf.OCEAN.with_scale('50m'),edgecolor='none')    ax.add_feature(cf.RIVERS.with_scale('110m'),lw=0.1)    ax.set_extent([70,140,10,70],crs=proj)    ax.set_xticks([70,80,90,100,110,120,130,140])#指定要显示的经纬度                          ax.set_yticks([10,20,30,40,50,60,70])                      ax.xaxis.set_major_formatter(LongitudeFormatter())#刻度格式转换为经纬度样式                           ax.yaxis.set_major_formatter(LatitudeFormatter())                            ax.tick_params(axis='both',which='major',labelsize=1.7,direction='in',length=1,width=0.2,pad=0.6,top=True,right=True)    ax.spines['geo'].set_linewidth(0.3)    return axdef cut_map_boundary_and_set(ax,bx):#副图兰勃脱投影下的边界裁剪嵌入子图封装    extent=[70,140,10,60]    latmin,latmax,lonmin,lonmax=[0,70,40,160]                                                              vertices=[(lon, latmin) for lon in range(lonmin, lonmax + 1, 1)]+[(lon, latmax) for lon in range(lonmax, lonmin - 1, -1)]         boundary=mpath.Path(vertices)                                                                                                                      bx.add_feature(cf.OCEAN.with_scale('50m'))               bx.add_feature(cf.COASTLINE.with_scale('50m'),lw=0.1)                     bx.add_feature(cf.LAND.with_scale('50m'),edgecolor='none')                                                            bx.add_feature(cf.RIVERS.with_scale('110m'),lw=0.1)                                                            bx.set_boundary(boundary, transform=ccrs.PlateCarree())                      bx.set_extent(extent)                                                                                           bx.spines['geo'].set_linewidth(0.3)    ip=InsetPosition(ax,[-0.12,0.8,0.4,0.4])    bx.set_axes_locator(ip)    return ax,bxax1=plt.subplot(221,projection=proj)ax2=plt.subplot(222,projection=proj)ax3=plt.subplot(223,projection=proj)ax4=plt.subplot(224,projection=proj)bx1=fig.add_axes([0.1,0,1,1],projection=proj2)#其具体大小不重要,最后都将被InsetPosition强制同步bx2=fig.add_axes([0.2,0,1,1],projection=proj2)bx3=fig.add_axes([0.3,0,1,1],projection=proj2)bx4=fig.add_axes([0.4,0,1,1],projection=proj2)for i in [ax1,ax2,ax3,ax4]:    create_map(i)for i,s in zip([ax1,ax2,ax3,ax4],[bx1,bx2,bx3,bx4]):    cut_map_boundary_and_set(i,s)plt.show()

经纬度绘图_Python气象绘图教程(二十二)—mpl_toolkits.axes_grid1_第4张图片

第一个封装函数是对主图的修饰。第二个封装函数是对小地图的修饰,裁剪地图边界形状并将其与主图的相对位置固定。
    ip=InsetPosition(ax,[-0.12,0.8,0.4,0.4])    bx.set_axes_locator(ip)
其中,ax是主图,列表四个元素,第一个为副图相对主图的起始横坐标,第二个为纵坐标,第三个为副图相对主图的长度比,第四个为副图相对主图的宽度比。 这种情况下八个子图都可以分别绘制数据,且副图随主图的形状参数变化而变化。 三、Inset_axes
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
这个功能也是在当前主子图上嵌入一个子图。除了可以实现小节2中的功能外,还有类似DataCharm公众号上的在当前子图外添加部分构件的功能。另外,使用了axis('off')的命令后,还可以实现主图和子图互相重叠,但是不会遮挡最下面的图片。与ax.patch.set_visible(False)有类似的功效。 四、mark_inset 这个功能在前面的文章中已经介绍过了,这里只简单归类。
from mpl_toolkits.axes_grid1.inset_locator import mark_insetmark_inset(ax1,ax2,loc1=1,loc2=3,alpha=0.5,fc='none',ec='r',ls='-.')

经纬度绘图_Python气象绘图教程(二十二)—mpl_toolkits.axes_grid1_第5张图片

其中,ax1,ax2代表需要产生连接的子图,loc1,loc2表示需要产生连线的结点,fc即facecolor,ec表示 edgecolor,其他参数与线状参数类似。除了地图之间的链接,普通子图之间也可以进行链接。 五、zoomed_inset_axes 缩放主轴,并将生成的新轴嵌入主图。这个功能很少用到,我目前读的东西好像从来没有遇见过这个。具体用法可以参考官网实例。 这次只是简单的介绍了工具箱里面为数不多的几种,下次可以看看寄生轴之类的。最实用的还是强制长宽比和批量嵌入两个功能。 谢谢阅读 欢迎关注云台书使公众号获取更多资讯

经纬度绘图_Python气象绘图教程(二十二)—mpl_toolkits.axes_grid1_第6张图片

你可能感兴趣的:(经纬度绘图)