ERA5是欧洲中期天气预报中心(ECMWF)发布的第五代全球大气再分析数据,广泛应用于气象、气候研究和数值天气预报。ERA5数据通常为多维数组(时间、经度、纬度、高度层等),且数据量大、维度复杂。利用xarray库的apply_ufunc函数,可以在保证数据标签(坐标、属性)完整性的同时,高效实现针对气象数据的批量计算(如空间平均、时间序列提取、物理量转换等)。本文以ERA5数据为例,介绍apply_ufunc的核心应用场景和实现方法。
xarray.apply_ufunc的核心功能xarray.apply_ufunc是对NumPy通用函数(ufunc)的扩展,支持有标签的多维数组(如DataArray和Dataset),并自动处理以下任务:
它适用于复杂的批量计算场景,尤其在处理ERA5这类多维、高分辨率数据时,避免了手动编写循环的繁琐过程。
目标:将日平均温度数据(时间×纬度×经度)沿纬度、经度维度平均,生成时间序列。
import xarray as xr
import numpy as np
# 加载ERA5数据
ds = xr.open_dataset("/home/mw/input/era58091/ERA5-2023-08_pl.nc")
temperature = ds["t"] #
temperature

image
# 定义空间平均函数 (沿纬度和经度平均))
def spatial_mean(data):
return np.mean(data, axis=(-2, -1)) # 最后一维是经度,倒数第二维是纬度
# 应用函数
temperature_global_mean = xr.apply_ufunc(
spatial_mean,
temperature,
input_core_dims=[["latitude", "longitude"]], # 核心维度为lat和lon,其余维度自动广播
output_core_dims=[[]], # 输出无核心维度(转换为时间序列)
keep_attrs=True, # 保留属性(如单位)
)
print(temperature_global_mean)
# 输出:<xarray.DataArray (time: 365)> 单位:K

image
目标: 根据水平风速分量 (东风)和 (北风),计算各高度层、各时次的相对涡度 。
其简化的直角坐标系公式为:
import xarray as xr
import numpy as np
# 1. 定义核心计算函数 (基于 NumPy)
def calculate_vorticity(u, v, dx, dy):
"""
使用中心差分计算涡度
dx, dy 可以是标量(简化情况)或与网格对应的数组
"""
# np.gradient 返回数组梯度:dv/dx - du/dy
dv_dx = np.gradient(v, axis=-1) / dx
du_dy = np.gradient(u, axis=-2) / dy
return dv_dx - du_dy
# 2. 准备参数
# 实际操作中,dx 和 dy 随纬度变化,这里为演示方便假设固定值(约 0.25度 对应的距离)
dx = 25000.0
dy = 25000.0
# 3. 应用 apply_ufunc
vorticity = xr.apply_ufunc(
calculate_vorticity,
ds["u"], ds["v"],
dx, dy,
input_core_dims=[["latitude", "longitude"], ["latitude", "longitude"], [], []],
output_core_dims=[["latitude", "longitude"]],
vectorize=True, # 如果函数不支持向量化,开启此项
dask="parallelized", # 如果数据是 dask 数组,支持并行
output_dtypes=[float]
)
# 4. 赋值属性并查看结果
vorticity.attrs = {"units": "s^-1", "long_name": "relative_vorticity"}
print(vorticity)

image
目标:对4小时间隔气温数据计算12小时滑动平均。
from scipy.ndimage import uniform_filter1d
# 滑动平均函数
def rolling_mean(data, window_size):
return uniform_filter1d(data, window_size, axis=0, mode="nearest")
# 应用函数
temperature_30d_mean = xr.apply_ufunc(
rolling_mean,
temperature,
input_core_dims=[["time"]], # 核心维度为时间
output_core_dims=[["time"]],
kwargs={"window_size": 3}, # 窗口
dask="parallelized", # 并行加速
output_dtypes=[float], # 指定输出数据类型
keep_attrs=True,
)
temperature_30d_mean

image
input_core_dims与output_core_dimsinput_core_dims=[[], ["lat"], ["time"]]表示不同输入变量参与维度广播的规则。dask参数的并行加速dask="parallelized"或dask="allowed"结合dask_gufunc_kwargs,可实现GPU加速或分布式计算。vectorize=True的慎用vectorize=True会自动调用np.vectorize,但性能较低;推荐预先将函数向量化。ValueError: Dimensions ('lon', 'lat') do not exist in data
解决:检查输入数据是否包含input_core_dims中指定的维度,使用ds.transpose()调整维度顺序。
解决:
ds = ds.chunk({"time": 100, "lon": 180})dask="parallelized"分布式计算。解决:设置keep_attrs="override",或手动指定属性:
result.attrs.update({"units": "K", "description": "Global mean temperature"})
xarray.apply_ufunc为ERA5类多维度气象数据的批量计算提供了灵活的接口。通过合理定义核心维度和参数设置,可实现复杂气象指标的高效计算,同时保持数据标签的完整性和可复现性。针对海量数据,结合Dask并行化计算工具,能显著提升处理效率。