
ERA5数据与Python可视化打造符合学术出版标准的夏季环流形势图第一次接触气象数据可视化时我被那些色彩斑斓的等值线图深深吸引但很快发现学术期刊对图表有着近乎苛刻的要求——模糊的线条、不规范的字体、低分辨率的输出都可能成为拒稿理由。本文将分享如何用Python从ERA5数据出发制作一张能直接用于论文发表的夏季环流形势图重点解决科研人员最常遇到的四个痛点配色选择、字体规范、地理信息标注和矢量输出。1. 数据准备与预处理ERA5作为目前最常用的再分析数据集其500hPa位势高度场数据是研究大气环流的基石。不同于简单的数据下载我们需要特别关注三个关键点时间范围选择夏季通常定义为6-8月(JJA)但某些研究可能需要延长到5-9月空间分辨率高分辨率(0.25°×0.25°)适合区域研究但会增加计算负担单位转换ERA5中的位势高度单位为m²/s²需除以重力加速度(9.8m/s²)转换为位势米import xarray as xr # 读取ERA5数据 def load_era5_data(path): ds xr.open_dataset(path) # 单位转换位势高度转换为位势米 ds[z] ds[z] / 9.8 # 选择夏季月份(6-8月) summer_months ds.sel(timeds[time.month].isin([6,7,8])) # 计算夏季平均 summer_mean summer_months.mean(dimtime) return summer_mean处理中国区域数据时要特别注意经度范围的定义方式。国际通用0-360°范围而国内研究常用-180-180°范围不当的转换会导致地图错位。2. 可视化基础框架搭建学术图表与普通图表的核心区别在于对细节的极致追求。我们从三个维度构建基础框架2.1 投影系统选择PlateCarree等距投影虽简单但在中高纬度地区会产生明显形变。对于东亚区域建议考虑以下投影对比投影类型优点缺点适用场景PlateCarree计算简单经纬线垂直高纬度形变严重全球或低纬研究LambertConformal保持角度不变设置参数复杂中纬度区域研究Mercator保持方向准确极区无法显示航海或热带研究import cartopy.crs as ccrs # 创建地图投影 def create_projection(proj_typePlateCarree): if proj_type PlateCarree: return ccrs.PlateCarree() elif proj_type LambertConformal: return ccrs.LambertConformal(central_longitude105, standard_parallels(25, 47)) else: return ccrs.Mercator()2.2 字体与排版规范主流气象期刊对字体有严格要求通常需要西文Times New Roman中文宋体含中文标注时字号8-12pt根据图表大小调整from matplotlib import rcParams # 设置学术图表字体规范 def set_academic_font(): rcParams.update({ font.family: serif, font.serif: [Times New Roman, SimSun], # 西文优先Times中文用宋体 font.size: 12, mathtext.fontset: stix, # 数学字体与正文一致 axes.unicode_minus: False # 解决负号显示问题 })提示在Linux系统下可能需要额外安装Times New Roman字体否则会自动回退到其他衬线字体2.3 色彩与线型设计单色等值线是学术论文最安全的选择但需要精心设计线型和标注主等值线实线间隔40位势米副等值线虚线间隔20位势米可选588线加粗至2-3pt突出显示标签位置避免重叠关键区域必须标注3. 地理信息与坐标系统规范的地理信息标注是论文图表的基本要求也是容易被忽视的细节。3.1 基础地理要素import cartopy.feature as cfeature def add_basic_features(ax): # 海岸线细线0.5pt ax.add_feature(cfeature.COASTLINE.with_scale(50m), linewidth0.5) # 陆地掩膜白色填充 ax.add_feature(cfeature.LAND.with_scale(50m), facecolorwhite) # 海洋掩膜浅蓝色填充 ax.add_feature(cfeature.OCEAN.with_scale(50m), facecolor#D0E0F0)3.2 国界与行政区划处理国界线时需要特别注意使用国家官方发布的矢量数据线宽控制在0.5-0.7pt颜色建议使用黑色或深灰色from cartopy.io.shapereader import Reader def add_admin_boundaries(ax, shp_path): # 添加省级边界细线0.3pt ax.add_geometries( Reader(shp_path).geometries(), ccrs.PlateCarree(), edgecolorgray, facecolornone, linewidth0.3 )3.3 经纬网格与刻度专业的气象图需要精心设计的经纬网格import matplotlib.ticker as mticker from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER def add_gridlines(ax, extent): # 设置网格线虚线半透明 gl ax.gridlines( crsccrs.PlateCarree(), draw_labelsTrue, linewidth0.5, colorgray, alpha0.5, linestyle-- ) # 仅显示左下方刻度 gl.top_labels False gl.right_labels False # 设置刻度间隔 gl.xlocator mticker.FixedLocator(range(extent[0], extent[1]10, 10)) gl.ylocator mticker.FixedLocator(range(extent[2], extent[3]10, 10)) # 格式化刻度标签 gl.xformatter LONGITUDE_FORMATTER gl.yformatter LATITUDE_FORMATTER4. 高级美化与输出技巧4.1 等值线优化绘制588位势米线时常规方法只是简单加粗其实可以做得更专业def enhance_contour(ax, lon, lat, data): # 主等值线5600-6000间隔40 c1 ax.contour(lon, lat, data, levelsrange(5600, 6001, 40), colorsblack, linewidths1) # 突出588线加粗不同线型 c2 ax.contour(lon, lat, data, levels[5880], colorsblack, linewidths2.5, linestyles-) # 等值线标签关键区域 ax.clabel(c1, fmt%1.0f, inlineTrue, fontsize10) ax.clabel(c2, fmt5880, inlineTrue, fontsize10, colorsred)4.2 输出格式选择期刊通常接受三种矢量格式PDF最通用文字可编辑EPS老牌出版标准但逐渐被PDF取代SVG可进一步编辑但部分期刊不接受def save_figure(fig, filename): # 同时保存多种格式 fig.savefig(f{filename}.pdf, dpi600, bbox_inchestight) fig.savefig(f{filename}.eps, dpi600, bbox_inchestight) fig.savefig(f{filename}.png, dpi600, bbox_inchestight)注意dpi设置仅影响栅格格式如PNG矢量格式PDF/EPS/SVG不受影响但需要明确指定4.3 期刊特定要求不同期刊对图表有细微差别要求投稿前务必检查AMS期刊推荐使用Helvetica字体Elsevier期刊图表宽度分单栏(8.5cm)和双栏(17.5cm)Nature系列要求提供原始可编辑的图表文件5. 完整工作流示例整合上述所有步骤的完整示例# 1. 初始化设置 import matplotlib.pyplot as plt set_academic_font() # 2. 数据准备 era5_data load_era5_data(h_2023_JJA.nc) lon, lat era5_data.longitude, era5_data.latitude hgt era5_data.z.sel(longitudeslice(60,140), latitudeslice(70,10)) # 3. 创建图形 fig plt.figure(figsize(12, 8)) proj create_projection(LambertConformal) ax fig.add_subplot(111, projectionproj) ax.set_extent([60, 140, 10, 70], crsccrs.PlateCarree()) # 4. 添加地理要素 add_basic_features(ax) add_admin_boundaries(ax, cn_shp/Province_9.shp) add_gridlines(ax, [60, 140, 10, 70]) # 5. 绘制等值线 enhance_contour(ax, lon, lat, hgt) # 6. 添加图题等 ax.set_title(Summer 500-hPa Geopotential Height (2023), pad20) # 7. 输出 save_figure(fig, summer_circulation_2023)在实际投稿中我通常会准备三种版本彩色版用于演示黑白版用于打印高对比度版用于黑白印刷的期刊。记住期刊审稿人看到的第一个图表往往决定了他们对整篇文章的第一印象。