[英]How to specify precision when reading in variables using netCDF4 in Python?
[英]How to incrementally save multiple variables using Python netCDF4?
我正在嘗試使用 python netCDF4 模塊將多個變量(例如A
和B
)寫入單個 netcdf 文件。
我的 function 在每次循環迭代中為A
輸出一個新時間片,為B
輸出一個新時間片,我試圖在這些新切片出來時將它們保存到文件中,而不是在 RAM 中累積並保存在一個 go 中。
以下是我目前的嘗試:
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()
這是 output:
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
這樣的值,因為我覺得它容易出錯。 如果循環中有一些條件continue
跳過了幾個ii
,就會產生間隙。
那么在時間維度上增加多個變量的更穩健的方法是什么?
看來查詢當前時間維度的長度得到插入索引還不夠。
我對netcdf文件中現有變量的append數據做了一個粗略的解決:
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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.