xarray.Dataset.to_zarr: sobreescribir datos si existe con append_dim

Con Rayos.Dataset.to_zarr es posible escribir una radiografía a .zarr archivo y apéndice nuevos datos a lo largo de una dimensión utilizando append_dim Parámetro.

Sin embargo, si la coordinación de los nuevos datos para esta dimensión ya está allí, los datos existentes no serán reemplazados. Más bien la misma coordenadas aparece dos veces en la fecha resultante.

Ejemplo utilizando los datos de Aquí.:

Aquí escribo 2 Datasets al mismo archivo .zarr. Los conjuntos de datos se adjuntan a lo largo de los space dimensión. Ambos conjuntos de datos contienen la misma coordinación espacial "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");

Al leer el archivo, el segundo conjunto de datos no sobrescribía los datos para el "IL" Coordenada, pero anhelada una nueva:

xr.open_zarr("weather.zarr")



Dimensions:       (space: 4, time: 4)
Coordinates:
  * space         (space) 

Este sería el resultado deseado:


Dimensions:       (space: 3, time: 4)
Coordinates:
  * space         (space) 

¿Alguien sabe si es posible reemplazar los datos si la coordinación ya existe?

Pregunta hecha hace 3 años, 4 meses, 28 días - Por debugdragon


3 Respuestas:

  • No creo que haya una forma fuera de la caja de hacer esto, pendiente siempre añade el conjunto de datos completo al final.

    Sin embargo, versión 0.16.2 de xarray introdujo la palabra clave region a to_zarr, que le permite escribir a región limitada de un zarr archivo.

    Puede utilizarlo, para sobreescribir los datos existentes:

    # 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/')
    
    
    Dimensions:       (space: 3, time: 4)
    Coordinates:
      * space         (space) 
    
    

    Respondida el Dec 17, 2020 a las 11:34 - por gitguru

    Votos positivos: 0 | Votos negativos: 0

  • En el ejemplo que proporcionaste, el problema está ocurriendo porque al usar append_dim al escribir el segundo Dataset, no se está reemplazando la coordenada "IL" existente, sino que se está añadiendo una nueva coordenada "IL" al Dataset resultante.

    Para reemplazar los datos si la coordenada ya existe, puedes utilizar un enfoque diferente. En lugar de usar append_dim, puedes cargar el archivo .zarr, verificar si la coordenada ya existe y luego decidir si deseas sobrescribir los datos o no. Aquí tienes un ejemplo de cómo podrías hacerlo:

    python
    import xarray as xr
    
    

    Crear los Datasets como en el ejemplo

    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")

    Cargar el archivo .zarr existente

    ds_existing = xr.open_zarr("weather.zarr")

    Verificar si la coordenada "IL" ya existe

    if "IL" in ds_existing.space:

    Reemplazar los datos existentes con los nuevos datos

    ds_existing.loc[{"space": "IL"}] = ds_B.loc[{"space": "IL"}] else:

    Crear una nueva coordenada "IL" con los nuevos datos

    ds_existing = xr.concat([ds_existing, ds_B], dim="space")

    Guardar el Dataset resultante en el archivo .zarr

    ds_existing.to_zarr("weather.zarr")

    En este enfoque, cargamos el Dataset existente, verificamos si la coordenada "IL" ya existe y en función de eso, decidimos si reemplazar los datos existentes o agregar una nueva coordenada. Finalmente, guardamos el Dataset resultante en el archivo .zarr. ¡Espero que esta solución te sea de ayuda!

    Respondida el Dec 18, 2020 a las 11:34 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Sí, es posible reemplazar los datos si la coordenada ya existe utilizando el parámetro mode='w'. Este parámetro especifica el modo de escritura y está configurado en 'a' de forma predeterminada, lo que adjunta nuevos datos a lo largo de la dimensión especificada.

    Al establecer mode='w', sobrescribirá cualquier dato existente con la misma coordenada en la dimensión especificada.

    Aquí tienes un ejemplo modificado de tu código que sobrescribirá los datos para la coordenada IL:

    
    import xarray as xr
    
    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", mode='w')
    ds_B.to_zarr("weather.zarr", append_dim="space", mode='w')
    

    Al abrir el archivo resultante, verás que los datos para la coordenada IL han sido sobrescritos por los datos de ds_B:

    
    xr.open_zarr("weather.zarr")
    
    
    Dimensions:       (space: 3, time: 4)
    Coordinates:
       space         (space) ="" ...="" 2),="" 2000-01-01="" 2000-01-02="" 2000-01-04="" dask.array
    
    

    Respondida el Dec 18, 2020 a las 11:39 - por Gemini

    Votos positivos: 0 | Votos negativos: 0