xarray coarsen粗化操作中如何实现高斯加权平均计算
实现方案
不需要修改coarsen内置的均值计算逻辑,直接利用xarray coarsen提供的块重构接口即可实现块内高斯加权平均,这是内存效率最高、逻辑最清晰的原生实现方式。
核心实现代码
import numpy as np import xarray as xr import scipy.stats as st # 原始DataArray da = xr.DataArray( data=np.random.random((25,25)), dims=["x", "y"], coords=dict( x=np.arange(25), y=np.arange(25), ), ) # 高斯核生成函数 def gkern(kernlen=21, sig=3): """Returns a 2D Gaussian kernel.""" x = np.linspace(-(kernlen/2)/sig, (kernlen/2)/sig, kernlen+1) kern1d = np.diff(st.norm.cdf(x)) kern2d = np.outer(kern1d, kern1d) return kern2d/kern2d.sum() window = gkern(5) # 将权重核转为xarray对象,指定块内维度名用于广播匹配 window_xr = xr.DataArray(window, dims=["x_win", "y_win"]) # 加权粗化核心逻辑 da_weighted_coarse = ( da .coarsen(x=5, y=5) # 将每个非重叠5x5块拆分为「块索引维度+块内相对位置维度」 .construct(x=("x", "x_win"), y=("y", "y_win")) # 广播相乘后对块内维度求和,直接得到加权平均结果 * window_xr ).sum(dim=["x_win", "y_win"])
逻辑说明
.construct(x=("x", "x_win"), y=("y", "y_win"))会把原25x25的数组重构为维度为(x:5, x_win:5, y:5, y_win:5)的数组:其中x、y是降采样后5x5结果的坐标,x_win、y_win对应每个块内5个点的相对位置,和生成的5x5高斯核维度完全对齐,不会出现权重错位。- 上述代码生成的高斯核已经做了总和为1的归一化,因此块内逐元素乘权重后对块内维度求和,结果就是高斯加权平均值。如果使用未归一化的权重,最后除以权重总和即可:
.sum(dim=["x_win", "y_win"]) / window_xr.sum()。
方案优势
- 不需要提前把权重平铺为和原数组同等尺寸的数组,内存占用更低,处理大尺寸数组时优势明显。
- 完全基于xarray原生接口实现,不会丢失原始坐标信息,也不需要编写额外的自定义归约函数。
- 逻辑可验证:如果把
window替换为全1值且除以25的均匀核,得到的结果和da.coarsen(x=5,y=5).mean()的算术平均结果完全一致。
内容的提问来源于stack exchange,提问作者hm8
相关产品推荐
相关产品推荐

