如何在Python中对DataArray/栅格进行空间平均重采样以匹配另一DataArray的网格
当然可以!你提到的通过空间平均降低分辨率、匹配目标栅格/DataArray的空间网格的操作,完全属于**重采样(resampling)**的范畴——这个术语用得非常准确。下面我给你介绍几个常用工具的实现方法:
一、用xarray + rioxarray实现(推荐)
rioxarray是xarray的扩展,完美结合了rasterio的空间处理能力,最适合这种匹配目标网格的需求,步骤简单省心:
- 先安装依赖:
pip install xarray rioxarray rasterio
- 加载源数据和目标栅格/DataArray:
import rioxarray import xarray as xr # 加载高分辨率的源数据 src_da = rioxarray.open_rasterio("high_res_input.tif").squeeze() # 加载目标网格的参考数据 target_da = rioxarray.open_rasterio("target_grid.tif").squeeze()
- 调用
reproject_match方法,指定重采样方式为平均:
# 自动对齐坐标系、匹配目标网格,用空间平均聚合数据 matched_da = src_da.reproject_match(target_da, resampling=rasterio.enums.Resampling.average)
二、纯xarray实现(适合规则网格且分辨率为整数倍的情况)
如果你的源数据和目标数据都是规则经纬网格,且目标分辨率是源分辨率的整数倍(比如源是0.1°,目标是0.5°,刚好5倍),可以直接用xarray的coarsen方法做空间平均:
import xarray as xr # 加载高分辨率源数据 src_da = xr.open_dataset("high_res_data.nc")["variable"] # 按5个格点聚合(对应5倍分辨率降低),取平均 coarsened_da = src_da.coarsen(lat=5, lon=5, boundary="trim").mean()
如果目标网格不是整数倍的规则网格,还可以用groupby_bins分组后取平均:
# 提取目标网格的坐标边界 target_lat_bins = target_da.lat.values target_lon_bins = target_da.lon.values # 按目标网格的区间分组并计算平均 matched_da = src_da.groupby_bins("lat", target_lat_bins, labels=target_da.lat.values[:-1]).mean() matched_da = matched_da.groupby_bins("lon", target_lon_bins, labels=target_da.lon.values[:-1]).mean() # 重命名维度,和目标保持一致 matched_da = matched_da.rename({"lat_bins": "lat", "lon_bins": "lon"})
三、用rasterio实现(底层控制场景)
如果你需要更底层的空间处理控制,可以直接用rasterio的API:
import rasterio from rasterio.enums import Resampling from rasterio.warp import calculate_default_transform, reproject # 打开源和目标栅格文件 with rasterio.open("high_res_input.tif") as src: with rasterio.open("target_grid.tif") as target: # 复制目标栅格的元信息并更新转换参数 target_meta = target.meta.copy() transform, width, height = calculate_default_transform( src.crs, target.crs, src.width, src.height, *src.bounds ) target_meta.update({ "transform": transform, "width": target.width, "height": target.height, "crs": target.crs }) # 执行重采样并保存结果 with rasterio.open("matched_output.tif", "w", **target_meta) as dst: for i in range(1, src.count + 1): reproject( source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.transform, src_crs=src.crs, dst_transform=target.transform, dst_crs=target.crs, resampling=Resampling.average )
总结
- 快速对齐任意空间网格:优先选rioxarray的
reproject_match,最省心; - 规则整数倍分辨率降低:用纯xarray的
coarsen足够高效; - 需要底层空间控制:直接用rasterio的API实现。
内容的提问来源于stack exchange,提问作者marcgm




