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

时间:2018-02-12 21:40:51

标签: python netcdf python-xarray

我正在尝试从现有的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中将多个变量添加到空数据集而不会出现合并问题?

3 个答案:

答案 0 :(得分:1)

以下工作流程是否足够:

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')

答案 1 :(得分:1)

您的原始文件格式为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][:]

答案 2 :(得分:-1)

如果您正在使用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-classic模型格式:

$ 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-shaving scale-offset 的缩小有损算法。

查看nccopy -h命令帮助。