python 绘图基础--如何绘制多个的子图 and 封装绘图函数(提高绘图效率)

简介: 一般来说,我们研究分析一些海温或者降水等要素的的变化规律时,通常会进行季节特征变化分析,这就需要我们绘制不同季节的空间分布图来进行分析,这就需要我们掌握子图的绘制方法。

一般来说,我们研究分析一些海温或者降水等要素的的变化规律时,通常会进行季节特征变化分析,这就需要我们绘制不同季节的空间分布图来进行分析,这就需要我们掌握子图的绘制方法。


一般这种我们可以通过设置不同的ax进行绘制,简单介绍在这篇博客中:进阶绘图–axes

  • 通过对于每个子图的不同命令,可以绘制填色图、折线图等等,这种方法的不好的地方在于需要多次重复一些语句设置,比如地形、坐标、标签等等,当然,如果不怕麻烦也可以忽略。
  • 对于不同的子图,只需要对于不同的ax进行不同的绘图即可,同时对于不同的子图属性设置也要对应不同的ax序号,如果你第一个字图的ax是ax1,那么所有关于这个子图的命令语句,都要以ax1开头。
  • 下面给出一个通过ax命令海温的季节空间分布图绘制的例子:


ax绘制不同子图



# -*- coding: utf-8 -*-
"""
Created on Thu Aug 12 22:20:52 2021
@author: 纪
"""
## 导入库
import cartopy.feature as cfeature
from cartopy.util import add_cyclic_point
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
import xarray as xr
## 路径
path='D:\\sst.nc'
### =================================================================
# 准备数据、选择区域、求季节平均
###==================================================================
sst=xr.open_dataset(path)
lon=sst.lon
lat=sst.lat
lat_range = lat[(lat>-22.5) & (lat<22.5)]
sst_region =sst.sel(lat=lat_range,lon=lon)
season =sst_region.groupby(
    'time.season').mean('time', skipna=True)
#=====================draw==============================================
fig=plt.figure(figsize=(20,12))#设置一个画板,将其返还给fig
###=================设置全局字体、字体大小==============================
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['font.size'] = 15
###=========================绘制第一个子图=================================
ax = fig.add_subplot(4, 1, 1, projection=ccrs.PlateCarree(central_longitude =180))
### 添加地形,并且设置陆地为白色遮盖
ax.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '50m', \
                             edgecolor='white',facecolor='white',zorder=2))
### 添加循环,为了避免经线180°出现白色竖线                         
cycle_sst, cycle_lon = add_cyclic_point(season.sst[1], coord=lon)
cycle_LON, cycle_LAT = np.meshgrid(cycle_lon, lat_range)
### 绘制填色图   
cb=ax.contourf(cycle_LON,cycle_LAT, cycle_sst,levels=np.arange(20,36),cmap='bwr',\
   zorder=0,transform= ccrs.PlateCarree())
### 设置横纵坐标的范围  
ax.set_xticks(np.arange(0, 361, 30),crs=ccrs.PlateCarree())
ax.set_yticks(np.arange(-20, 40, 20),crs=ccrs.PlateCarree())
ax.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label =False))#经度0不加标识
ax.yaxis.set_major_formatter(LatitudeFormatter())
### 绘制等值线
contour = ax.contour(lon,lat_range, season.sst[1],colors='k',zorder=1,transform= ccrs.PlateCarree())
#zorder 显示图层叠加顺序
### 设置坐标轴的轴长、宽、离轴的距离、
ax.tick_params(which='major', direction='out', length=10, width=0.99, pad=0.2, bottom=True, left=True, right=False, top=False)
### 设置子图的标题
ax.set_title('JJA-SST horizontal distribution')
### 设置子图的colorbar
cbar = fig.colorbar(cb,shrink=0.7,ticks=[20,25,30],pad=0.04,aspect=3.5)
###=========================绘制第2个子图=================================
ax1 = fig.add_subplot(4, 1, 2, projection=ccrs.PlateCarree(central_longitude=180))#中心线为180°
ax1.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '110m', \
                                            edgecolor='black', facecolor='white'))
cycle_sst1, cycle_lon = add_cyclic_point(season.sst[2], coord=lon)
cb=ax1.contourf(cycle_LON,cycle_LAT, cycle_sst1,levels=np.arange(20,34),cmap='bwr',\
    zorder=0,transform= ccrs.PlateCarree() )
contour = plt.contour(cycle_LON,cycle_LAT, cycle_sst1,colors='k',zorder=1,transform= ccrs.PlateCarree())
ax1.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '50m', \
                                           edgecolor='white', facecolor='white',zorder=2))
ax1.tick_params(which='major', direction='out', length=10, width=0.99, pad=0.2, bottom=True, left=True, right=False, top=False)
ax1.set_xticks(np.arange(0, 361, 30),crs=ccrs.PlateCarree())
ax1.set_yticks(np.arange(-20, 40, 20),crs=ccrs.PlateCarree())
ax1.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label =False))#经度0不加标识
ax1.yaxis.set_major_formatter(LatitudeFormatter())
ax1.set_title('MAM-SST horizontal distribution')
cbar = fig.colorbar(cb,shrink=0.7,ticks=[20,25,30],pad=0.04,aspect=3.5)
###=========================绘制第3个子图=================================
ax2= fig.add_subplot(4, 1, 3, projection=ccrs.PlateCarree(central_longitude=180))#中心线
ax2.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '110m', \
                                            edgecolor='black', facecolor='white'))
cycle_sst2, cycle_lon = add_cyclic_point(season.sst[3], coord=lon)
cb=ax2.contourf(cycle_LON,cycle_LAT, cycle_sst2,levels=np.arange(20,34),cmap='bwr',\
   zorder=0,transform= ccrs.PlateCarree()  )
contour = plt.contour(cycle_LON,cycle_LAT, cycle_sst2,colors='k',zorder=1,transform= ccrs.PlateCarree())
ax2.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '50m', \
 edgecolor='white', facecolor='white',zorder=2))
ax2.tick_params(which='major', direction='out', length=10, width=0.99, pad=0.2, bottom=True, left=True, right=False, top=False)
ax2.set_xticks(np.arange(0, 361, 30),crs=ccrs.PlateCarree())
ax2.set_yticks(np.arange(-20, 40, 20),crs=ccrs.PlateCarree())
ax2.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label =False))#经度0不加标识
ax2.yaxis.set_major_formatter(LatitudeFormatter())
ax2.set_title('SON-SST horizontal distribution')
cbar = fig.colorbar(cb,shrink=0.7,ticks=[20,25,30],pad=0.04,aspect=3.5)
###=========================绘制第4个子图=================================
ax3= fig.add_subplot(4, 1, 4, projection=ccrs.PlateCarree(central_longitude=180))#中心线
ax3.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '110m', \
                                            edgecolor='black', facecolor='white'))
cycle_sst3, cycle_lon = add_cyclic_point(season.sst[0], coord=lon)
cb=ax3.contourf(cycle_LON,cycle_LAT, cycle_sst3,levels=np.arange(20,34),cmap='bwr',\
    zorder=0,transform= ccrs.PlateCarree() )
contour = plt.contour(cycle_LON,cycle_LAT, cycle_sst3,colors='k',zorder=1,transform= ccrs.PlateCarree())
ax3.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '50m', \
                                            edgecolor='white', facecolor='white',zorder=2))
ax3.tick_params(which='major', direction='out', length=10, width=0.99, pad=0.2, bottom=True, left=True, right=False, top=False)
ax3.set_xticks(np.arange(0, 361, 30),crs=ccrs.PlateCarree())
ax3.set_yticks(np.arange(-20, 40, 20),crs=ccrs.PlateCarree())
ax3.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label =False))#经度0不加标识
ax3.yaxis.set_major_formatter(LatitudeFormatter())
ax3.set_title('DJF-SST horizontal distribution')
cbar = fig.colorbar(cb,shrink=0.7,ticks=[20,25,30],pad=0.04,aspect=3.5)
### 保存图片到指定路径
#fig.savefig('D:\\desktopppp\\picture\\'+'SST_horizontal_distribution.tiff',format='tiff',dpi=150)


绘图结果如下,海温的四个季节的空间水平分布:


8c5d886b5e0c425b8095d2edcb658edf.png


通过绘图函数封装绘制不同子图



其实,通过上面的代码,我们可以发现,有部分代码完全是重复设置的,非常的麻烦,所以我们完全可以设置一个绘图函数,减少我们的代码量。

下面给出一个使用代码封装后的绘图例子,可以前后对比一下:


"""
Created on Thu Nov  4 19:47:58 2021
@author: (ji)
E-mail : 211311040008@hhu.edu.cn
Introduction: keep learning
"""
import cartopy.feature as cfeature
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
import xarray as xr
path2='D:\\sst.nc'
ds=xr.open_dataset(path2).sortby("lat", ascending= True)
sst=ds.sel(lat=slice(-20,20),time=slice('2010','2010'))
season =sst.groupby('time.season').mean('time', skipna=True)
def make_map(ax, title):
    # set_extent  set crs
    ax.set_extent(box, crs=ccrs.PlateCarree())
    land = cfeature.NaturalEarthFeature('physical',
                                        'land',
                                        scale,
                                        edgecolor='white', 
                                        facecolor='white',
                                        zorder=2)
    ax.add_feature(land)  # set land color
    ax.coastlines(scale)  # set coastline resolution
    # set coordinate axis
    ax.set_xticks(np.arange(0, 360+30, 30),crs=ccrs.PlateCarree())
    ax.set_yticks(np.arange(-20, 30, 10),crs=ccrs.PlateCarree())
    ax.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label =False))#经度0不加标识
    ax.yaxis.set_major_formatter(LatitudeFormatter())
    # plt.tick_params(labelsize=25)
    lon_formatter = LongitudeFormatter(zero_direction_label=False)  
    # zero_direction_label set 0 without E or W
    lat_formatter = LatitudeFormatter()
    ax.xaxis.set_major_formatter(lon_formatter)
    ax.yaxis.set_major_formatter(lat_formatter)
    ax.set_title(title, fontsize=25, loc='center')
    ax.tick_params(which='major', 
                    direction='out', 
                    length=8,
                    width=0.99, 
                    pad=0.2, 
                    labelsize=20,
                    bottom=True, left=True, right=False, top=False)
    return ax
# # prepare 
box = [0, 361, -20, 20]  
scale = '50m'            
xstep, ystep = 30, 5   
cmap=plt.get_cmap('bwr')#'RdYlBu_r'
levels=np.arange(20,34)
zorder=0
# name=['DJF-SST horizontal distribution','JJA-SST horizontal distribution',\
#       'MAM-SST horizontal distribution','SON-SST horizontal distribution']
sea=['JJA','MAM','SON','DJF']
#=================draw   picture   =================================
fig=plt.figure(figsize=(20,12))#设置一个画板,将其返还给fig
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['font.size'] = 15
proj=ccrs.PlateCarree(central_longitude=180)
count=0
for i in range(len(sea)):
    count+=1
    ax=fig.add_subplot(4,1,count,projection=proj)
    make_map(ax,sea[i]+'-SST horizontal distribution')
    plot=ax.contourf(sst.lon,sst.lat,season.sel(season=sea[i]).sst,cmap=cmap,levels=levels,\
                      zorder=0,transform=ccrs.PlateCarree())
    contour=ax.contour(sst.lon,sst.lat,season.sel(season=sea[i]).sst,colors='k',zorder=1,transform=ccrs.PlateCarree())
    # pcolor=ax.pcolormesh(sst.lon,sst.lat,season.sst[i],transform=ccrs.PlateCarree(),\
    #                  cmap='bwr', zorder=0)
    # fig.colorbar(pcolor,ax=ax,shrink=0.7,ticks=[20,25,30],pad=0.04,aspect=3.5)
    fig.colorbar(plot,ax=ax,shrink=0.7,ticks=[20,25,30],pad=0.04,aspect=3.5)
plt.show()
# fig.savefig('G:\\daily\\'+'SST_horizontal_distribution.tiff',format='tiff',dpi=150)


结果是一样的:


d70a0d326ffe4f59ad4193908eb9d2eb.png


可以明显的发现,代码更简洁了,也可以将这个封装函数进行保存,以后直接导入这个函数,大大节省我们绘图时间!!!

有兴趣的小伙伴们可以尝试一下~


测试数据有点大,不方面传在这里,有需要的找我要


         

                            一个努力学习python的海洋
                            水平有限,欢迎指正!!!
                            欢迎评论、收藏、点赞、转发、关注。
                            关注我不后悔,记录学习进步的过程~~                  


相关文章
|
2月前
|
搜索推荐 Python
利用Python内置函数实现的冒泡排序算法
在上述代码中,`bubble_sort` 函数接受一个列表 `arr` 作为输入。通过两层循环,外层循环控制排序的轮数,内层循环用于比较相邻的元素并进行交换。如果前一个元素大于后一个元素,就将它们交换位置。
147 67
|
10天前
|
Python
[oeasy]python057_如何删除print函数_dunder_builtins_系统内建模块
本文介绍了如何删除Python中的`print`函数,并探讨了系统内建模块`__builtins__`的作用。主要内容包括: 1. **回忆上次内容**:上次提到使用下划线避免命名冲突。 2. **双下划线变量**:解释了双下划线(如`__name__`、`__doc__`、`__builtins__`)是系统定义的标识符,具有特殊含义。
21 3
|
14天前
|
JSON 监控 安全
深入理解 Python 的 eval() 函数与空全局字典 {}
`eval()` 函数在 Python 中能将字符串解析为代码并执行,但伴随安全风险,尤其在处理不受信任的输入时。传递空全局字典 {} 可限制其访问内置对象,但仍存隐患。建议通过限制函数和变量、使用沙箱环境、避免复杂表达式、验证输入等提高安全性。更推荐使用 `ast.literal_eval()`、自定义解析器或 JSON 解析等替代方案,以确保代码安全性和可靠性。
27 2
|
1月前
|
Python
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
54 18
|
1月前
|
数据可视化 DataX Python
Seaborn 教程-绘图函数
Seaborn 教程-绘图函数
69 8
|
1月前
|
Python
Python中的函数
Python中的函数
47 8
|
2月前
|
监控 测试技术 数据库
Python中的装饰器:解锁函数增强的魔法####
本文深入探讨了Python语言中一个既强大又灵活的特性——装饰器(Decorator),它以一种优雅的方式实现了函数功能的扩展与增强。不同于传统的代码复用机制,装饰器通过高阶函数的形式,为开发者提供了在不修改原函数源代码的前提下,动态添加新功能的能力。我们将从装饰器的基本概念入手,逐步解析其工作原理,并通过一系列实例展示如何利用装饰器进行日志记录、性能测试、事务处理等常见任务,最终揭示装饰器在提升代码可读性、维护性和功能性方面的独特价值。 ####
|
2月前
|
Python
Python中的`range`函数与负增长
在Python中,`range`函数用于生成整数序列,支持正向和负向增长。本文详细介绍了如何使用`range`生成负增长的整数序列,并提供了多个实际应用示例,如反向遍历列表、生成倒计时和计算递减等差数列的和。通过这些示例,读者可以更好地掌握`range`函数的使用方法。
64 5
|
2月前
|
测试技术 数据安全/隐私保护 Python
探索Python中的装饰器:简化和增强你的函数
【10月更文挑战第24天】在Python编程的海洋中,装饰器是那把可以令你的代码更简洁、更强大的魔法棒。它们不仅能够扩展函数的功能,还能保持代码的整洁性。本文将带你深入了解装饰器的概念、实现方式以及如何通过它们来提升你的代码质量。让我们一起揭开装饰器的神秘面纱,学习如何用它们来打造更加优雅和高效的代码。
|
2月前
|
中间件 Docker Python
【Azure Function】FTP上传了Python Function文件后,无法在门户页面加载函数的问题
通过FTP上传Python Function至Azure云后,出现函数列表无法加载的问题。经排查,发现是由于`requirements.txt`中的依赖包未被正确安装。解决方法为:在本地安装依赖包到`.python_packages/lib/site-packages`目录,再将该目录内容上传至云上的`wwwroot`目录,并重启应用。最终成功加载函数列表。

热门文章

最新文章