python绘制多图/子图的框架代码

很多时候画组图还是很方便的,这里整理框架性的命令。

这里引用一些我画图常用的包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import xarray as xr
import numpy as np
from netCDF4 import Dataset
import netCDF4 as nc
from wrf import getvar,disable_xarray,ALL_TIMES
from datetime import datetime, timedelta
import wrf
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy.ma as ma
import matplotlib
from global_land_mask import globe
# from cartopy.util import add_cyclic_point
from cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatter
from cartopy.mpl.gridliner import LATITUDE_FORMATTER, LONGITUDE_FORMATTER
from matplotlib.pyplot import MultipleLocator
import nclcmaps

plt.rcParams['font.sans-serif']=['Times New Roman']
matplotlib.rcParams.update({'font.size': 8})

然后读取我们需要绘图的数据,以及坐标信息,比如经纬度等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
## 前期准备,设置好地图投影的信息
ref_lat = 32
ref_lon = 98
true_lat1 = 30
true_lat2 = 60
false_easting = (180-1)/2*30000
false_northing = (99.5-1)/2*30000

proj_lambert = ccrs.LambertConformal(
central_longitude=ref_lon,
central_latitude=ref_lat,
standard_parallels=(true_lat1,true_lat2),
cutoff=-30,
false_easting=false_easting,
false_northing=false_northing,
)
## 提前将每个子图中都有的背景设置定义为一个函数(对ax进行操作),就不必复制代码了
def ax_set(ax):
ax.set_extent([0, false_easting*2, 0, false_northing*2], crs=proj_lambert)
ax.coastlines(linewidth=0.8,resolution='50m',zorder=101)
ax.add_feature(cfeature.LAKES.with_scale('50m'),linewidth=0.5,edgecolor='black',facecolor='none')
# ax.add_feature(cfeature.OCEAN,facecolor='w',linewidth=0,zorder=100)

filepath =disk+':\LHwork\shpfile\中国GIS地图\国家基础地理数据/hyd1_4l.shp'
crs = ccrs.PlateCarree()
reader = shpreader.Reader(filepath)
geoms = reader.geometries()
ax.add_geometries(geoms, crs, lw=0.5, fc='none')
reader.close()

## --设置网格属性, 不画默认的标签
gl=ax.gridlines(draw_labels=True,linestyle=":",linewidth=0.6 ,x_inline=False, y_inline=False,color='k',zorder=102)

## 关闭上面和右边的经纬度显示
gl.top_labels=False #关闭上部经纬标签
# gl.bottom_labels = False
# gl.left_labels = False
import matplotlib.ticker as mticker
gl.right_labels=False
gl.xformatter = LONGITUDE_FORMATTER #使横坐标转化为经纬度格式
gl.yformatter = LATITUDE_FORMATTER


gl.xlocator=mticker.FixedLocator(np.arange(60,160,10))
gl.ylocator=mticker.FixedLocator(np.arange(10,60,10))
gl.rotate_labels = False
gl.xlabel_style={'size':8,}
# 'rotation':'horizontal','rotation_mode':'default',
# 'horizontalalignment':'center','verticalalignment':'center'}#修改经纬度字体大小
gl.ylabel_style={'size':8,}#'rotation':'horizontal'}
ax.spines['geo'].set_linewidth(0.6)#调节边框粗细

plt.plot([110,122], [28,28], 'r--',linewidth=1,transform=ccrs.PlateCarree(),zorder=105)
plt.plot([110,122], [32,32], 'r--',linewidth=1,transform=ccrs.PlateCarree(),zorder=105)
plt.plot([110,110], [28,32], 'r--',linewidth=1,transform=ccrs.PlateCarree(),zorder=105)
plt.plot([122,122], [28,32], 'r--',linewidth=1,transform=ccrs.PlateCarree(),zorder=105)

下面开始设置大图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 设置大图
fig = plt.figure(figsize=[8, 8])# 设置width, height
fig.subplots_adjust(wspace=0.1,hspace=0.25)
'''
fig.subplots_adjust(left=None, bottom=None, right=None,
top=None, wspace=None, hspace=None)
函数的参数如下:
left:所有子图整体相对于图像的左外边距,距离单位为图像宽度的比例(小数)。
可选参数。浮点数。默认值为0.125。
right:所有子图整体相对于图像的右外边距,距离单位为图像宽度的比例(小数)。
可选参数。浮点数。默认值为0.0。
bottom:所有子图整体相对于图像的下外边距,距离单位为图像高度的比例(小数)。
可选参数。浮点数。默认值为0.11。
top:所有子图整体相对于图像的上外边距,距离单位为图像高度的比例(小数)。
可选参数。浮点数。默认值为0.88。
wspace:子图间宽度内边距,距离单位为子图平均宽度的比例(小数)。
浮点数。默认值为0.2。
hspace:子图间高度内边距,距离单位为子图平均高度的比例(小数)。
可选参数。浮点数。默认值为0.2。
'''
for i in range(4):
ax = fig.add_subplot(2, 2, i+1,projection=proj_lambert)
ax.text(0.001, 1.05, '('+alphabat[i]+')',transform=ax.transAxes,fontsize=10)#, va='bottom', ha='right')
ax_set(ax) # 把一些相同的基础设置打包
cs = ax.contourf(lon,lat, data[i,:],
levels=levels,cmap=nclcmaps.cmap('MPL_BrBG'),
transform=ccrs.PlateCarree(),
extend='both')
### 设置colorbar
cax = fig.add_axes([0.1,0.13,0.7,0.03])
bar = plt.colorbar(cs,cax = cax,orientation='horizontal',
ticks=v,drawedges=False)

bar.ax.tick_params(labelcolor='k',labelsize=8,pad=0.5)
bar.outline.set_linewidth(0.3)
bar.ax.set_xticklabels(v,fontsize=10,fontname="Times New Roman")
fig.text(0.8,0.118,r"$(\times 10^{-%d}m^3/m^3)$"%scale,fontsize=10) # sm


plt.savefig(work_dir+'111.png',dpi=800, bbox_inches='tight')