使用 CDO 将累积变量转换为 netcdf 文件中的时间步长值

converting an accumulated variable to timestep values in a netcdf file with CDO

我有一个 netcdf 文件,在一个网格上有大约 100 个时间步长,一个变量是在时间步长上累积的。我现在有兴趣计算每个时间步长对变量值的贡献(即连续时间步长的差异)。

目前我使用以下顺序:

  1. 为了将每个时间步提取到一个新文件中,我使用 cdo seltimestep,$i ...
  2. 将每个差异计算到一个新文件中 cdo sub $i ${i-1} ...
  3. 最后将这些新文件与 cdo mergetime ... 合并到一个结果文件中。

在我看来,这似乎非常麻烦,而且在性能方面也不理想。由于时间步长的原因,我无法使用 cdo 管道,因此需要同时创建许多文件。

是否有更好的解决方案来使用 cdo(或类似 nco/ncl 的其他方法将累积变量转换为时间步长值?)

numpy's diff 计算连续条目的差异。

我怀疑你的文件中有一个多维变量,所以这里有一个通用的例子来说明如何做:

import netCDF4
import numpy as np

ncfile = netCDF4.Dataset('./myfile.nc', 'r')
var = ncfile.variables['variable'][:,:,:] # [time x lat x lon]

# Differences with a step of 1 along the 'time' axis (0) 
var_diff = np.diff(var, n=1, axis=0) 
ncfile.close()

# Write out the new variable to a new file     
ntim, nlat, nlon = np.shape(var_diff)

ncfile_out = netCDF4.Dataset('./outfile.nc', 'w')
ncfile_out.createDimension('time', ntim)
ncfile_out.createDimension('lat', nlat)
ncfile_out.createDimension('lon', nlon)
var_out = ncfile_out.createVariable('variable', 'f4', ('time', 'lat', 'lon',))
var_out[:,:,:] = var_diff[:,:,:]
ncfile_out.close()

xarray 是我选择的此类工具:

import xarray as xr

# Open the netCDF file
ds = xr.open_dataset('./myfile.nc')

# Take the diff along the time dimension
ds['new_variable'] = ds['variable'].diff(dim='time')

# Write a new file
ds.to_netcdf('outfile.nc')

如果你想使用cdo,不需要所有那些循环和写很多文件,只需使用函数deltat:

cdo deltat in.nc diff.nc 

与 python 解决方案一样,这将比您使用的循环快几个数量级,并且具有命令行单行的优势。

或者,如果你知道长度,你可以区分这两个系列(我展示这个是因为这种技术在其他情况下很有用),而且不那么简洁:

# calculate number of steps in the file:
nstep=$(cdo -s ntime in.nc)

# do difference between steps 2:n and steps 1:(n-1)
cdo sub -seltimestep,2/$nstep in.nc -seltimestep,1/`expr $nstep - 1` in.nc diff.nc

关于累积字段的后记! 请注意,上述解决方案和此页面上发布的 python 解决方案都会产生一个时间步长小于输入的输出, 即他们扔掉了第一个时间步。在某些情况下,例如,如果您有一个在预测中累积的模型通量场(似乎是这种情况),您不想丢弃第一个时间步长(因为这是从预测开始时的零到第一步)。在这种情况下,您可以提取第一步并将其插入到文件的“前面”,如下所示:

cdo mergetime -seltimestep,1 in.nc diff.nc diff_with_step1.nc 

您还应确保对 python 解决方案也执行此操作。

你可以把整个东西作为一个单行管道(有时管道会导致总线错误或段错误,这些通常可以使用“-L”选项来补救,以强制执行顺序操作)。

cdo mergetime -seltimestep,1 in.nc -deltat in.nc diff_with_step1.nc

如果遇到段错误,试试这个

cdo -L mergetime -seltimestep,1 in.nc -deltat in.nc diff_with_step1.nc

这是为了防止舍入和准确性问题,如果您有打包数据(即类型 NC_SHORT):

cdo -L -b f32 mergetime -seltimestep,1 in.nc -deltat in.nc diff_with_step1.nc