保姆级教程:用Python和Cartopy绘制专业气象图(以ERA5 500hPa位势高度场为例)

保姆级教程:用Python和Cartopy绘制专业气象图(以ERA5 500hPa位势高度场为例) Python气象可视化实战从ERA5数据处理到Cartopy高级绘图技巧气象数据可视化是科研和业务工作中不可或缺的一环。对于初学者来说从数据获取到最终成图往往需要跨越多个技术门槛。本文将手把手带你完成一个完整的气象可视化流程使用Python的xarray处理ERA5再分析数据并通过Cartopy绘制专业的500hPa位势高度场图特别强化588线的显示效果。1. 环境准备与数据获取在开始之前我们需要配置好Python环境并获取必要的ERA5数据。气象数据处理与可视化通常需要以下几个核心库xarray处理NetCDF格式的气象数据Cartopy地理空间数据可视化Matplotlib基础绘图功能NumPy数值计算pip install xarray cartopy matplotlib numpyERA5是欧洲中期天气预报中心(ECMWF)提供的第五代全球气候再分析数据。获取ERA5数据通常有以下几种方式CDS API通过Copernicus Climate Data Store的API下载ECMWF Web API需要注册获取API key第三方平台部分科研机构提供预处理好的数据提示使用CDS API下载数据前需要先在Copernicus Climate Data Store网站注册账号并在用户设置中获取API key。2. 数据处理与夏季平均计算获得原始ERA5数据后我们需要进行预处理和计算夏季平均。ERA5数据通常以NetCDF格式存储非常适合用xarray处理。import xarray as xr # 读取NetCDF文件 data xr.open_dataset(era5_500hPa_2023.nc) # 查看数据结构 print(data)典型的ERA5 500hPa位势高度场数据包含以下维度time时间维度latitude纬度longitude经度计算夏季平均(6-8月)的位势高度场# 选择夏季月份 (6月、7月、8月) summer_months [6, 7, 8] summer_data data.sel(timedata[time.month].isin(summer_months)) # 计算夏季平均 summer_mean summer_data.mean(dimtime) # 位势高度单位转换 (从m²/s²转换为位势米) summer_mean[z] summer_mean[z] / 9.806653. Cartopy基础绘图设置Cartopy是一个强大的地理空间数据处理库特别适合气象数据的可视化。在绘制地图前我们需要进行一些基础设置。import cartopy.crs as ccrs import cartopy.feature as cfeature import matplotlib.pyplot as plt # 创建图形和坐标轴 fig plt.figure(figsize(12, 8)) ax fig.add_subplot(1, 1, 1, projectionccrs.PlateCarree()) # 设置地图范围 (东亚区域) ax.set_extent([60, 140, 10, 70], crsccrs.PlateCarree()) # 添加地理特征 ax.add_feature(cfeature.COASTLINE.with_scale(50m), linewidth0.8) ax.add_feature(cfeature.BORDERS.with_scale(50m), linestyle:, linewidth0.5)Cartopy支持多种地图投影方式常见的有PlateCarree等距圆柱投影LambertConformal兰伯特正形圆锥投影Mercator墨卡托投影Robinson罗宾森投影4. 位势高度场等值线绘制技巧绘制等值线是气象分析中最常用的可视化方法之一。我们将重点讲解如何绘制专业的等值线图并突出显示特定的588线。import numpy as np # 准备经纬度网格 lon summer_mean.longitude lat summer_mean.latitude lon_grid, lat_grid np.meshgrid(lon, lat) # 绘制基本等值线 (间隔40位势米) cs ax.contour(lon_grid, lat_grid, summer_mean[z], levelsnp.arange(5600, 6000, 40), colorsblack, linewidths1) # 添加等值线标签 ax.clabel(cs, inlineTrue, fontsize10, fmt%1.0f) # 特别强调588线 cs588 ax.contour(lon_grid, lat_grid, summer_mean[z], levels[5880], colorsred, linewidths3) ax.clabel(cs588, inlineTrue, fontsize12, fmt5880)为了使图像更加专业我们还可以添加以下元素色阶填充用颜色表示位势高度值风场箭头叠加风场信息高低压中心标记标注重要的天气系统# 色阶填充 cf ax.contourf(lon_grid, lat_grid, summer_mean[z], levelsnp.arange(5600, 6000, 40), cmapcoolwarm, extendboth) plt.colorbar(cf, axax, label位势高度 (位势米))5. 高级定制与常见问题解决在实际操作中经常会遇到一些技术问题。以下是几个常见问题及其解决方案5.1 中文显示问题Matplotlib默认不支持中文显示需要特别设置from matplotlib import rcParams # 设置中文字体 rcParams[font.family] SimHei rcParams[axes.unicode_minus] False # 解决负号显示问题5.2 地图细节优化添加更多地理信息可以提升地图的专业性# 添加省界 import cartopy.io.shapereader as shpreader # 加载中国省界shapefile provinces shpreader.Reader(china_province.shp).geometries() ax.add_geometries(provinces, ccrs.PlateCarree(), edgecolorgray, facecolornone, linewidth0.5) # 添加经纬网格 gl ax.gridlines(draw_labelsTrue, linewidth0.5, colorgray, alpha0.5) gl.top_labels False gl.right_labels False5.3 图像输出设置高质量论文需要高分辨率的图片plt.savefig(500hPa_height.png, dpi300, bbox_inchestight, transparentFalse)6. 完整代码示例以下是整合了所有功能的完整代码import xarray as xr import numpy as np import cartopy.crs as ccrs import cartopy.feature as cfeature import matplotlib.pyplot as plt from matplotlib import rcParams # 设置中文字体 rcParams[font.family] SimHei rcParams[axes.unicode_minus] False # 1. 数据读取与处理 data xr.open_dataset(era5_500hPa_2023.nc) summer_data data.sel(timedata[time.month].isin([6, 7, 8])) summer_mean summer_data.mean(dimtime) summer_mean[z] summer_mean[z] / 9.80665 # 2. 创建地图 fig plt.figure(figsize(15, 10)) ax fig.add_subplot(1, 1, 1, projectionccrs.PlateCarree()) ax.set_extent([60, 140, 10, 70], crsccrs.PlateCarree()) # 3. 添加地理特征 ax.add_feature(cfeature.COASTLINE.with_scale(50m), linewidth0.8) ax.add_feature(cfeature.BORDERS.with_scale(50m), linestyle:, linewidth0.5) # 4. 绘制位势高度场 lon, lat np.meshgrid(summer_mean.longitude, summer_mean.latitude) cs ax.contour(lon, lat, summer_mean[z], levelsnp.arange(5600, 6000, 40), colorsblack, linewidths1) ax.clabel(cs, inlineTrue, fontsize10, fmt%1.0f) # 5. 突出588线 cs588 ax.contour(lon, lat, summer_mean[z], levels[5880], colorsred, linewidths3) ax.clabel(cs588, inlineTrue, fontsize12, fmt5880) # 6. 添加色阶 cf ax.contourf(lon, lat, summer_mean[z], levelsnp.arange(5600, 6000, 40), cmapcoolwarm, extendboth) plt.colorbar(cf, axax, label位势高度 (位势米)) # 7. 添加网格和标题 gl ax.gridlines(draw_labelsTrue, linewidth0.5, colorgray, alpha0.5) gl.top_labels False gl.right_labels False plt.title(2023年夏季500hPa平均位势高度场, fontsize16) plt.savefig(500hPa_height.png, dpi300, bbox_inchestight) plt.show()在实际项目中我发现Cartopy在处理高分辨率海岸线数据时会显著增加绘图时间。对于快速测试可以使用较低分辨率的地理特征如50m而非10m。另外当数据集很大时使用dask可以有效地管理内存使用。