Python中float64型3D数组Upscaling解决方案问询(含NaN处理)
基于xarray的3D气象数组降分辨率解决方案(Windows环境)
核心结论
完全可以通过xarray实现,无需遍历第三维度,利用groupby_bins完成非整数倍的空间分箱平均,同时自动保留NaN掩码(陆面网格)。
具体实现步骤
1. 将原始数组包装为xarray DataArray
先为原始数组添加经纬度、月度维度的坐标信息,让xarray识别空间维度:
import xarray as xr import numpy as np # 构造原始数据的坐标 lat_original = np.linspace(30.1875, 45.9792, 380) lon_original = np.linspace(-6, 36.2917, 1016) month_dim = np.arange(396) # 396个月度数据 # 包装为xarray DataArray da = xr.DataArray( A, # 你的原始float64数组 dims=["month", "lat", "lon"], coords={ "month": month_dim, "lat": lat_original, "lon": lon_original } )
2. 裁剪原始数据到目标范围(可选但推荐)
目标网格的经纬度范围与原始数据略有差异,先裁剪掉超出目标范围的原始网格点,避免无效计算:
# 目标范围 target_lat_range = (30.0626, 45.9375) target_lon_range = (-5.9375, 36.9375) # 裁剪数据 da_clipped = da.sel( lat=slice(*target_lat_range), lon=slice(*target_lon_range) )
3. 定义目标网格的分箱规则
根据目标分辨率0.125°生成经纬度分箱边界,同时计算分箱中心作为新坐标:
# 纬度分箱:边界 + 中心坐标 lat_bins = np.arange(target_lat_range[0], target_lat_range[1] + 0.125, 0.125) lat_new = (lat_bins[:-1] + lat_bins[1:]) / 2 # 分箱中心作为新纬度坐标 # 经度分箱:边界 + 中心坐标 lon_bins = np.arange(target_lon_range[0], target_lon_range[1] + 0.125, 0.125) lon_new = (lon_bins[:-1] + lon_bins[1:]) / 2 # 分箱中心作为新经度坐标
4. 执行空间分箱平均
通过两次groupby_bins完成纬度、经度的降分辨率平均,自动处理所有月度数据:
# 先对纬度分箱平均,再对经度分箱平均 da_coarse = da_clipped.groupby_bins( "lat", lat_bins, labels=lat_new ).mean(dim="lat").groupby_bins( "lon", lon_bins, labels=lon_new ).mean(dim="lon")
5. 转换为numpy数组(得到目标数组B)
B = da_coarse.values # 检查形状:应为(396, 128, 344),符合要求
关键细节说明
- NaN处理:
mean方法默认skipna=True,会自动忽略NaN计算有效数值的平均;如果某个目标网格内的原始点全为NaN,结果会保留NaN,完美匹配陆面掩码需求。若需将NaN当作0参与平均,只需设置skipna=False。 - 效率优势:xarray的操作是向量化的,无需手动遍历月度维度,计算效率远高于循环遍历。
- 坐标匹配:使用分箱中心作为新坐标,确保目标网格的位置准确对应0.125°分辨率的网格中心。
内容的提问来源于stack exchange,提问作者Guybrush
相关产品推荐
相关产品推荐

