爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 7110|回复: 5

[经验总结] 添加子图的便利函数

[复制链接]

新浪微博达人勋

发表于 2022-1-13 11:47:04 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 灭火器 于 2022-1-13 11:47 编辑

Cartopy 中的地图,即 GeoAxes,因为 aspect_ratio 固定为 1,所以在 add_axes 后其实际形状位置会发生变化,导致不符预期(可见 Cartopy 系列:对入门教程的补充)。因此 GeoAxes 与普通的 Axes 放在一起排版时总是效果很差,以至于需要手动对齐。这里介绍一个自制的函数,功能是根据已有的一个(组)Axes 的位置,新建一个等高或等宽的 Axes。代码如下
  1. import numpy as np
  2. import matplotlib.transforms as mtransforms

  3. def add_equal_axes(ax, loc, pad, width):
  4.     '''
  5.     在原有的Axes旁新添一个等高或等宽的Axes并返回该对象.

  6.     Parameters
  7.     ----------
  8.     ax : Axes or array_like of Axes
  9.         原有的Axes,也可以为一组Axes构成的数组.

  10.     loc : {'left', 'right', 'bottom', 'top'}
  11.         新Axes相对于旧Axes的位置.

  12.     pad : float
  13.         新Axes与旧Axes的间距.

  14.     width: float
  15.         当loc='left'或'right'时,width表示新Axes的宽度.
  16.         当loc='bottom'或'top'时,width表示新Axes的高度.

  17.     Returns
  18.     -------
  19.     ax_new : Axes
  20.         新Axes对象.
  21.     '''
  22.     # 无论ax是单个还是一组Axes,获取ax的大小位置.
  23.     axes = np.atleast_1d(ax).ravel()
  24.     bbox = mtransforms.Bbox.union([ax.get_position() for ax in axes])

  25.     # 决定新Axes的大小位置.
  26.     if loc == 'left':
  27.         x0_new = bbox.x0 - pad - width
  28.         x1_new = x0_new + width
  29.         y0_new = bbox.y0
  30.         y1_new = bbox.y1
  31.     elif loc == 'right':
  32.         x0_new = bbox.x1 + pad
  33.         x1_new = x0_new + width
  34.         y0_new = bbox.y0
  35.         y1_new = bbox.y1
  36.     elif loc == 'bottom':
  37.         x0_new = bbox.x0
  38.         x1_new = bbox.x1
  39.         y0_new = bbox.y0 - pad - width
  40.         y1_new = y0_new + width
  41.     elif loc == 'top':
  42.         x0_new = bbox.x0
  43.         x1_new = bbox.x1
  44.         y0_new = bbox.y1 + pad
  45.         y1_new = y0_new + width

  46.     # 创建新Axes.
  47.     fig = axes[0].get_figure()
  48.     bbox_new = mtransforms.Bbox.from_extents(x0_new, y0_new, x1_new, y1_new)
  49.     ax_new = fig.add_axes(bbox_new)

  50.     return ax_new
复制代码
add_equal_axes 函数的常见的使用场景为:已有一个 ax,在这个 ax 的右边新建一个等高的 cax,以便于之后作为 colorbar 使用。ax 有好几个也能正确处理,ax 是地图也没有影响。有了这个函数,就不再需要反反复复调节 add_axes 里的参数了。
也许有人会说,灵活的组图可以通过 matplotlib.gridspec.GridSpec 类进行设置,但它对于 GeoAxes 的效果不是很好。并且 GridSpec 的思路是在最开始就规划好组图网格,而 add_equal_axes 的思路是像搭积木一样,需要什么子图就随时添加。下面是一个例子
  1. import matplotlib.pyplot as plt
  2. import cartopy.crs as ccrs

  3. def add_center_text(ax, num):
  4.     ax.text(
  5.         0.5, 0.5, num, fontsize='large', fontweight='bold', color='C3',
  6.         ha='center', va='center', transform=ax.transAxes
  7.     )

  8. fig = plt.figure()
  9. ax1 = fig.add_axes([0.1, 0.5, 0.4, 0.4], projection=ccrs.PlateCarree())
  10. ax1.set_global()
  11. ax1.stock_img()
  12. add_center_text(ax1, 1)

  13. ax2 = add_equal_axes(ax1, loc='right', pad=0.1, width=0.1)
  14. add_center_text(ax2, 2)
  15. ax3 = add_equal_axes([ax1, ax2], loc='bottom', pad=0.1, width=0.1)
  16. add_center_text(ax3, 3)
  17. ax4 = add_equal_axes(ax3, loc='bottom', pad=0.1, width=0.1)
  18. add_center_text(ax4, 4)
  19. ax5 = add_equal_axes([ax1, ax2, ax3, ax4], loc='right', pad=0.1, width=0.1)
  20. add_center_text(ax5, 5)

  21. plt.show()
复制代码
subplots.png
如果要把这个函数结合 plt.subplots 进行使用,建议先用 fig.subplots_adjust 调节已有组图的间隔。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2022-1-13 16:00:55 | 显示全部楼层
漂亮
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

发表于 2022-7-8 19:18:27 | 显示全部楼层
非常好,谢谢分享。
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2024-3-5 11:50:15 | 显示全部楼层
您好 麻烦问下 我画的图中D01和02的经纬度网格都没显示出来 麻烦问下是哪里有问题?
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2024-3-6 20:00:12 | 显示全部楼层
leyutianzi 发表于 2024-3-5 11:50
您好 麻烦问下 我画的图中D01和02的经纬度网格都没显示出来 麻烦问下是哪里有问题?

没代码不知道
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2024-7-4 21:15:15 | 显示全部楼层

密码修改失败请联系微信:mofangbao
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表