使用 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)
的完整数组大小。以前,number
、step
和 surface
是标量(不是数组 - 只是单个值),而 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 讨论压缩选项的默认设置。
我正在研究 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)
的完整数组大小。以前,number
、step
和 surface
是标量(不是数组 - 只是单个值),而 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 讨论压缩选项的默认设置。