做气象、水文、环境或者新能源项目的人,最近两三年一定绕不开一个名字:ECMWF 的 ERA5。这套全球再分析数据几乎是目前公开可获取的同类产品里综合表现最稳的,空间分辨率做到了 0.25°(约 31 公里),时间上能逐小时输出,变量覆盖从常规地面气象要素到高空分层再到大气的各种通量项。文章开篇先给结论:如果你需要长时间序列、空间连续、相对可靠的历史气象场,ERA5 基本是首选,甚至在某些场景里比站点实测数据更好用——因为站点数据断点、缺测、口径不一致的问题,在再分析数据里被统一规避了。
这篇东西适合正在接触 ERA5 的人,包括刚入行的数据分析师、做光伏风电功率预测的工程师、搞农业气象的科研助理,以及所有被导师或需求方丢来一句“你去把 ERA5 数据下一下”而不知道从哪下手的同学。我会按照自己实际用下来的理解,把 ERA5 的数据逻辑、下载流程、文件格式、常见坑一次性讲清楚。文章里不会有云里雾里的官方文档翻译,全部是动手操作层面能直接用的经验。
1. 为什么你有必要搞懂“再分析”:ERA5 的数据逻辑
1.1 再分析到底在“分析”什么
先把概念理顺。很多人第一次听到“再分析”会以为它是一堆观测数据的插值结果,比如把全球几千个气象站的温度数据揉在一起,插出一个漂亮网格。如果真这么简单,那 ERA5 不会积累这么高的口碑。
再分析的核心逻辑是“用数值模式把观测吸收进去”。ECMWF 内部有一套非常成熟的大气环流模式,这套模式能够根据物理定律模拟大气的运动、热量交换、水循环。但模式有误差,观测有真值,怎么把两者结合?答案就是资料同化:每一段时间步里,把全球范围内的卫星辐射、探空气球、地面自动站、船舶报、飞机报等数据“灌”进模式,让模型的运行轨迹不断被真实观测拉回正确方向。ERA5 用的同化系统是 IFS Cycle 41r2,同化方法以四维变分(4D-Var)为核心,这不是简单插值,而是通过最小化“模式预报与观测之间差异”来反演出最优的大气状态场。
通俗一点理解:再分析产品像一个“戴着镣铐跳舞”的模拟器。模式负责保证物理一致性,观测负责随时纠偏。最终产出的每个网格点、每个时刻的气象要素,都不是单纯来自哪一颗卫星或哪一个站点,而是整个地球系统综合反演出来的结果。
1.2 为什么 ERA5 不是“预测”而是一套“重构”
另一个容易误解的点是:ERA5 虽然出自 ECMWF(欧洲中期天气预报中心),但它不是预报数据。预报是面向未来的,ERA5 是面向过去的。它使用的模式配置和实时预报模式有共通之处,但同化的观测数据是经过质量控制、延迟整理的完整历史观测。
实际上 ERA5 提供的数据通常滞后实际时间约 5 天,因为要等全球观测数据收集齐全、完成质量检验。ECMWF 之外还提供一套叫 ERA5T 的初步数据,滞后时间更短,但属于未完全质控的版本。做正式研究或者出报告时我建议认准 product_type = "reanalysis" 的产品,而不是贪快用 ERA5T 凑数。如果你是做实时监测系统,那么 ERA5T 可以临时顶一顶,但后续数据出来后一定要回补替换。
我把 ERA5 的本质归纳为三句话:
- 它是一段长时间、连续、全球覆盖的大气状态重构历史;
- 每个时刻的全球大气状态是模式与观测融合的结果;
- 它解决的是“观测站点稀疏、时间不连续、空间不统一”的问题。
1.3 从 ERA-Interim 到 ERA5 的关键迭代
如果之前用过 ECMWF 上一代产品 ERA-Interim,你会明显感受到 ERA5 是“跨代”的提升,而不只是分辨率变高了一点。
先看几个硬指标:ERA-Interim 的水平分辨率是 0.75°(约 79 公里),时间分辨率是 6 小时,垂直分层 60 层;ERA5 水平分辨率提高到 0.25°(约 31 公里),时间分辨率提高到 1 小时,垂直分层增加到 137 层,最高层到 1 hPa(大概 80 公里高度)。这意味着 ERA5 对中小尺度天气系统、地形复杂的区域、强对流天气过程的描述能力明显更好。
更重要的改进是数据同化和模式物理的升级。ERA5 能够同化更多类型的卫星观测数据,包括近几十年来大量的辐射计、散射计、掩星观测资料;在降水、土壤湿度、海洋表面温度这些变量的模拟上也比上一代产品有明显改善。实际使用中,ERA5 在东亚地区的地面气温、风速的误差通常低于 ERA-Interim,尤其是在资料稀少的区域和高海拔地带。
所以我的建议很直接:新项目一律用 ERA5,没必要再碰 ERA-Interim。除非你要对比历史成果、复现别人论文里的数据,才需要刻意使用旧版本的逐变量输出口径。
2. 盘点 ERA5 的家底:空间分辨率、变量分类和时间粒度
2.1 0.25° 背后的真实物理分辨率
ERA5 的数据网格并不是单纯把地球切成了一个个边长 31 公里的方块。它内部是基于球面上的谱模式(spectral model)来计算的,输出的时候转到了规则经纬度网格。因此 0.25° 的“有效分辨率”不等于每个网格内所有气象过程都能被精确描述,它只是代表模式的截断尺度。
对使用者来说,0.25° 意味着两点:第一,它比绝大多数台站网密度更高的国家地区更粗,比如中国东部省份平均每几十公里就有一个国家级气象观测站,所以你在站点位置读取 ERA5 网格值时,它不是站点实测,而是周边大气的网格平均状态;第二,对于全球尺度和区域尺度研究,0.25° 已经能满足绝大多数需求,比如计算区域平均气温、分析风资源分布、评估降水大尺度特征等。
在使用层面,我非常建议明确一个原则:不要试图用 ERA5 数据“还原”某一个具体站点的分钟级天气变化,那不是这套数据的定位。它适合做统计、做背景场、做模型输入、做空间制图。如果非要用站点做验证,务必要用站点周边网格的平均值来对比,而不是拿单个网格点当作站点实况的完全替代品。
2.2 单层变量与压力层变量的选择
ERA5 在数据组织上主要分成两大数据集:单层变量(single-levels)和压力层变量(pressure-levels)。从名字就能看出来,单层变量指的是某个高度或者某个物理面上的量,而压力层变量是规则气压层上的三维大气状态。
单层变量里最常见的包括:
- 2 米温度(2m temperature)
- 2 米露点温度(2m dewpoint temperature)
- 10 米风场 U/V 分量(10m u/v wind component)
- 海平面气压(mean sea level pressure)
- 地表气压(surface pressure)
- 总降水量(total precipitation)
- 地表太阳辐射(surface solar radiation)
- 各种通量项(感热通量、潜热通量等)
压力层变量则是定义在 1000 hPa、975 hPa、950 hPa……一直到 1 hPa 这些高度上的,典型变量有温度、位势高度、比湿、风场、垂直速度等。做高空天气分析、大气化学运输、垂直结构研究时,必须用压力层数据。
有一类变量要特别留意,比如总降水量,它在单层数据集里的累积方式是有讲究的,官方给出的是从数据开始时间往前累积的值,每一个时次代表“过去一小时累积降水”。这跟站点雨量计的“小时降水”概念是一致的,但如果你下载 00 时和 01 时两个时刻的降水数据相减,得到的就是 00—01 时这一个小时内的降水量。很多新手直接拿“total precipitation”当作瞬时雨强,单位还会看错,后面我专门讲。
2.3 不同时间产品怎么选:逐小时、逐月平均还是极端指数
ERA5 的原始时间分辨率是逐小时输出,这在同类再分析产品里已经算是天花板了。但逐小时全变量全球数据量非常庞大,一次下载很容易把电脑硬盘搞爆,所以 ECMWF 还提供了很多“后处理”产品。
常见的时间聚合产品包括:
- 月平均月值(monthly averaged by month)
- 月平均日值(monthly averaged by day,即某个变量的逐日序列的月内均值)
- 日统计产品(daily statistics)
- 气候学指标(如极端温度指数等)
做长期气候变化分析时,直接用月平均数据即可,没必要下载逐小时再去重采样,省流量、省时间、省内存。做天气过程分析、可再生能源功率预测、逐日模型驱动时,才需要逐小时原始数据。
另外一个实用建议:如果你需要的最终结果是日均值,可以考虑直接下载日聚合产品,而不是把 24 个小时都拉下来再在本地算平均。因为 ERA5 原始逐小时数据是 GRIB 或者 NetCDF 格式,单文件动辄几个 GB,在里面挑变量和时间再逐点运算,既费时间又容易内存溢出。官方提供的日统计产品已经做好了这些聚合,直接拿结果是最优解。
3. 下载 ERA5 的高效路径:从 CDS 注册到脚本化批量拉取
3.1 CDS 平台和 API 密钥配置
ERA5 数据官方获取渠道是 CDS(Climate Data Store),地址是 cds.climate.copernicus.eu,由 ECMWF 代表欧盟哥白尼计划运行。第一次使用需要注册账号,注册完全免费,个人用户和非商业用途都可以直接使用。
注册完登录后,进入个人页面能找到一个 API key 的配置入口,里面有你的 UID 和 API key 字符串。这一步很关键:如果只用网页下载,每次都要在浏览器里勾变量、选时间、点提交,一旦批量请求多了非常痛苦。配置好 CDS API 之后,你可以完全通过 Python 脚本发起请求、等待处理、自动下载。
CDS 的 API 机制其实不像普通网站接口那样“请求即返回”。它更像任务队列:你提交一个数据请求,服务器判断参数合法后进入排队,后台开始切片、处理、组装文件,完成后给你一个下载链接。所以脚本里调用 retrieve 之后需要等待,有时候几分钟,有时候几十分钟甚至更久。这是正常的,不要因为等一下就没耐心或者断掉进程。
配置文件一般放在用户目录下,命名为~/.cdsapirc,内容格式:
url: https://cds.climate.copernicus.eu/api key: UID:API_KEY写完后可以执行一句话验证是否生效:
python -c "import cdsapi; print(cdsapi.__version__)"如果这段命令不报错,说明安装和配置没问题。我后来换电脑重装环境时,经常忘掉复制.cdsapirc,结果脚本一直提示认证失败,排查了一圈才发现是配置文件没放对位置。建议直接把这份文件纳入环境初始化脚本,免得重复踩坑。
3.2 用 Python 脚本批量下载,而不是在网页上“点点点”
网页端检索下载适合临时取一小段数据,比如只要某一天、某一个省范围的数据。但实际项目往往需要几年甚至几十年的数据,如果你还手动在网页上重复提交请求,一轮下来可能上百次操作,纯属浪费生命。
我用得最多的下载方式是写一个download_era5.py脚本,把年份、月份做成循环,逐月提交请求。以单层气温数据为例,核心代码长这样:
import cdsapi c = cdsapi.Client() for year in [2020, 2021]: for month in [1, 2, 3, 4, 5, 6]: c.retrieve( "reanalysis-era5-single-levels", { "product_type": ["reanalysis"], "variable": ["2m_temperature"], "year": [str(year)], "month": [str(month)], "day": [ "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", ], "time": [ "00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00", ], "data_format": "netcdf", "download_format": "unarchived", }, f"era5_t2m_{year}_{month}.nc", )这里有几个参数值得解释:
data_format指定输出为 netcdf,这对大多数 Python 用户更友好。download_format指定unarchived,这样下载下来直接是.nc文件;如果不指定,默认会打包成 tar 压缩包,还需要先解压一步。- 时间列表必须写完整的 24 个小时,CDS 平台不会自动帮你生成“所有小时”,这里确实是有点死板,但也是官方 API 的基本规则。
下载大范围数据时,一次性提交 32 年、365 天、24 小时的全变量请求很容易被服务器拒绝。我的经验是按年甚至按月拆分请求,一方面失败之后重试成本低,另一方面平台对请求的排队优先级也和数据量有关系。按月下载看似慢,但每个请求的成功率明显更高。
3.3 请求被拒、队列卡死和数据量限制的应对
CDS 平台近几年因为用户量大,经常出现排队时间不稳定、偶发请求失败的情况。我遇到最多的几类问题:
第一,请求参数超限。比如一次提交的年份过多、变量过多、区域过大,平台直接返回 400 错误。解决办法是缩小请求粒度,把整段数据拆成若干个小请求,再本地合并。
第二,返回格式异常。有时候你明明指定了 NetCDF,下载下来却发现是 tar 包或者文件名不对。这大概率是请求中的download_format没写对,建议每次都显式写上"download_format": "unarchived"。
第三,进程中断导致下载失败。因为请求处理时间较长,本地电脑休眠或者网络波动都会让下载中断。更稳妥的做法是在脚本里增加重试机制,并写成断点续传的逻辑。我自己常用retry循环包住 retrieve,配合日志记录,哪怕中途断了也能知道哪些文件还没下载成功。
CDS 对用户每天的数据下载总量也有配额限制。如果只是做中小区域的分析,配额基本摸不到顶;但如果你需要全球范围几十年的逐小时数据,那配额会很紧张。解决思路是尽量减少不必要的数据量:先确定研究区域,在请求里加上area参数限定经纬度范围;只要几个变量,就不要把整个数据集所有变量都拉下来。下载之前多想一步,能省掉后期大量的存储和清洗时间。
4. 读取 ERA5 时的格式关:GRIB、NetCDF 与坐标系统易错点
4.1 GRIB 文件为什么让新手想弃坑
ERA5 官方最原汁原味的格式是 GRIB,这是气象界的老牌二进制格式,专门为了存储网格化的气象数据设计。WMO(世界气象组织)主导维护这个格式,它的特点是自描述性极强,文件头里包含了变量名、单位、级别、时间、网格类型等大量元数据,但要直接读取并不像 CSV 那么友好。
如果你用xarray直接打开 GRIB 文件,会提示需要安装cfgrib和eccodes插件。因为 GRIB 本身是一大段二进制流,解析它需要底层库来按规则切片、识别消息边界。第一次用的人经常在装eccodes这一步被系统库依赖折磨——macOS 上要用 Homebrew 装,Linux 上要 apt 装,版本还得对得上。
我后来给所有新合作者的统一建议是:除非你有深厚的气象背景或者需要使用特定的 GRIB 工具链,否则下载时直接选 NetCDF 格式。NetCDF 本质上是为科学计算设计的自描述二进制格式,xarray可以直接读取,变量名、坐标、单位一目了然,调试时还能直接.info()或.print()。ERA5 的 NetCDF 版本本质上是从 GRIB 转换过来的,数据内容一致,只是文件组织更适合通用科学计算。
如果实在拿到了 GRIB 文件,也没必要慌。最简单的转换方式是用cfgrib插件读取,或者用eccodes提供的grib_to_netcdf命令行工具:
grib_to_netcdf -o output.nc input.grib但这里有一个大坑:如果一个 GRIB 文件里混合了多个垂直层、多个变量,直接转换时可能丢失一部分消息或者产生奇怪的维度合并。原因是 GRIB 消息的排列有固定规则,不同变量在不同层之间的存储顺序不一定符合 NetCDF 的维度组织习惯。所以转换前务必确认文件内到底包含了哪些参数,必要时先拆分成多个单一变量文件再转。
4.2 经纬度坐标陷阱:0~360 和 -180~180
这是初识 ERA5 最容易出的问题,没有之一。ERA5 原始网格的经度坐标范围是 0 到 360,而不是常见的 -180 到 180。也就是说,北京的经度在常规 GIS 里是 116.4°E,对应 116.4;如果你把同一个点放在 0~360 网格上,它的经度也是 116.4,看起来没什么区别。但问题出在西半球。
比如纽约的经度是 -74°W,常规表示为 -74,而 ERA5 网格上它会变成 360 - 74 = 286。如果你用习惯了全球底图,直接拿 -74 去 ERA5 文件里sel(longitude=-74),结果会得到一个空数组或者提示“out of bounds”。正确做法是把负经度统一转换成 0~360:
lon_new = lon % 360另一个方向也同理:如果你从文件里读出了经度 286,而底图坐标系是 -180~180,就得自行转换 286 - 360 = -74。这种坐标系的不一致在绘制全球地图、跨数据集对比时尤其致命,因为绝大多数制图工具默认输出经度是 -180~180,混用坐标容易导致图形“错位”或者图例范围异常。
4.3 经度、维度排列顺序对数据切片的影响
ERA5 的 NetCDF 文件打开后,维度顺序一般是time,latitude,longitude(单层变量),或者是time,level,latitude,longitude(压力层变量)。latitude 通常是从北到南排列的,也就是 90 到 -90;longitude 是从 0 到 360。这种排列和很多遥感数据不一致,读取时务必先打印ds.coords确认。
如果你习惯了直接从数组索引去读数据,比如data[0, 100, 200],很容易拿错网格点。更稳妥的方式是用坐标选择,比如:
ds.sel(latitude=30.25, longitude=104.0, method="nearest")这样无论数组内部怎么排列,xarray 都会帮你找到最近的网格点。
还有一个容易忽略的细节:ERA5 输出的网格不是严格的高斯网格,而是规则经纬度网格(regular lat/lon grid),所以在大多数场景下可以当作普通矩形网格来处理。但要注意经纬度坐标在文件里是二维还是一维的问题。ERA5 的 NetCDF 版本给的经度和纬度是一维坐标数组,而不是二维网格坐标,这让sel和isel的操作变得很简单;如果你手头拿到的是已经转换成其他网格的数据,那结构可能就完全不一样了。
5. 实战示例:导出一座城市的逐小时气温曲线
5.1 从网格坐标到站点位置的最近邻选择
假设任务是把成都(30.57°N,104.06°E)2020 年 6 月的逐小时 2 米气温导出成一个 CSV,用来和当地气象站数据做对比。先下载好区域范围内的 ERA5 逐小时 2m 温度 NetCDF 文件,然后进入数据处理环节。
第一步是定位城市所在的网格点。因为 ERA5 网格分辨率约 0.25°,所以成都的精确坐标大概率不会正好落在网格点上,必须做“最近邻”选取。用method="nearest"就能搞定:
import xarray as xr ds = xr.open_dataset("era5_t2m_2020_06.nc") t2m = ds["t2m"] - 273.15 # 转成摄氏度 point = t2m.sel(latitude=30.57, longitude=104.06, method="nearest") # 查看实际选中的网格坐标 print(point.latitude.values, point.longitude.values)这里有一个细微差别:ERA5 文件里 longitude 是从 0 到 360,104.06 本来就落在 0~360 区间内,所以不需要做% 360的转换。如果你要处理的是西经或负经度地区,请务必先统一坐标体系再读取。
用最近邻比较简单,但如果你的研究点正好落在某根经线上,最近邻产生的偏差就会变得很大。更精细的做法是在四个相邻网格点之间做双线性插值,只是这样代码量会多一些。对于气温这种空间连续性比较好的变量,最近邻的误差通常在一个可接受的范围内;但对于降水这种空间变率大的变量,建议直接用区域平均而不是单点,我后文会解释原因。
5.2 按时间范围切片与缺失值检查
选定空间点之后,接下来要处理时间轴。ERA5 的逐小时数据时间步长是整点小时,坐标格式是datetime64,切片方式非常直接:
subset = point.sel(time=slice("2020-06-01", "2020-06-30 23:00"))切片后务必检查一下数据是否有 NaN:
import pandas as pd df = subset.to_dataframe().dropna() print(df.head()) print(df.isna().sum())ERA5 的全球陆地区域一般不会有系统性缺失,但近海岸网格湿网格上某些变量可能会出现“未知值”。因为 NetCDF 里的缺失值可能标记成nan,也有可能是一个巨大的负数(比如-9999),单纯用isna()查不出来。
更好的办法是读数据时加上mask_and_scale=True(xarray 默认开启),同时打印数组的min(),max(),一旦发现最小值是 -9999 之类明显异常的数,就要立刻查一下变量属性里的_FillValue。这个习惯能避免数据进入后续计算后悄悄带偏结果。
5.3 单位换算和时间戳的坑
ERA5 的原始单位绝大多数不是我们习惯用的常规单位。以气温为例,NetCDF 文件里 2m 温度的单位是 K(开尔文),换算成摄氏度需要减去 273.15。湿度类的变量单位往往是kg/kg,风速是m/s,气压是Pa(注意不是 hPa),降水量是m(注意不是 mm)。
如果你从变量属性里读到units: K,可以换算;但有时你打开不同的 CDS 产品,温度单位可能是°C而不是K,因为官方后处理产品在生成时做过单位调整。这也是为什么我建议在使用任何变量之前,先用ds[var].attrs["units"]看属性,而不是凭记忆去猜。
时间戳方面也容易踩坑。ERA5 NetCDF 文件的 time 坐标在 xarray 打开后通常是datetime64[ns],看起来很正常,但如果你用pandas读取,偶尔会碰到整数类型的时间坐标(比如单位是 hours since 1900-01-01)。遇到这种情况,处理方式是用 pandas 的to_datetime配合unit="h":
time_index = pd.to_datetime(ds.time.values, unit="h")主要是为了防止数据源不是新版 xarray 或者经过其他工具转存后丢失了时间解码信息的情况。每次写新的处理脚本,我都会保留一个简单的“数据体检”步骤:打印变量名、单位、坐标范围、时间范围、shape。基本能给后面的分析扫掉一半的坑。
6. 结合我实际踩过的坑,ERA5 使用中的避雷清单
6.1 降水量“累计值”让很多人白算半天
前面提到过,ERA5 单层数据里的参数total_precipitation是一个累积量。在这个数据集的设计里,每个时次的值代表从“数据起始时刻”以来的累积降水。如果你下载了某一天 00:00 到 23:00 的逐小时数据,每个时刻的降水其实是过去一小时内的降水累积量。
但这里有个容易搞错的变体:你如果直接对 24 个时次的 total_precipitation 求和,得到的是一天总降水吗?不对。因为既然每个时次的值已经是“从起始时刻以来的累积”,那直接求和就变成“第一天累积 + 第二天累积 + ……”,数值会越滚越大。正确的做法是把相邻两个时次相减:
precip_hourly = ds["tp"].diff(dim="time")得到的precip_hourly第一个时次是 NaN,因为 00:00 时刻无法做差。之后的时次就是每个小时内的降水量。温度、辐射、风速这类瞬时量没有这个问题,但对流量的处理一定要先弄清变量的累积属性。
而且单位上,ERA5 总降水量的原始单位是 m(米),换算成 mm 要乘以 1000。由于水密度和单位换算的关系,很多人在第一步就把量级做错了,得出的日降水量结果比站点观测大几十倍也是常有的事。
6.2 与站点观测对比时,别拿网格点值直接当真值
再分析数据和站点观测之间的差异,严格说是“网格平均值”和“站点点值”的差异,不是单纯测量误差。地形复杂的地区这种差异尤其明显,比如山区站点可能在海拔 1500 米,而 ERA5 的网格点地表高度设置可能只有 900 米,两者之间的气温差异有一两度甚至更多很正常。
我建议的做法是:先做了“地形偏差校正”再做对比。ERA5 提供geopotential变量,能算出一个网格的地表高度权重,再用标准大气直减率(如 6.5 K/km)粗略折算到站点高程。很多做风资源评估的同事还会用测风塔和 ERA5 风速的长期逐时对比,构造一个订正系数,目的都是消除网格与单点之间的系统性偏差。
不要拿着 ERA5 的数据和观测值的差异来证明 ERA5 数据不可用,也不要在没有偏差分析的情况下直接拿 ERA5 数据代替观测数据。它的价值在于空间连续、时间一致,而不在于对每一个局地点都有完全保真的能力。
6.3 内存溢出与文件组织的最佳实践
ERA5 的 NetCDF 文件如果范围是全球、变量多、时间跨度大,很容易一个文件十几个 GB。用 xarray 打开时会自动惰性加载,展示出来的数据对象看起来很小,但一旦你执行ds["t2m"].mean(dim="time")或者.values这类操作,数据就会被全部读入内存,导致内存溢出。
优化思路有两条。第一条是下载时就缩小范围。在 CDS API 的请求里加上area参数,只下载你研究区域的经纬度范围,这种做法能在源头把数据量减少一个数量级。第二条是使用 chunked lazy 计算,即把数据切块:
ds = xr.open_dataset("era5_large.nc", chunks={"time": 24}) t2m_mean = ds["t2m"].mean(dim="time").compute()用chunks参数让 xarray 以 Dask 数组的形式按块处理数据,这样就算单文件很大,也能避免一次性把全部数据塞进内存。
另外,建议把原始下载文件、中间处理文件和最终结果文件分别放在不同目录,每次处理完不要覆盖原始文件。因为 ERA5 的版本会更新,如果你只保留处理后的文件,后续别人需要某个变量的原始值时,你往往需要重新下载,那时候数据版本可能已经变了,处理结果也不可复现。
6.4 版本更新带来的“隐性差异”
ERA5 不是一个永不变动的静态数据集。ECMWF 每隔一段时间会用改进的同化系统或新增的观测资料对整个历史时段进行重新处理,这意味着同一时间段、同一变量,你在不同时间下载得到的数值可能微妙不同。CDS 平台上的数据版本标识通常体现在数据集名称和产品说明里。
这种差异对于绝大多数研究来说可以忽略,但对基准数据集、模型评估和跨时间对比的影响需要留意。如果项目周期较长,比如跨好几年,尽量在项目开始时把所有需要的数据一次性下载完整并留存备份,后续整个项目统一使用同一版本的数据,避免中间混入新版数据造成不一致。
7. 最后说一点我自己的使用习惯
做 ERA5 数据处理这几年,我最大的感触是:这套数据的门槛不在数据本身,而在于对气象变量物理含义的理解程度。很多人卡在下载和格式读取阶段,实际上只要按照我上面写的方式配置好 CDS API,选好变量和时间范围,再用 NetCDF 格式读取,后面就顺畅很多了。
我的个人习惯是维护一张变量速查表,把用到的每个变量的变量名、单位、累积属性、分层方式都记下来。因为 ERA5 变量太多,记忆负担太重,而且每次官方更新文档时也会调整某些描述,有一张自己的速查表会省掉大量翻文档的时间。平时写脚本时,也建议把数据文件命名完整,比如era5_t2m_2020_06_area_sw.nc,一眼就能知道这个文件的内容范围,避免半年之后看到一堆data1.nc、data2.nc完全不知道谁是谁。
ERA5 的优势在于它是目前公开数据中空间覆盖、时间跨度和变量完整度都很均衡的一套选择,短到一周的天气过程分析,长到几十年的气候变化研究,都能支撑起来。把这套数据的下载、读取和变量语义摸透,后续很多衍生数据集(比如各种站点插值产品、驱动数据)用起来也会顺手很多。希望这篇文章能帮你少走我走过的弯路。