从现有 NetCDF 文件创建新的 NetCDF,同时保留原始文件的压缩

Creating a new NetCDF from existing NetCDF file while preserving the compression of the original file

我正在尝试从现有的 NetCDF 文件创建一个新的 NetCDF 文件。我只对使用 177 个变量列表中的 12 个变量感兴趣。您可以从此 ftp 站点 here.

找到示例 NetCDF 文件

我使用了之前 SO 答案中的以下代码。你可以找到它 here.

import netCDF4 as nc

file1 = '/media/sf_jason2/cycle_001/JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc'
file2 = '/home/sandbox/test.nc'

toinclude = ['lat_20hz', 'lon_20hz', 'time_20hz', 'alt_20hz', 'ice_range_20hz_ku', 'ice_qual_flag_20hz_ku', 'model_dry_tropo_corr', 'model_wet_tropo_corr', 'iono_corr_gim_ku', 'solid_earth_tide', 'pole_tide', 'alt_state_flag_ku_band_status']

with nc.Dataset(file1) as src, nc.Dataset(file2, "w") as dst:
    # copy attributes
    for name in src.ncattrs():
        dst.setncattr(name, src.getncattr(name))
    # copy dimensions
    for name, dimension in src.dimensions.iteritems():
        dst.createDimension(
        name, (len(dimension) if not dimension.isunlimited else None))
    # copy all file data for variables that are included in the toinclude list
    for name, variable in src.variables.iteritems():
        if name in toinclude:
            x = dst.createVariable(name, variable.datatype, variable.dimensions)
            dst.variables[name][:] = src.variables[name][:]

我遇到的问题是原始文件只有 5.3 MB,但是当我将新变量复制到新文件大小时,新文件大小约为 17 MB。剥离变量的全部目的是减小文件大小,但我最终得到了更大的文件大小。

我也尝试过使用 xarray。但是当我尝试合并多个变量时遇到问题。以下是我尝试在 xarray 中实现的代码。

import xarray as xr

fName = '/media/sf_jason2/cycle_001/JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc'
file2 = '/home/sandbox/test.nc'
toinclude = ['lat_20hz', 'lon_20hz', 'time_20hz', 'alt_20hz', 'ice_range_20hz_ku', 'ice_qual_flag_20hz_ku', 'model_dry_tropo_corr', 'model_wet_tropo_corr', 'iono_corr_gim_ku', 'solid_earth_tide', 'pole_tide', 'alt_state_flag_ku_band_status']

ds = xr.open_dataset(fName)
newds = xr.Dataset()
newds['lat_20hz'] = ds['lat_20hz']
newds.to_netcdf(file2)

如果我尝试复制一个变量,Xarray 工作正常,但是,当我尝试将多个变量复制到一个空数据集时,它会出现问题。我找不到任何使用 xarray 复制多个变量的好例子。无论哪种方式,我都可以很好地实现这个工作流程。

最后,如何减小使用 netCDF4 创建的新 NetCDF 的文件大小?如果这不理想,有没有办法在不合并问题的情况下将多个变量添加到 xarray 中的空数据集?

以下工作流程是否足够:

ds = xr.open_dataset(fName)
ds[toinclude].to_netcdf(file2)

既然你提到试图减小文件大小,你应该看看 Xarray 在 "writing encoded data" 上的文档。你可能想做这样的事情:

encoding = {v: {'zlib: True, 'complevel': 4} for v in toinclude}
ds[toinclude].to_netcdf(file2, encoding=encoding, engine='netcdf4')

您的原始文件格式为 NETCDF3_CLASSIC,但您的副本格式为 NETCDF4_CLASSIC。这会增加生成的文件大小,不知道为什么,但我之前已经 运行 了。

with nc.Dataset(file1) as src, nc.Dataset(file2, "w") as dst:

至:

with nc.Dataset(file1) as src, nc.Dataset(file2, "w", format="NETCDF3_CLASSIC") as dst:

出于某种我不知道的原因,这导致您检查无限维度时出现问题,这也很容易修复。

我修改后的脚本如下。生成的 NetCDF 文件为 1.4 MB

import netCDF4 as nc

file1 = 'JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc'
file2 = 'test.nc'

toinclude = ['lat_20hz', 'lon_20hz', 'time_20hz', 'alt_20hz', 'ice_range_20hz_ku', 'ice_qual_flag_20hz_ku', 'model_dry_tropo_corr', 'model_wet_tropo_corr', 'iono_corr_gim_ku', 'solid_earth_tide', 'pole_tide', 'alt_state_flag_ku_band_status']

with nc.Dataset(file1) as src, nc.Dataset(file2, "w", format="NETCDF3_CLASSIC") as dst:
 # copy attributes
  for name in src.ncattrs():
    dst.setncattr(name, src.getncattr(name))
  # copy dimensions
  for name, dimension in src.dimensions.iteritems():
    if dimension.isunlimited():
      dst.createDimension( name, None)
    else:
      dst.createDimension( name, len(dimension))
  # copy all file data for variables that are included in the toinclude list
  for name, variable in src.variables.iteritems():
    if name in toinclude:
      x = dst.createVariable(name, variable.datatype, variable.dimensions)
      dst.variables[name][:] = src.variables[name][:]

如果您使用的是 netCDF4 python 的软件包,那么您可以使用 netcdf-c 库中的命令行工具。例如 nccopy 允许从一个 netCDF 文件复制到另一个 netCDF 文件过滤变量:

$ VARS = "lat_20hz,lon_20hz,time_20hz,alt_20hz,ice_range_20hz_ku,ice_qual_flag_20hz_ku,model_dry_tropo_corr,model_wet_tropo_corr,iono_corr_gim_ku,solid_earth_tide,pole_tide,alt_state_flag_ku_band_status"
$ nccopy -V $VARS JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc dum.nc

生成的文件 dum.nc 将包含唯一需要的变量,并且它的大小将成比例。输出格式将与输入相同,在本例中为 classic 或 netCDF3。您可以选择netCDF4-经典模型格式:

$ nccopy -k4 -V $VARS JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc dum_k4.nc

这会导致更多的开销(<4KiB)。但是如果你真的担心大小,你可以使用 netCDF4-classic 数据模型格式压缩数据,比如:

$ nccopy -k4 -s -d9 -V $VARS JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc dum_k4_s_d9.nc

哪个尺寸只有上一个尺寸的 33%。

[ 编辑:这是从原始文件复制到新文件的命令,带有 deflate 选项,没有变量过滤器: $ nccopy -k4 -s -d9 JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc orig_k4_s_d9.nc ]

这里有不同文件的大小对比:

   Size File
5514208 JA2_GPN_2PdP001_140_20080717_113355_20080717_123008.nc
2579535 orig_k4_s_d9.nc
1494174 dum_k4.nc
1457076 dum.nc
 487695 dum_k4_s_d9.nc

nco 还有其他基于 bit-shavingscale-offset 的压缩有损算法。

查看 nccopy -h 命令帮助。