为什么无编码的xarray生成的Zarr文件占用的磁盘空间比实际数据大小小?
我一直在测试用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,使用netcdf4
或h5netcdf
引擎(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}'