微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

沿维度操作而不在 Xarray 上的 dask 数组中写回数据

如何解决沿维度操作而不在 Xarray 上的 dask 数组中写回数据

我有一个具有 3 个维度(“时间”、“x”和“y”)的数据集。我想沿时间维度应用此函数 foo

def foo(arr):
    lo,hi = np.percentile(arr,(1,99))
    arr = np.clip(arr,lo,hi)
    arr = (arr - lo) / (hi - lo)
    return arr

基本上,我想用 foo 之类的函数在时间维度上缩放每个“图像”

在 numpy 中,我可以这样做:

for i in range(data.shape[0]):
   data[i] = foo(data[i])

但由于数据存储在 dask 数组中,我无法写回修改后的数据。我遇到了这个错误

TypeError: this variable's data is stored in a dask array,which does not support item assignment. To assign to this variable,you must first load it into memory explicitly using the .load() method or accessing its .values attribute.

如何在 xarray/dask 中执行此操作?

解决方法

不需要在时间维度上循环,你可以用矢量化的方式来做到这一点:

da = xr.tutorial.open_dataset(
    "air_temperature",chunks={"lat": -1,"lon": -1,"time": 10}
)["air"]


def scale_image(da,quantiles):
    quantiles = da.quantile(quantiles,dim=("lat","lon"))
    lower = quantiles.isel(quantile=0,drop=True)
    upper = quantiles.isel(quantile=1,drop=True)
    clipped = xr.apply_ufunc(np.clip,da,lower,upper,dask="allowed")
    return (clipped - lower) / (upper - lower)


scaled = scale_image(da,quantiles=[0.01,0.99])

这样就没有必要将整个数组加载到内存中。

我意识到您也可以将 xarray 的 apply_ufunc 直接与 foo 函数一起使用,如果您向 axis 提供 np.percentile 参数并负责制作数组形状一致。 看来,percentile 函数的 dask 版本没有为多维数组实现,但是您可以使用 parallelizedapply_ufunc 选项使其与 numpy 函数一起使用:

def foo(arr):
    lo,hi = np.percentile(arr,(1,99),axis=[1,2])
    arr = np.clip(arr,lo[:,None,None],hi[:,None])
    return (arr - lo[:,None]) / (hi[:,None] - lo[:,None])

scaled2 = xr.apply_ufunc(foo,dask="parallelized")

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。