一、前言做气象、海洋、能源研究的同学几乎每天都要和NetCDF.nc格式打交道。这种格式虽然跨平台、自带元数据但对新手来说用Python读取、裁剪、计算区域平均、画图每一步都可能踩坑。本文基于公开的ERA5示例数据可从Copernicus Climate Data Store免费获取完整演示用xarray打开并查看数据结构按经纬度范围裁剪计算区域如某省的逐月平均绘制等值线填色图并叠加地图底图使用cartopy全程不使用任何商业平台所有代码开源可复现。二、环境准备推荐使用conda创建专用环境bashconda create -n meteo python3.10 conda activate meteo conda install xarray netcdf4 matplotlib cartopy -c conda-forge pip install rioxarray # 可选用于地理裁剪三、数据准备本文使用ERA5 2022年全球月平均地表气温2m temperature数据文件名为t2m_2022.nc大小约180MB。您可以从 CDS官网 下载或使用我提供的示例片段见文末链接。如果手头没有真实数据可用下面的代码生成模拟NetCDF用于测试但建议使用真实数据练习pythonimport xarray as xr import numpy as np # 生成伪数据仅用于测试实际请替换为真实文件 lon np.linspace(70, 140, 141) lat np.linspace(15, 55, 81) time pd.date_range(2022-01-01, 2022-12-01, freqMS) data np.random.rand(len(time), len(lat), len(lon)) * 20 280 ds xr.Dataset({t2m: ([time,lat,lon], data)}, coords{time:time,lat:lat,lon:lon}) ds.to_netcdf(test.nc)四、核心代码与讲解4.1 读取文件并查看结构pythonimport xarray as xr ds xr.open_dataset(t2m_2022.nc) print(ds)输出类似textxarray.Dataset Dimensions: (time: 12, latitude: 721, longitude: 1440) Coordinates: * time (time) datetime64[ns] 2022-01-01 ... 2022-12-01 * latitude (latitude) float32 90.0 ... -90.0 * longitude (longitude) float32 0.0 ... 359.75 Data variables: t2m (time, latitude, longitude) float32 ... Attributes: ...注意ERA5的经纬度坐标名为latitude/longitude有时为lat/lon。先确认坐标名称。4.2 选择中国区域经度70~140°E纬度15~55°Npython# 方法一使用sel结合slice推荐 ds_china ds.sel(latitudeslice(55, 15), longitudeslice(70, 140)) # 注意latitude要降序从北到南因为ERA5的纬度从90到-90 # 如果您的数据纬度是升序则使用 slice(15,55)若经纬度名为lat/lon则对应修改。4.3 计算区域平均空间平均python# 对空间维度求平均得到每个月的区域平均温度 t2m_region_mean ds_china[t2m].mean(dim[latitude, longitude]) print(t2m_region_mean.values) # 一维数组长度12扩展如果想用面积加权平均因为网格面积随纬度变化可参考pythonweights np.cos(np.deg2rad(ds_china.latitude)) t2m_weighted ds_china[t2m].weighted(weights).mean(dim[latitude,longitude])4.4 将开尔文转为摄氏度pythont2m_c ds_china[t2m] - 273.154.5 绘制某个月份的空间分布图以2022年7月为例pythonimport matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature fig plt.figure(figsize(10, 8)) ax plt.axes(projectionccrs.PlateCarree()) # 提取7月数据索引为6 data_jul t2m_c.isel(time6) # 绘制等值线填色图 im ax.contourf(ds_china.longitude, ds_china.latitude, data_jul, levels20, cmapRdBu_r, transformccrs.PlateCarree()) # 添加地理要素 ax.add_feature(cfeature.COASTLINE, linewidth0.8) ax.add_feature(cfeature.BORDERS, linestyle:, linewidth0.5) ax.add_feature(cfeature.OCEAN, colorlightblue, alpha0.3) # 添加色标 plt.colorbar(im, axax, orientationhorizontal, pad0.05, label°C) # 设置标题和范围 ax.set_extent([70, 140, 15, 55], crsccrs.PlateCarree()) ax.set_title(2022年7月中国区域2m气温分布, fontsize14) plt.show()4.6 输出时间序列折线图pythonplt.figure(figsize(9,5)) plt.plot(t2m_region_mean.time, t2m_region_mean - 273.15, markero) plt.xlabel(时间) plt.ylabel(区域平均气温 (°C)) plt.title(2022年中国区域月平均气温变化) plt.grid(alpha0.3) plt.xticks(rotation45) plt.tight_layout() plt.show()五、常见问题与避坑问题解决方法打开文件报OSError: NetCDF: Unknown file format检查文件是否完整或使用enginenetcdf4参数坐标名称不是latitude/longitude先用ds.coords查看然后用rename({lat:latitude})修改裁剪后维度顺序混乱使用transpose(time,latitude,longitude)重排地图边界缺失安装naturalearth_lowres数据conda install -c conda-forge naturalearth内存不足使用xr.open_dataset(..., chunks{})结合 Dask 分块处理六、完整脚本汇总我已将上述代码整理成一个.py文件可一次运行生成两幅图。您可以在我的Gist中获取[链接占位]七、延伸思考批量处理多年数据可使用xr.open_mfdataset(t2m_*.nc)并行读取。提取单站点时间序列使用ds.sel(latitude30, longitude120, methodnearest)。保存处理后的结果ds_china.to_netcdf(t2m_china_2022.nc)。八、结语以上是气象数据处理中最基础也最频繁的操作。对于不熟悉编程或希望直接获取处理结果的研究者也可考虑使用羲和能源气象大数据平台。