【问题标题】:How to incrementally save multiple variables using Python netCDF4?如何使用 Python netCDF4 增量保存多个变量?
【发布时间】:2020-07-21 08:17:03
【问题描述】:

我正在尝试使用 python netCDF4 模块将多个变量(例如 AB)写入单个 netcdf 文件。

我的函数在每次循环迭代中为A 输出一个新时间片,为B 输出一个新时间片,我试图在这些新片出现时将它们保存到文件中,而不是在 RAM 中累积并一次性节省。

以下是我目前的尝试:

import numpy as np
from netCDF4 import Dataset, date2num, num2date

fout=Dataset('test.nc', 'w')

x=np.arange(10)
y=np.arange(20)
xx,yy=np.meshgrid(x,y)

# create dimensions
fout.createDimension('x', len(x))
fout.createDimension('y', len(y))
fout.createDimension('t', None)

x_ax=fout.createVariable('x', np.float, ['x',])
x_ax[:]=x
y_ax=fout.createVariable('y', np.float, ['y',])
y_ax[:]=y
t_ax=fout.createVariable('t', np.float, ['t',])

# a big loop
for ii in range(10):  

    # some function that outputs a slice of A and a slice of B
    var_aii=(xx*ii + yy)[None, ...]
    var_bii=(xx + yy*ii)[None, ...]

    if 'var_A' not in fout.variables.keys():
        # if 1st time writing "var_A", create new variable
        var_A=fout.createVariable('var_A', np.float, ['t', 'y', 'x'])
        var_A[:]=var_aii
    else:
        # if variable already created, append to the end of 1st dimension
        var_A=fout.variables['var_A']
        var_A[:]=np.concatenate([var_A[:], var_aii])

    if 'var_B' not in fout.variables.keys():
        var_B=fout.createVariable('var_B', np.float, ['t', 'y', 'x'])
        var_B[:]=var_aii
    else:
        var_B=fout.variables['var_B']
        var_B[:]=np.concatenate([var_B[:], var_aii])

    print('ii=', ii, 'var_A.shape=', var_A.shape, 'var_B.shape=', var_B.shape)

fout.close()

这是输出:

ii= 0 var_A.shape= (1, 20, 10) var_B.shape= (1, 20, 10)
ii= 1 var_A.shape= (3, 20, 10) var_B.shape= (3, 20, 10)
ii= 2 var_A.shape= (5, 20, 10) var_B.shape= (5, 20, 10)
ii= 3 var_A.shape= (7, 20, 10) var_B.shape= (7, 20, 10)
ii= 4 var_A.shape= (9, 20, 10) var_B.shape= (9, 20, 10)
ii= 5 var_A.shape= (11, 20, 10) var_B.shape= (11, 20, 10)
ii= 6 var_A.shape= (13, 20, 10) var_B.shape= (13, 20, 10)
ii= 7 var_A.shape= (15, 20, 10) var_B.shape= (15, 20, 10)
ii= 8 var_A.shape= (17, 20, 10) var_B.shape= (17, 20, 10)
ii= 9 var_A.shape= (19, 20, 10) var_B.shape= (19, 20, 10)

问题在于t 维度的时间增长了 2 步,而不是 1。我认为这是因为无限的 t 维度会随着更多数据的添加而自动扩展,因此在 ii==1 迭代中,写入var_A后,时间维度增长到2的长度,所以在追加var_B时,var_B在追加之前已经有2的长度了。

我没有使用ii 作为索引来分配像var_A[ii]=var_aii 这样的值,因为我觉得它容易出错。如果循环中有一些条件continues 跳过了几个iis,就会产生间隙。

那么沿时间维度递增地追加多个变量的更稳健的方法是什么?

【问题讨论】:

    标签: python netcdf4


    【解决方案1】:

    看来查询当前时间维度的长度得到插入索引还不够。

    我做了一个粗略的解决方案,将数据附加到 netcdf 文件中的现有变量:

    def appendTime(fout, newslice, newt, varid):
        '''Append data along time dimension
    
        Args:
            fout (netCDF4.Dataset): opened Dataset file obj to write into.
            newslice (ndarray): new time slice data to save.
            newt (1darray): new time values of <newslice>.
            varid (str): variable id.
        '''
    
        newt=np.atleast_1d(newt)
    
        if varid not in fout.variables.keys():
            #-----------------Create variable-----------------
            varout=fout.createVariable(varid, np.float, ('t','y','x'), zlib=True)
            varout[:]=newslice
        else:
            #-----------------Append variable-----------------
            varout=fout.variables[varid]
            timeax=fout.variables['t']
            tlen=len(timeax)
            t0=newt[0]
            tidx=np.where(timeax==t0)[0]
            if len(tidx)>0:
                # time point already exists
                tidx=tidx[0]
            else:
                # new time point added
                tidx=tlen
            timeax[tidx:tidx+len(newt)]=newt
            varout[tidx:tidx+len(newt)]=newslice
    
        return
    

    现在循环内的代码可能是:

    for ii in range(10):
        # some function that outputs a slice of A and a slice of B
        var_aii=(xx*ii + yy)[None, ...]
        var_bii=(xx + yy*ii)[None, ...]
        appendTime(fout, var_aii, ii, 'var_A')
        appendTime(fout, var_bii, ii, 'var_B')
        var_A=fout.variables['var_A']
        var_B=fout.variables['var_B']
        print('ii=', ii, 'var_A.shape=', var_A.shape, 'var_B.shape=', var_B.shape)
    

    【讨论】:

      猜你喜欢
      • 2021-11-15
      • 2018-04-30
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      • 2011-09-27
      • 2013-08-10
      • 1970-01-01
      相关资源
      最近更新 更多