xarray 生成的没有编码的 Zarr 文件如何使用比其实际数据大小更少的磁盘空间?

问题描述 投票:0回答:1

我一直在对如何使用 netCDF 或 Zarr 文件格式以及任一文件格式提供的所有不同编码选项使用 xarray 存储 N 维数组进行基准测试。 Zarr 在我的数据和系统上似乎总体上优于 netCDF,但我发现生成的文件有一些令人惊讶的地方。

下面的 MWE 生成 16793600 字节的

xarray.Dataset

import numpy as np
import xarray as xr
import zarr

# Versions (Python 3.11.6)
print(np.__version__)   # 1.26.0
print(xr.__version__)   # 2023.10.1
print(zarr.__version__) # 2.16.1

rng = np.random.default_rng(0)

t = 10
ds = xr.Dataset(
    data_vars=dict(
        A=(["y", "x"], rng.normal(size=(2**t,2**t))),
        B=(["y", "x"], rng.normal(size=(2**t,2**t))),
    ),
    coords=dict(
        x=(["x"], np.linspace(0, 1, 2**t)),
        y=(["y"], np.linspace(0, 1, 2**t)),
    ),
)
print(f'{ds.nbytes}') # 16793600

# To netCDF, using different engines
ds.to_netcdf('file1.nc', engine='netcdf4', encoding=None)
ds.to_netcdf('file2.nc', engine='scipy', encoding=None)
ds.to_netcdf('file3.nc', engine='h5netcdf', encoding=None)

# To Zarr
ds.to_zarr('file.zarr', encoding=None)

但是生成的文件是

$ du -bs file*
16801792        file1.nc
16793952        file2.nc
16801792        file3.nc
16017234        file.zarr

也就是说,Zarr 文件更小,存储时减少了近 800 kB。编码设置为

None
,我将其理解为“不使用压缩”。这看起来差异很小,但我正在使用 38 GB
xarray.Dataset
。使用相同的方法,其中
encoding=None
,netCDF 使用
netcdf4
h5netcdf
引擎得到 38 GB(
scipy
由于某种原因失败),而 Zarrs 只有 16 GB,一半!

如果没有指定编码,这怎么可能? Zarr(或 xarray)在做什么?如果使用任何压缩,我可以避免它吗?我注意到保存和读取这些大型 Zarr 文件,虽然花费的时间更少,但它们比 netCDF 对应文件使用更多的内存。

python python-xarray zarr
1个回答
0
投票

保存后,您应该仔细检查 netcdf4 和 zarr 数据的编码。

ncdump -hs
将显示netcdf编码,您可以直接打开zarr数组元数据JSON文件。根据您的描述,我怀疑这两种格式都使用了一些默认压缩。

如果您想强制 Zarr 忽略其默认压缩,您需要为每个数组设置

compressor
编码参数
None

store = {}
ds.to_zarr(store, encoding={"A": {"compressor": None}, "B": {"compressor": None}})
json.loads(store['A/.zarray'])

# yields
{'chunks': [256, 256],
 'compressor': None,
 'dtype': '<f8',
 'fill_value': 'NaN',
 'filters': None,
 'order': 'C',
 'shape': [1024, 1024],
 'zarr_format': 2}'
© www.soinside.com 2019 - 2024. All rights reserved.