使用Python绘制中国地图的详细教程

 1. 导入库
import cartopy
import numpy as np
import pandas as pd
import proplot as pplt
import geopandas as gpd
import matplotlib.pyplot as plt
from proplot import rc
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.path as mpath
import cmaps
seis = cmaps.GMT_seis

# 导出指北针的库
import gma
import gma.extend.mapplottools as mpt
import gma.extend.arrayenhancement as aec

# 导入自定义色带
from colormaps import parula

rc["font.family"] = "TeX Gyre Schola"
rc['tick.labelsize'] = 10
rc["axes.labelsize"] = 12
rc["axes.labelweight"] = "light"
rc["tick.labelweight"] = "light"

2. 导入数据

# 加载数据
import geopandas as gpd
file = r".\China map\中国省级地图GS(2019)1719号.geojson"
nine = r".\China map\九段线GS(2019)1719号.geojson"
china_main = gpd.read_file(file)
china_nine = gpd.read_file(nine)
china_main.head()

china_shp = "./nc data/Data_ipynb/country1"

from netCDF4 import Dataset 
import xarray as xr
nc_file = r".\nc data\EC-Interim_monthly_2018.nc" 
ds = xr.open_dataset(nc_file) 
lat = ds.latitude 
lon = ds.longitude 
data = (ds['t2m'][0,::-1,:] - 273.15) # 把温度转换为℃

3. 南海九段线部分数据预处理

开始绘图之前需进行数据选择,即中国区域的数据,特别是绘制南海小地图的更需要,可避免一些问题(小地图上方出现完整地图)

#中国整体范围
lon_range1=lon[(lon>=70)&(lon<=138)]
lat_range1=lat[(lat>=3)&(lat<=55)]
#南海九段线范围
lon_range2=lon[(lon>=104)&(lon<=125)]
lat_range2=lat[(lat>=0)&(lat<=27)]

china_full = data.sel(longitude=lon_range1,latitude=lat_range1)
china_sub = data.sel(longitude=lon_range2,latitude=lat_range2)


china_full_lon = china_full.longitude.values
china_full_lat = china_full.latitude.values
china_full_data = china_full.values

china_sub_lon = china_sub.longitude.values
china_sub_lat = china_sub.latitude.values
china_sub_data = china_sub.values

levels = np.arange(-25, 25 + 1, 1)  
4. 定义掩膜方法,从全球的nc数据中,裁出中国地图部分的数据(根据shp文件裁剪nc数据)
def maskout_areas(originfig, ax, shp_path, proj=None):
    import shapefile
    import cartopy.crs as ccrs
    from matplotlib.path import Path
    #from cartopy.mpl.clip_path
    from matplotlib.patches import PathPatch
    #sf = shapefile.Reader(shp_path)
    sf = shapefile.Reader(shp_path,encoding='gbk')
    vertices = []
    codes = []
    for shape_rec in sf.shapeRecords():
        if shape_rec.record[2] == 'China':
            pts = shape_rec.shape.points
            prt = list(shape_rec.shape.parts) + [len(pts)]
            for i in range(len(prt) - 1):
                for j in range(prt[i], prt[i + 1]):
                    if proj:
                        vertices.append(proj.transform_point(pts[j][0], pts[j][1], ccrs.Geodetic()))
                    else:
                        vertices.append((pts[j][0], pts[j][1]))
                codes += [Path.MOVETO]
                codes += [Path.LINETO] * (prt[i + 1] - prt[i] - 2)
                codes += [Path.CLOSEPOLY]
            clip = Path(vertices, codes)
            clip = PathPatch(clip, transform=ax.transData)
    for contour in originfig.collections:
        contour.set_clip_path(clip)
5. 绘制填色地图
levels = np.arange(-25, 25 + 1, 1)  

projn = ccrs.LambertConformal(central_longitude=107.5, 
                              central_latitude=36,
                              standard_parallels=(25.0, 47.0)
                            )
fig = plt.figure(figsize=(4,3.5),dpi=120,facecolor="w")
ax = fig.add_subplot(projection=projn)
# cs = data.plot.contourf(ax=ax,levels=levels,cbar_kwargs=cbar_kwargs,
#                         cmap=parula,transform=ccrs.PlateCarree(),
#                        )
#自定义colorbar 参数
cs = china_full.plot.contourf(ax=ax,levels=levels,add_colorbar=False,
                        cmap=parula,transform=ccrs.PlateCarree(),
                       )
# #basemask(ax=ax, cs=cs,shp=china_shp)
maskout_areas(originfig=cs,ax=ax,shp_path=china_shp,proj=projn)

ax.set_facecolor('#BEE8FF')
ax.spines['geo'].set_linewidth(0.5)
#ax.stock_img()
ax.set_extent([80, 130, 16, 52.5], crs=ccrs.PlateCarree())
ax.coastlines(linewidth=0.3,zorder=20)
ax.add_feature(cfeature.LAND, facecolor='white')
ax.add_feature(cfeature.LAKES.with_scale('110m'), facecolor='#BEE8FF')
#添加geopandas 读取的地理文件
ax.add_geometries(china_main["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="k",linewidth=.2)
ax.add_geometries(china_nine["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="black",linewidth=.3)
#设置标题
ax.set_title("Example Of China Lambert Projection")
gls = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree(), 
                   color='gray', linestyle='dashed', linewidth=0.2, 
                   y_inline=False, x_inline=False,
                   rotate_labels=0,xpadding=5,
                   xlocs=range(-180,180,10), ylocs=range(-90,90,5),
                   xlabel_style={"size":8,"weight":"bold"},
                   ylabel_style={"size":8,"weight":"bold"}
                  )
gls.top_labels= False                      
gls.right_labels=False

#添加南海小地图
# 定位南海子图的位置,四个数字需要调整
# 四个数字分别是(left, bottom, width, height):
# 子图左下角水平方向相对位置,左下角垂直方向相对位置,子图宽,子图高
ax2 = fig.add_axes([0.74, 0.24, 0.1, 0.25], projection = projn)
ax2.set_extent([104.5, 124, 0, 26],crs=ccrs.PlateCarree())
#ax2.set(xlim=(104.5, 125),ylim=(0, 26))
ax2.set_facecolor('#BEE8FF')
ax2.spines['geo'].set_linewidth(0.4)

cs2 = china_sub.plot.contourf(ax=ax2,levels=levels,add_colorbar=False,
                        cmap=parula,transform=ccrs.PlateCarree(),
                       )
#basemask(ax=ax2, cs=cs2,shp=china_shp)
maskout_areas(originfig=cs2,ax=ax2,shp_path=china_shp,proj=projn)
ax2.set_title("")

# 设置网格点
lb=ax2.gridlines(draw_labels=False,x_inline=False, y_inline=False,
                 linewidth=0.1, color='gray', alpha=0.8, 
                 linestyle='--' )
ax2.add_geometries(china_main["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="k",linewidth=.3)
ax2.add_geometries(china_nine["geometry"],crs=ccrs.PlateCarree(),
                  fc="None",ec="black",linewidth=.5)
ax2.add_feature(cfeature.LAND, facecolor='w')

## n.1 添加指北针
mpt.AddCompass(ax, LOC = (0.07, 0.86), SCA = 0.04, FontSize = 8)
## n.2 添加比例尺
mpt.AddScaleBar(ax, LOC = (0.2, 0.05), SCA = 0.12, FontSize = 6, 
                UnitPad = 0.2, BarWidth = 0.6)

cbar = fig.colorbar(cs,ax=ax,orientation='horizontal',
                    shrink=0.65,aspect=25,pad=.08)
cbar.ax.tick_params(labelsize=7.5,direction="in")
cbar.ax.tick_params(which="minor",direction="in")
#cbar.ax.xaxis.set_ticks_position('top')
cbar.set_label("Temperature (℃)",fontsize=9)
#cbar.ax.set_title("Sea Surface Temperature(m)",fontsize=9)
cbar.outline.set_linewidth(.4)
#plt.tight_layout()

 

物联沃分享整理
物联沃-IOTWORD物联网 » 使用Python绘制中国地图的详细教程

发表评论