python绘图

环境配置与IDE配置

  • python环境安装可通过直接下载或者通过包管理器anaconda下载,这里更推荐使用anaconda可以搭建多个不同版本的python环境且彼此不受影响,两种方法下载后均会自动配置好环境变量,不需要下一步操作。后续介绍主要围绕anaconda+vscode的配置来介绍。
  • conda创建环境需要打开anaconda prompt来创建,常用的conda命令如下
    • conda env list 列出目前已有的环境
    • conda create -n env_name python=3.x.x 创建名称为env_name版本为3.x.x的python环境
    • conda activate env_name 进入env_name的环境 deactivate 退出环境
    • 在进入某一环境后可以通过conda install xxx来下载不同的包,原理与pip相同
  • IDE使用vscode,下载好后在任意一个目录下创建python文件后,在右下角选择已经创建好的conda环境即可

    常用包

  1. numpy 数据处理包,主要使用其中创建空数组或是对数组进行布尔逻辑索引等操作
  2. matplotlib python中绘图最主要的包
  3. xarray 可以读取.nc等带有表头格式的文件
  4. cartopy 主要进行地图绘制的包
  5. netCDF4 可以读取nc格式文件并将读取出来的文件转换为ndarray即numpy数组
  6. scipy 包含许多统计变量的计算函数
  7. h5py 读取HDF格式文件,读取后变为Dataset格式,通过提取变量变为ndarray
  8. shapefile 与shp文件相关的地图绘制

绘图基本流程与常用函数

以绘制GPM降水资料在甘肃的分布为例

  1. 读取数据
    import h5py
    file = 'path_to_GPM_file'
    Dataset = h5py.File(file)
    lon = Dataset['/Grid/lon'][:] #不同的二进制文件中变量关键词不同,变量组关系不同,可使用ncdump -h 先查看文件变量组在读取
    lat = Dataset['/Grid/lat'][:] #这里使用[:]是为了只将变量中的数据取出,而不包含变量的头信息等
    prec = Dataset['Grid/precipitationCal'][:]/2 #由于GPM是逐半小时的降雨率
    prec = prec[0,:,:].transpose() #由于GPM资料是time*lon*lat,需要转化为lat*lon再绘图
  2. 控制数据区域

由于GPM数据为全球范围,直接整体处理对内存与运行速度负载较大,可以通过python中numpy的特性MaskedArray与shp文件来限定其范围

import numpy as np
import shapefile as shp
mark = np.zeros((150,200),dtype=bool) #创建一个布尔形式与数据大小相符的数组
shp_file = shp.Reader('Gansu.shp')
rec = shp_file.shapeRecords()
for r in rec:
    poly = r.shape    #.shape属性一般需要通过迭代内部才能取到
for i in range(0,len(lon)):
    for j in range(0,len(lat)): #通过便利格点,来确定其是否在给定的shp文件范围内部
        if geometry.Point([lon[i],lat[j]]).within(geometry.shape(poly)):
            mark[j,i] = True # 根据shp文件结构不同,需要调整poly的结构,如这里使用的是甘肃省界shp文件,内部仅有一个多边形

到这里,mark数组就变为了在甘肃省内部为True,外部为False的一个标记数组,之后将经纬度网格点以及降水数据网格点取mark,即可绘制图像。这是python中较为常用的一个特性

  1. 绘图
  • 主要用到matplotlib下的pyplot包,需要在画图时将图中出现的字体改为新罗马

    from matplotlib import pyplot as plt #引入pyplot库
    import matplotlib as mpl
    mpl.rcParams['font.family'] = 'sans-serif'
    mpl.rcParams['font.sans-serif'] = ['Times New Roman']
    mpl.rcParams['axes.unicode_minus'] = False
    mpl.rcParams['mathtext.fontset'] = 'stix'
  • 主要的画图函数有

    plt.plot(x = ,y = ,color = ,linestyle = ) #折线图 可指定线条颜色,线条形式(实线 solid、虚线 dashed...)
    plt.contourf(x = , y = , z = , cmap = ) #填色图 z为每个格点上对应的值,注意,这里的xy必须为网格点数据,即不能是单一的xy一维序列,而是网格坐标,cmap可以修改填色所使用的colorbar
    import matplotlib.colors as mcolors
    clevs = [0,0.1,2,5,15,30,50]
    cdict = ['#00000000','#A9F090','#40B73F','#63B7FF','#0000FE','#FF00FC','#850042']
    prec_cmap = mcolors.ListedColormap(cdict)
    norm = mpl.colors.BoundaryNorm(clevs,prec_cmap.N) #可以使用这种方式自定义cmap,同样可以在scatter图中使用
    plt.scatter(x = , y = , c = , cmap = ,...) #注意,scatter中的xy与countourf不同,需为一维长度相等的数组,不可为二维网格
    plt.contour() #等值线图 同contourf
    plt.bar(x = , height = , width = ) #直方图 可以指定宽度或是高度随x而变化 
  • 绘图流程

可以通过plt直接调用几个函数直接进行绘制,或是通过

fig = plt.figure(figsize=(12,8))
ax = fig.addsubplot(111,projection = xxx) #这里的111是指一幅图,可以通过指定该参数来绘制组图如
ax1 = fig.addsubplot(2,2,1) # 此时添加了一副2*2的子图,并指定当前绘图区域在第一幅,即左上图,按照左到右,上到下排序
....
# 在绘图结束后,可以调用
plt.savefig(fanme = , dpi = , Orientation = , format = ) # 参数包括文件保存地址与文件名,文件清晰度(如保存位图可忽略),图片方向,图片格式
# 或是
plt.show() # 在弹出的对话框中选择保存的形式
  • 常用绘图工具函数
  1. 经纬度显示转化
from matplotlib.ticker import FuncFormatter
def to_latitude(temp, position):
    return '%1.0f'%(temp) + '°N'
def to_longtitude(temp,position): #通过占位符替换坐标轴显示形式,同理可以改写百分数
    return '%1.0f'%(temp)+ '°E'

需要在主函数,即绘图调用处加上,同理,改写百分制显示时只需要改写y轴显示形式即可

x_fomatter = FuncFormatter(to_longtitude)
y_fomatter = FuncFormatter(to_latitude)
plt.gca().yaxis.set_major_formatter(y_fomatter)
plt.gca().xaxis.set_major_formatter(x_fomatter)