如何使用xarray open_mfdataset和分位数函数降低RAM使用率



我正试图在nc文件中加载多年的日常数据(每年一个nc文件(。单个nc文件的维度为365(天(*720(纬度(*1440(经度(。所有的nc文件都在";数据";文件夹

import xarray as xr
ds = xr.open_mfdataset('data/*.nc',
chunks={'latitude': 10, 'longitude': 10})
# I need the following line (time: -1) in order to do quantile, or it throws a ValueError:
# ValueError: dimension time on 0th function argument to apply_ufunc with dask='parallelized'
# consists of multiple chunks, but is also a core dimension. To fix, either rechunk into a single
# dask array chunk along this dimension, i.e., ``.chunk(time: -1)``, or pass ``allow_rechunk=True``
# in ``dask_gufunc_kwargs`` but beware that this may significantly increase memory usage.
ds = ds.chunk({'time': -1})
# Perform the quantile "computation" (looks more like a reference to the computation, as it's fast
ds_qt = ds.quantile(0.975, dim="time")
# Verify the shape of the loaded ds
print(ds)
# This shows the expected "concatenation" of the nc files.
# Get a sample for a given location to test the algorithm
print(len(ds.sel(lon = 35.86,lat = 14.375, method='nearest')['variable'].values))
print(ds_qt.sel(lon = 35.86,lat = 14.375, method='nearest')['variable'].values)

结果是正确的。我的问题来自内存使用。我认为,通过执行open_mfdataset方法,在引擎盖下使用Dask,这个问题就会得到解决。然而,加载";只是";2年的nc文件使用大约8GB的虚拟RAM,使用10年的数据使用我的整个虚拟RAM(大约32GB(。

我是不是错过了一些东西,可以在一个dask数组中获得给定的百分比值(我需要30个nc文件(?显然,我必须将区块({‘time’:-1}(应用到数据集才能使用分位数函数,这是RAM节省失败的原因吗?

这可能会在未来对某人有所帮助,这是我正在实现的解决方案,尽管它没有优化。我基本上是根据地理位置将nc文件分解为切片,然后将其粘贴回一起以创建输出文件。

ds = xr.open_mfdataset('data/*.nc')
step = 10
min_lat = -90
max_lat = min_lat + step
output_ds = None
while max_lat <= 90:
cropped_ds = ds.sel(lat=slice(min_lat, max_lat))
cropped_ds = cropped_ds.chunk({'time': -1})
cropped_ds_quantile = cropped_ds.quantile(0.975, dim="time")
if not output_ds:
output_ds = cropped_ds_quantile
else:
output_ds = xr.merge([output_ds, cropped_ds_quantile])
min_lat += step
max_lat += step
output_ds.to_netcdf('output.nc')

这不是很好,但它将RAM的使用限制在可管理的水平。如果存在(可能(更清洁/更快的解决方案,我仍然持开放态度。

最新更新