python cartopy绘制子图九段线,南海诸岛
今天给大家介绍如何使用 「Cartopy」 绘制一张高质量的中国地图,带上九段线和南海诸岛子图。看完这篇文章,你不仅能绘制出专业的地图,还能轻松地处理各种矢量和栅格数据!赶紧收藏!
「1. 先准备数据」
绘制地图的第一步是准备数据。在这里,我们需要两种数据:
「降水格点栅格数据」:作为示例数据,可以显示中国的降水分布; 「矢量数据」:包括中国省界 shapefile 和九段线 shapefile,用于精确绘制边界。
栅格数据准备
降水数据可以通过多个开源平台获取,例如 中国气象局数据开放平台。下载的降水格点数据可以通过以下代码处理,提取并计算月降水总量的均值栅格:
import pandas as pd
import numpy as np
import os
dir = 'D:/Acdemic/xibei/data_1/grid_prcp/'
txtLists = os.listdir(dir)
files = list(filter(lambda x: x[-4:] in ['.txt'], txtLists))
df = pd.DataFrame()
i = 0;
prcp = np.zeros((72, 128, len(files)))
for file in files:
data = pd.read_table(dir+file, sep='\s+', header=None, index_col=False, skiprows=6)
print(str(i) + ': ' + file)
prcp[:, :, i] = np.array(data)
i += 1
prcp1 = np.mean(prcp, 2) * 12
prcp1[prcp1 < -1000] = None
矢量数据准备
我们需要两个矢量文件:
中国省界矢量( china.shp
);九段线矢量( dashline.shp
)。
定义两个辅助函数,方便在绘图中加载这些数据:
import cartopy.io.shapereader as shpreader
def add_china(ax, **kwargs):
'''
在地图上画出中国省界的shapefile.
Parameters
----------
ax : GeoAxes
目标地图.
**kwargs
绘制shape时用到的参数.例如linewidth,edgecolor和facecolor等.
'''
proj = ccrs.PlateCarree()
reader = shpreader.Reader('D:/OneDrive/data/china.shp')
provinces = reader.geometries()
ax.add_geometries(provinces, proj, **kwargs)
reader.close()
def add_dashline(ax, **kwargs):
'''
在地图上画出中国省界的shapefile.
Parameters
----------
ax : GeoAxes
目标地图.
**kwargs
绘制shape时用到的参数.例如linewidth,edgecolor和facecolor等.
'''
proj = ccrs.PlateCarree()
reader = shpreader.Reader(r"D:\OneDrive\data\dashline.shp")
provinces = reader.geometries()
ax.add_geometries(provinces, proj, **kwargs)
reader.close()
矢量文件的下载链接见文末,记得保存到本地,并修改路径。
「2. 开始绘图」
绘图中,我们将使用 Cartopy
的 「Lambert Conformal 投影」 来绘制中国地图,同时在子图中展示南海诸岛及九段线。
import geopandas as gpd
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
projn = ccrs.LambertConformal(central_longitude=105,
central_latitude=40,
standard_parallels=(25.0, 47.0))
fig = plt.figure(figsize=(4,3.5),dpi=120,facecolor="w")
ax = fig.add_subplot(projection=projn)
ax.add_feature(cfeature.LAND, facecolor='white')
ax.add_feature(cfeature.OCEAN)
ax.add_feature(cfeature.LAKES.with_scale('110m'), facecolor='#BEE8FF')
ax.set_extent([70, 140, 15, 55], crs=ccrs.PlateCarree())
long = np.linspace(72, 136, 128); lat = np.linspace(18, 54, 72)
im = ax.contourf(
long, lat[::-1], prcp1,
levels=np.linspace(0, 2000, 11), cmap='RdYlBu_r',
extend='both', alpha=0.8, transform=ccrs.PlateCarree()
)
cbar = fig.colorbar(
im, ax=ax, shrink=0.9, pad=0.1, orientation='horizontal'
)
#添加geopandas 读取的地理文件
add_dashline(ax, ec="black", linewidth=.2)
add_china(ax, ec="black", fc="None", linewidth=.2)
gls = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree(),
color='k', linestyle='dashed', linewidth=0.3,
y_inline=False, x_inline=False,
xlocs=range(70,150,10), ylocs=range(15,65,10)
)
#gls.top_labels= False
#gls.right_labels=False
ax2 = fig.add_axes([0.76, 0.265, 0.20, 0.3], projection = projn)
ax2.set_extent([104.5, 125, 0, 26])
im = ax2.contourf(
long, lat[::-1], prcp1,
levels=np.linspace(0, 2000, 11), cmap='RdYlBu_r',
extend='both', alpha=0.8, transform=ccrs.PlateCarree()
)
ax2.set_facecolor('#BEE8FF')
ax2.spines['geo'].set_linewidth(.2)
# 设置网格点
lb=ax2.gridlines(draw_labels=False,x_inline=False, y_inline=False,
linewidth=0.1, color='gray', alpha=0.8,
linestyle='--' )
add_dashline(ax2, ec="black", linewidth=.2)
add_china(ax2, ec="black", fc="None", linewidth=.2)
ax2.add_feature(cfeature.LAND, facecolor='w')
plt.tight_layout()
plt.show()
「3. 结果展示」
最终的结果如下图所示:
「代码解析」
核心步骤解读:
「投影设置」: projn = ccrs.LambertConformal(...)
,Lambert 正形投影适合中国地图显示,能避免纬度偏差造成的视觉问题。「绘制背景」:使用 ax.add_feature
添加陆地、海洋和湖泊特征,颜色和风格可自定义。「栅格数据叠加」:利用 ax.contourf
绘制降水分布图,并设置色彩范围和透明度。「矢量边界」:自定义函数 add_china
和add_dashline
,通过 shapefile 精确绘制省界和九段线。「南海诸岛子图」:子图通过 fig.add_axes
添加,独立设置绘图范围和投影,同样支持栅格与矢量叠加。「美化细节」:添加网格、色条和样式优化,提升地图可读性。
「4. 数据获取和说明」
「降水数据」:CMA 数据开放平台;http://data.cma.cn 矢量数据: 中国省界矢量:Data Source;https://github.com/datasets/geo-boundaries-world-110m 九段线矢量:参考 South China Sea Dashline。https://github.com/datasets/geo-boundaries-world-110m
「结语」
掌握了这套模板,你可以轻松绘制出带九段线和南海子图的中国地图,并添加任意的栅格或矢量数据进行展示!如果觉得有用,赶紧点赞收藏!🎉
求求你点个在看吧,这对我真的很重要