xarray.Dataset.to_zarr: перезаписать данные, если они существуют, с помощью append_dim

#python #dask #python-xarray #zarr

#python #dask #python-xarray #zarr

Вопрос:

С помощью xarray.Dataset.to_zarr можно записать xarray в .zarr файл и добавить новые данные вдоль измерения, используя append_dim параметр.

Однако, если координата новых данных для этого измерения уже существует, существующие данные не будут заменены. Скорее одна и та же координата появляется дважды в результирующем наборе данных.

Пример использования данных отсюда:

Здесь я записываю 2 набора данных в один и тот же файл .zarr. Наборы данных добавляются вдоль space измерения. Оба набора данных содержат одну и ту же пространственную координату "IL"

 ds_A = xr.DataArray(
    np.random.rand(4, 2),
    [
        ("time", pd.date_range("2000-01-01", periods=4)),
        ("space", ["IA", "IL"]),
    ],
).to_dataset(name="measurements")


ds_B = xr.DataArray(
    np.random.rand(4, 2),
    [
        ("time", pd.date_range("2000-01-01", periods=4)),
        ("space", ["IL", "NY"]),
    ],
).to_dataset(name="measurements")


ds_A.to_zarr("weather.zarr", append_dim="space")
ds_B.to_zarr("weather.zarr", append_dim="space");
 

При чтении файла второй набор данных не перезаписывал данные для "IL" координаты, а создавал новую:

 xr.open_zarr("weather.zarr")


<xarray.Dataset>
Dimensions:       (space: 4, time: 4)
Coordinates:
  * space         (space) <U2 'IA' 'IL' 'IL' 'NY'
  * time          (time) datetime64[ns] 2000-01-01 2000-01-02 ... 2000-01-04
Data variables:
    measurements  (time, space) float64 dask.array<chunksize=(4, 2), meta=np.ndarray>
 

Это было бы желаемым результатом:

 <xarray.Dataset>
Dimensions:       (space: 3, time: 4)
Coordinates:
  * space         (space) <U2 'IA'  'IL' 'NY'
  * time          (time) datetime64[ns] 2000-01-01 2000-01-02 ... 2000-01-04
Data variables:
    measurements  (time, space) float64 dask.array<chunksize=(3, 2), meta=np.ndarray>
 

Кто-нибудь знает, можно ли заменить данные, если координата уже существует?

Ответ №1:

Я не думаю, что есть готовый способ сделать это, добавление всегда добавляет полный набор данных в конец.

Однако в версии 0.16.2 xarray введено ключевое region слово to to_zarr , которое позволяет записывать в ограниченную область zarr файла.

Вы можете использовать его для перезаписи существующих данных:

 # write first dataset
ds_A.to_zarr("weather.zarr")

# read structure of dataset to see what's on disk
ds_ondisk = xr.open_zarr('weather.zarr/')

# get index of first new datapoint
start_ix, = np.nonzero(~np.isin(ds_B.space, ds_ondisk.space))

# region of new data
region_new = slice(start_ix[0], ds_B.space.size)

# append structure of new data (compute=False means no data is written)
ds_B.isel(space=region_new).to_zarr("weather.zarr", append_dim='space', compute=False)

# get updated dataset size and create slice
ds_ondisk = xr.open_zarr('weather.zarr/')
region_update = slice(start_ix[0], ds_ondisk.space.size)

# write new data to zarr (time needs to be dropped)
ds_B.drop("time").to_zarr("weather.zarr", region={"space": region_update})

# produces
xr.open_zarr('weather.zarr/')

<xarray.Dataset>
Dimensions:       (space: 3, time: 4)
Coordinates:
  * space         (space) <U2 'IA' 'IL' 'NY'
  * time          (time) datetime64[ns] 2000-01-01 2000-01-02 ... 2000-01-04
Data variables:
    measurements  (time, space) float64 dask.array<chunksize=(4, 2), meta=np.ndarray>