背景介绍
NetCDF(Network Common Data Form)是一种自描述的二进制文件格式,在大气和海洋领域广泛使用,如各种大气海洋再分析资料,数值模式的输入输出等。
netcdf4-python是 netCDF4 C库的python模块。新版本(V4)中有很多以前版本中没有的优点,而且新版本是在 HDF5 上建立的。此模块可以读写 netCDF4 及 netCDF3 格式的文件,同时也可创建 HDF5 客户端只读的文件。
netcdf-python库基本支持了netCDF格式的大部分常用功能,netCDF4 格式的许多特征都实现了,比如:多个无限维度,组(groups)及zlib数据压缩。
基于该模块能方便快捷的在python语言中对netCDF格式的文件进行操作,便于分析各种大气海洋领域的数据。
1 安装netcdf-python
pip安装或conda安装:
pip install netCDF4
conda install -c conda_forge netCDF
2 新建、打开和关闭文件
import netCDF4 as nc
fname = "wrfout_d01.nc"
f = nc.Dataset(fname, mode="w", format="NETCDF4")
f = nc.Dataset(fname, mode="r", format="NETCDF4")
f = nc.Dataset(fname, mode="a", format="NETCDF4")
f = nc.Dataset(fname, mode="r+", format="NETCDF4")
f.close()
3 维度创建和读取
3.1 创建维度
time = f.createDimension("time", None)
lat = f.createDimension("lat", 73)
lon = f.createDimension("lon", 144)
time.isunlimited()
3.2 读取维度
f = nc.Dataset(fname, "r", format="NETCDF4")
nlats = len(f.dimensions["lat"])
nlons = len(f.dimensions["lon"])
4 变量的创建、读取和存储
4.1 创建变量
times = f.createVariable("time","f8",("time",))
latitudes = f.createVariable("lat","f4",("lat",))
longitudes = f.createVariable("lon","f4",("lon",))
latitudes.units = "degrees north"
longitudes.units = "degrees east"
times.units = "hours since 0001-01-01 00:00:00.0"
times.calendar = "gregorian"
temp = f.createVariable("temp","f4",("time","lat","lon",))
temp.units = "K"
temp.decription = "Air temperature"
temp._Fillvalue = -999
"""
# 常用数据类型
i2 :整型int16
i4 :整型int32
i8 :整型int64
f4 : 实型单精度single,32位
f8 : 实型双精度double,64位
S1 :单个字符串 (single-character string)
"""
4.2 读取变量
lats = f.variables['lat'][:]
lons = f.variables['lon'][:]
temp = f.variables['temp'][:]
print(temp.shape)
4.3 存储变量
lats = np.arange(-90,91,2.5)
lons = np.arange(-180,180,2.5)
latitudes[:] = lats # 赋值方法1
longitudes[:] = lons
f.variables['lat'][:] = lats # 赋值方法2
f.variables['lon'][:] = lons
temp2D = np.zeros(ny,nx)
temp[0,:,:] = temp2D # 第0个时间赋值,时间维度此时为1
temp[1,:,:] = temp2D # 第1个时间赋值,时间维度此时为2
...
5 文件属性
# 设置文件属性
f.description = "atm_ocn test netcdf"
f.source = "netCDF4 python module tutorial"
f.author = "atm_ocn"
f.history = "Created at 2021.01.01"
#也可用setattr命令设置属性
setattr(f, 'history' , "Created at 2021.01.01")
#判断文件属性是否存在
hasattr(f, 'history') # True or False
# 读取文件属性
hist_attr = getattr(f, 'history')
这里为一个小应用:判断文件的history属性是否存在,不存在则新建,存在则继续添加内容。 可以方便的保存对文件的每一步操作命令。
if hasattr(f, 'history'):
#thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + ": " + " ".join(sys.argv[:])
thiscommand = "python test.py"
newhist = '\n'.join([thiscommand, getattr(f, 'history')])
else:
newhist = thiscommand
setattr(f, 'history' , newhist )
6 压缩变量空间
format="NETCDF4"、"NETCDF4_CLASSIC "格式的文件由于其底层文件格式是HDF5,因此可以使用压缩功能,节约存储空间。不过启用压缩功能会降低存取速度,对存储资源无所谓的可以不使用。
创建变量的时候,使用以下关键字可以实现压缩功能:
(1) zlib= True,使用压缩(默认为False)。
(2)complevel,压缩水平,取值1~9,1存取速度最快但是压缩率最大,9存取速度最慢压缩率最高,默认值为4。
(3)shuffle, HDF5 shuffle filter, 这个滤波器通过对字节重新排序,它可以在压缩之前对数据块进行去隔行处理,可以显著提升压缩率, 默认为True)
(4)least_significant_digit 如果能够事先知道数据的测量精度,比如气温有效位数是0.1℃,可以将此参数设置为1。
temp = f.createVariable("temp","f4",("time","level","lat","lon",),zlib=True)
temp = f.createVariable("temp","f4",("time","level","lat","lon",),zlib=True,least_significant_digit=3)
参考:
https://www.unidata.ucar.edu/software/netcdf/
http://unidata.github.io/netcdf4-python/
https://github.com/Unidata/netcdf4-python
https://cloud.tencent.com/developer/article/1616777
关注气海同途,获取更多大气海洋数值模拟领域的内容。