为什么无编码的xarray生成的Zarr文件占用的磁盘空间比实际数据大小小?

0 投票
1 回答
52 浏览
提问于 2025-04-14 17:02

我一直在测试用xarray存储N维数组,看看用netCDF格式还是Zarr格式更好,同时也在研究这两种格式提供的各种编码选项。根据我的数据和系统,Zarr的表现通常比netCDF要好,但我发现生成的文件有些出乎意料。

下面这个简单的例子生成了一个xarray.Dataset,大小是16793600字节。

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千字节。并且编码设置为None,我理解为“没有压缩”。这看起来差别不大,但我处理的是38 GB的xarray.Dataset。用同样的方法,设置encoding=None,netCDF文件的大小是38 GB,使用netcdf4h5netcdf引擎(scipy出于某种原因无法使用),而Zarr文件的大小只有16 GB,只有一半!

这怎么可能呢?如果没有指定编码,Zarr(或xarray)到底在做什么?如果它使用了某种压缩,我能避免吗?我注意到保存和读取这些大的Zarr文件时,虽然所需时间更少,但它们占用的内存却比netCDF文件要多。

1 个回答

1

你应该在保存完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}'

撰写回答