使用 xarray 对 NetCDF 数据应用函数后文件大小显着增加 (x10)

Significant increase in file size (x10) after applying function on NetCDF data using xarray

我正在研究 ERA5 reanalysis data NetCDF 格式,我需要根据 U 和 V 分量计算风向。

我已经有一段 Python 代码可以使用 xarray 和 pandas 执行此操作,并将输出保存为 NetCDF。

虽然我没有添加任何额外数据(仅应用转换来计算新变量而不是 U 和 V),但输出文件的大小却大大增加了。 输入文件约为 30 Mo,输出文件约为 300 Mo。

谁能解释一下这是怎么回事?我的输出文件的形状一定有问题,但我不知道如何。是由于文件的编码、使用的数据类型(此处的输入和输出均为 float32)还是任何其他 NetCDF 格式问题?

此外,您是否知道如何优化输出文件的大小?

为了帮助您理解差异,这里是输入文件的摘要:

<xarray.Dataset>
Dimensions:     (latitude: 7, longitude: 8, time: 113952)
Coordinates:
    number      int64 ...
  * time        (time) datetime64[ns] 1979-01-01 ... 1991-12-31T23:00:00
    step        timedelta64[ns] ...
    surface     float64 ...
  * latitude    (latitude) float64 47.5 47.25 47.0 46.75 46.5 46.25 46.0
  * longitude   (longitude) float64 -3.0 -2.75 -2.5 -2.25 -2.0 -1.75 -1.5 -1.25
    valid_time  (time) datetime64[ns] ...
Data variables:
    u10         (time, latitude, longitude) float32 ...
Attributes:
    GRIB_edition:            1
    GRIB_centre:             ecmf
    GRIB_centreDescription:  European Centre for Medium-Range Weather Forecasts
    GRIB_subCentre:          0
    Conventions:             CF-1.7
    institution:             European Centre for Medium-Range Weather Forecasts
    history:                 2022-05-04T13:10 GRIB to CDM+CF via cfgrib-0.9.9...

输出一个:

<xarray.Dataset>
Dimensions:     (latitude: 7, longitude: 8, time: 113952)
Coordinates:
  * time        (time) datetime64[ns] 1979-01-01 ... 1991-12-31T23:00:00
  * latitude    (latitude) float64 46.0 46.25 46.5 46.75 47.0 47.25 47.5
  * longitude   (longitude) float64 -3.0 -2.75 -2.5 -2.25 -2.0 -1.75 -1.5 -1.25
Data variables:
    number      (time, latitude, longitude) int64 0 0 0 0 0 0 0 ... 0 0 0 0 0 0
    step        (time, latitude, longitude) timedelta64[ns] 00:00:00 ... 00:0...
    surface     (time, latitude, longitude) float64 0.0 0.0 0.0 ... 0.0 0.0 0.0
    valid_time  (time, latitude, longitude) datetime64[ns] 1979-01-01 ... 199...
    direction   (time, latitude, longitude) float32 17.76 26.89 ... 180.1 178.5

我能看到的唯一区别是一些原始坐标现在是数据变量。

最重要的是,您所有的变量现在都由 (time, latitude, longitude) 索引,因此将具有 (7 x 8 x 113952) 的完整数组大小。以前,numberstepsurface 是标量(不是数组 - 只是单个值),而 valid_time 仅由 time 索引。由于所有这些都是 64 位的,您的新数组现在实际上有 4 个新变量,每个变量的大小都是 u10 的两倍。因此,仅此一项就增加了 9 倍。

为确保不会发生这种情况,请尝试非常小心地只对 DataArrays 而不是数据集进行数学和重塑操作。 Xarray 在处理数据集时工作得非常好,但当您刚刚掌握它时,其行为并不总是直观的,像这样的自动广播是让您措手不及的事情之一。出于这个原因,我总是建议人们使用 DataArrays 进行工作,然后在写入之前创建一个数据集。有关此主题的更多信息,请参阅 Broadcasting by dimension name and Automatic Alignment 上的文档。

我还希望如果您从 ECMWF 获得此数据,则源数据可能会在磁盘上压缩,这不是 ds.to_netcdf. See the docs on writing netCDFs 讨论压缩选项的默认设置。