下采样地理空间阵列太大,内存不足



我有一个非常大的(86400x43200(xarray数据集,具有地理空间坐标(lat,lon(和高程,我想缩小此地图的尺寸,使其每维度的分辨率为二十分之一(43202160,相当于1/12度(。

起初我直接使用interp方法,但它试图加载整个数据集,因此请求28GB的内存,而我无法分配。

下面详细介绍的当前方法:

  1. 创建新的下采样数据集并填充0s
  2. 将大型数据集分割为36个相等的切片
  3. 加载并插值一个切片
  4. 将下采样切片添加到我的下采样数据集中

->获取所有nan值。第2步有效,只有第3步无效。如何对如此大的数据集进行下采样或以正确的方式填充新数据集?

import xarray as xr
def format_spatial_resolution(
xarray, res_lat=1 / 12, res_lon=1 / 12, sample_array=None
):
new_lon = np.arange(xarray.lon[0], xarray.lon[-1], res_lon)
new_lat = np.arange(xarray.lat[0], xarray.lat[-1], res_lat)
xarray_new = xarray.interp(
lat=new_lat,
lon=new_lon,
# Extrapolate to avoid nan values as edges
kwargs={
"fill_value": "extrapolate",
},
)
return xarray_new

xarray = xr.open_dataset(filename)
# Setting resolution
res_lat = 1/12 # 1/12 degree
res_lon = 1/12
# Create a downsampled xarray with zero values
new_lon = np.arange(xarray.lon[0], xarray.lon[-1], res_lon)
new_lat = np.arange(xarray.lat[0], xarray.lat[-1], res_lat)
xarray_downsampled = xr.Dataset(
dict(elevation=(["lat", "lon"], np.zeros((len(new_lat), len(new_lon))))),
coords=dict(lon=new_lon, lat=new_lat),
)
# Interpolate each slice and update downsampled xarray
for i in range(-180, 180, 10):
xarray_downsampled.update(format_spatial_resolution(xarray.sel(lon=slice(i, i + 10))))

我建议将dask与xr.DataArray.coarsen结合使用。

首先,在读取时使用分块方案将数据分块为粗化窗口的倍数(因此每个调光时为20的倍数(,目标是低100 MB的块大小。(8640 x 4320(float64数据块为285MB,如果转换为float32,则会减少到142MB,这是一个合理的大小。这些都是总数据集的1/10,所以我们总共有100个块:

ds = xr.open_dataset(filename, chunks={"lat": 8640, "lon": 4320})

可选地,我们可以降低精度:

ds["elevation"] = ds["elevation"].astype("float32")

最后,让我们用粗糙度降低像素密度:

coarsened = ds.coarsen(lat=20, lon=20, boundary='exact').mean()

结果是一个基于dask的数组;作业尚未执行。为了触发计算,我们可以将文件写入磁盘,也可以使用在内存中计算结果

coarsened = coarsened.compute()

最新更新