1.NetCDF 文件介绍
- Network Common Data Form (NetCDF),采用二进制格式;可以用来存储一系列的数组;
- files contain a header and file metadata in the form of name/value
attributes;
2.文件存储方式
netCDF文件中的数据以数组的形式存储。存储在数组中的数据需要具有相同的类型。如:
(1)一维数组
在一个位置上随时间变化的温度被存储为一维阵列。
(2)二维数组
给定时间内某一区域上的温度被存储为二维数组/阵列。注意:Pandas DataFrame也是一个二维的数据结构,但是它不同于数组:DataFrame可以存储异构的数据元素。
dataframe 存储结构:
(3)三维数组
如一个区域的温度随时间变化。
3.文件组成
netCDF文件包含维度、变量和属性。
(1)维度
维度可以用来表示实际的物理维度,例如,时间、纬度、经度或高度;或更抽象的数量,如车站或模型运行ID。
(2)变量
变量表示同一类型值的数组。变量用于在netCDF文件中存储大量数据。变量的名称、数据类型和形状由创建变量时指定的维度列表来描述。
(3)属性
NetCDF属性用于存储辅助数据或元数据。大多数属性提供关于特定变量的信息。这些属性由变量的名称和属性的名称标识。
图片转载自https://adyork.github.io/python-oceanography-lesson/17-Intro-NetCDF/index.html
4.数据读取与可视化
python中常用xarray读取nc数据。
(1)读取数据:
import xarray as xr
nc_file = r"./file.nc"
nc_data= xr.open_dataset(nc_file)
print(nc_data)
(2)查看变量
print(nc_data["variable1"].data[0])#查看第一个变量,data将variable1变量转换成numpy数组
(3)绘图
print(nc_data["variable1"][0].plot(x='lon',y='lat'))
举例:
nc数据可视化:
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs #加载地图信息
import numpy as np
access_pr_file = './file.nc'
#读取数据
dset = xr.open_dataset(access_pr_file)#读取Dataset类型数据,即能读取多个物理量
#时间平均处理
clim = dset['pr'].mean('time', keep_attrs=True)
#转换时间单位
clim.data = clim.data * 86400
clim.attrs['units'] = 'mm/day'
#创建画布
fig = plt.figure(figsize=[12,5])
#设置空间投影
ax = fig.add_subplot(111, projection=ccrs.PlateCarree(central_longitude=180))
clim.plot.contourf(ax=ax,
levels=np.arange(0, 13.5, 1.5),
extend='max',
transform=ccrs.PlateCarree(),
cbar_kwargs={'label': clim.units},
cmap='viridis_r')
ax.coastlines()
plt.show()
5.实例
https://adyork.github.io/python-oceanography-lesson/22-defensive/index.html
import argparse #argparse模块是命令行选项、参数和子命令解析器;适用于代码需要频繁地修改参数的情况。
import numpy as np
import matplotlib.pyplot as plt
import xarray as xr
import cartopy.crs as ccrs
import cmocean
#定义转换单位函数
def convert_pr_units(darray):
"""Convert kg m-2 s-1 to mm day-1.
Args:
darray (xarray.DataArray): Precipitation data
"""
darray.data = darray.data * 86400
darray.attrs['units'] = 'mm/day'
return darray
#定义mask函数
def apply_mask(darray, sftlf_file, realm):
"""Mask ocean or land using a sftlf (land surface fraction) file.
Args:
darray (xarray.DataArray): Data to mask
sftlf_file (str): Land surface fraction file
realm (str): Realm to mask
"""
dset = xr.open_dataset(sftlf_file)
if realm == 'land':
masked_darray = darray.where(dset['sftlf'].data < 50)
else:
masked_darray = darray.where(dset['sftlf'].data > 50)
return masked_darray
#定义绘图软件
def create_plot(clim, model_name, season, gridlines=False, levels=None):
"""Plot the precipitation climatology.
Args:
clim (xarray.DataArray): Precipitation climatology data
model_name (str): Name of the climate model
season (str): Season
Kwargs:
gridlines (bool): Select whether to plot gridlines
levels (list): Tick marks on the colorbar
"""
if not levels:
levels = np.arange(0, 13.5, 1.5)
fig = plt.figure(figsize=[12,5])
ax = fig.add_subplot(111, projection=ccrs.PlateCarree(central_longitude=180))
clim.sel(season=season).plot.contourf(ax=ax,
levels=levels,
extend='max',
transform=ccrs.PlateCarree(),
cbar_kwargs={'label': clim.units},
cmap=cmocean.cm.haline_r)
ax.coastlines()
if gridlines:
plt.gca().gridlines()
title = '%s precipitation climatology (%s)' %(model_name, season)
plt.title(title)
#定义main函数
def main(inargs):
"""Run the program."""
dset = xr.open_dataset(inargs.pr_file)
clim = dset['pr'].groupby('time.season').mean('time', keep_attrs=True)
clim = convert_pr_units(clim)
if inargs.mask:
sftlf_file, realm = inargs.mask
clim = apply_mask(clim, sftlf_file, realm)
create_plot(clim, dset.attrs['model_id'], inargs.season,
gridlines=inargs.gridlines, levels=inargs.cbar_levels)
plt.savefig(inargs.output_file, dpi=200)
if __name__ == '__main__':
description='Plot the precipitation climatology for a given season.'
parser = argparse.ArgumentParser(description=description)
parser.add_argument("pr_file", type=str, help="Precipitation data file")
parser.add_argument("season", type=str, help="Season to plot")
parser.add_argument("output_file", type=str, help="Output file name")
parser.add_argument("--gridlines", action="store_true", default=False,
help="Include gridlines on the plot")
parser.add_argument("--cbar_levels", type=float, nargs='*', default=None,
help='list of levels / tick marks to appear on the colorbar')
parser.add_argument("--mask", type=str, nargs=2,
metavar=('SFTLF_FILE', 'REALM'), default=None,
help="""Provide sftlf file and realm to mask ('land' or 'ocean')""")
args = parser.parse_args()
main(args)
参考资料:
Introduction to netCDF:https://adyork.github.io/python-oceanography-lesson/17-Intro-NetCDF/index.html
https://adyork.github.io/python-oceanography-lesson/22-defensive/index.html
气象数据处理:https://zhuanlan.zhihu.com/p/129351199
python的netCDF4库读取.nc文件:https://blog.csdn.net/weixin_43718675/article/details/102158535