第一篇 NC數據深度優先檢索
NetCDF是UCAR開發的一種通用數據格式,可能做環境或者地學的人會比較熟悉。這種數據格式非常方便使用者讀取和編輯,很多語言都可以對這種格式進行讀寫。這種格式會保留原有數據的長度、維度等信息,就像Python的.npy,matlab的.m和IDL的.sav文件一樣。NetCDF以.nc格式對數據進行存儲,所存儲的數據結構可以用一個數表示[1]:
樹的根節點表示我們訪問的nc文件,每一個子節點表示一個group,一個nc文件可能會包含很多group,而每一個group下面也可能包含很多新的group。這一個棵樹的葉子就代表了該文件所儲存的數據集,根節點和子節點都可以鏈接到很多數據集。所以,nc文件下存儲的數據結構可能會很複雜,當我們知道所需數據的key(通常就是數據名稱)的時候,便可以通過深度優先檢索的方式對數據進行查找。
代碼實現
Anaconda目前並沒有自帶netCDF4的庫,所以首先我們需要自行安裝這個庫。和其他大部分庫的安裝一樣,打開命令行窗口,鍵入:
pip install netCDF4
pip就會自動幫助你安裝好netCDF4。
我一般會使用Spyder或者vim對腳本進行編輯,我們需要先導入所需要的庫:
import netCDF4 as nc
from numpy import *
然後我們定義一個類,簡單地來說這個類的核心就是一個棧,用來暫存我們在檢索過程中遇到的節點,包括根節點和子節點。當我們對某一個節點檢索,沒有發現我們所要找的數據時,就從這個棧的棧尾取出一個節點繼續檢索。這個地方不明白的話可以先了解一下深度優先檢索:
class deep_search_nc:
def __init__(self,nc_ob): #初始化,把根節點放入棧內
self.ob_list_i = [nc_ob]
self.ob_list = [nc_ob]
def seek_for(self,varname):#單個數據集檢索
if self.ob_list == []:#檢查是否空棧
print('Cant find',varname)
self.ob_list=self.ob_list_i.copy()
return 1
ob_temp = self.ob_list.pop()#從棧尾取出一個節點(並從棧尾刪除)
if ob_temp.get_variables_by_attributes(name = varname) != []:
#判斷節點內是否有目標數據集,有的話返回數據集
self.ob_list=self.ob_list_i.copy()
temp = ob_temp.variables[varname][:]
if type(temp) == ma.core.MaskedArray:
return temp.data.squeeze()
elif type(temp) == ndarray:
return temp.squeeze()
else:
print('unrecognized type',type(temp))
return temp
else:
#沒有找到目標數據集,遞歸調用繼續檢索
for key in list(ob_temp.groups.keys()):
self.ob_list.append(ob_temp.groups[key])
return self.seek_for(varname)
def seek_lot_for(self,varnames):#多個數據集檢索
if type(varnames) == str:
varnames = [varnames]
elif type(varnames) != list:
print('wrong type of varnames!',varnames)
return []
return [self.seek_for(var) for var in varnames]
這個地方對函數進行了遞歸調用,這種方式可以使得代碼的編寫更加簡潔。
下面舉個例子,怎麼使用這個檢索工具。首先我們用nc.Dataset函數需要打開一個.nc文件,然後用它對我們的deep_search_nc類對象進行初始化,然後調用其中的seek_lot_for檢索函數:
NC_file_ob = deep_search_nc(nc.Dataset(NC_file,'r'))#NC_file是目標文件路徑,是一個字符串
nc_list= ['cloud_fraction_crb','cloud_pressure_crb','surface_pressure','surface_albedo','surface_albedo_nitrogendioxide_window','latitude_bounds','longitude_bounds','cloud_radiance_fraction_nitrogendioxide_window']
NC_file_ob.seek_lot_for(nc_list)#nc_list內包含了所有我們所想查找的數據集的key,通常來說就是變量名