目录
NetCDF 文件:从入门到精通 —— 理论与实验相结合
写在前面
写本文的目的就是想了解一下nc文件,其内部构造到底是什么样子的?
简单总结就是最主要的就是Variables
,比如海温(temperature),然后这个变量可能包含多个维度Dimensions
,比如time,lat,lon,level等等。然后每一个变量都有与之对应的数据,这样子的话其实也就是四组数据,他们之间并没有直接的联系,此次就有一个很重要的Coordinates
,坐标就可以把这些维度变量与海温变量之间联系起来,这样就很方便后面的操作,实现自描述!
一、什么是 NetCDF?
(一)定义
NetCDF(Network Common Data Form)是一种自描述、平台无关、二进制格式的数据文件,广泛应用于气象、海洋、地球科学等领域。它能够存储多维科学数据(如时间、纬度、经度、高度等),并且自带元数据信息,便于数据交换和共享。
(二)特点
- 自描述性(Self-describing):包含变量名、维度、单位、注释等元数据。
- 支持多维数组(Multidimensional arrays):适合表示时空数据。
- 跨平台兼容性强:支持多种操作系统和编程语言。
- 高效读写:适用于大规模科学数据处理。
二、NetCDF 文件的结构
NetCDF 文件的核心结构由以下四个部分组成,每部分的功能和区别如下:
组成部分 | 作用 | 特点 | 示例 |
---|---|---|---|
1. 维度(Dimensions) | 定义数据的维度(如时间、纬度、经度等),是变量的"骨架"。 | - 可以是固定长度或无限长度(UNLIMITED )。- 每个变量必须绑定到维度。 | time = 12 , lat = 73 , lon = 144 |
2. 变量(Variables) | 存储实际的多维数据(如温度、风速等),是数据的主体。 | - 每个变量关联到一个或多个维度。 - 数据类型支持 int , float , double , char 等。 | temperature(time, lat, lon) |
3. 属性(Attributes) | 描述变量或文件的元数据(如单位、长名称、来源等)。 | - 分为全局属性(描述整个文件)和局部属性(描述变量)。 - 用于增强数据的可读性和互操作性。 | units = "K" , long_name = "Surface Temperature" |
4. 数据(Data) | 实际存储在变量中的数值,按维度排列。 | - 数据块按需读取,支持高效访问子集。 | temperature[0, 0, 0] = 285.3 |
示例:一个 NetCDF 文件可能包含如下结构:
dimensions:
time = 12 ;
lat = 73 ;
lon = 144 ;
variables:
float temperature(time, lat, lon) ;
temperature:units = "K" ;
temperature:long_name = "Surface Air Temperature" ;
double time(time) ;
time:units = "months since 2000-01-01" ;
float lat(lat) ;
lat:units = "degrees_north" ;
float lon(lon) ;
lon:units = "degrees_east" ;
区别总结
维度 | 变量 | 属性 | 数据 |
---|---|---|---|
定义数据的轴(如时间、空间) | 存储具体科学数据 | 描述数据的元信息 | 实际的数值内容 |
是变量的"结构基础" | 依赖维度定义 | 附加在变量或文件上 | 由变量存储 |
例如:time = 12 | 例如:temperature(time, lat, lon) | 例如:units = "K" | 例如:285.3 |
如何实现自描述的?-----Coordinates
在 NetCDF 文件中,坐标(Coordinates) 是用于描述数据空间、时间或其他维度位置的关键元数据。它们通过 坐标变量(Coordinate Variables) 和 维度(Dimensions) 的组合,帮助定义数据的物理位置(如经纬度、时间、高度等),从而实现数据的多维定位和可视化。以下是其作用和细节的详细说明:
1. 坐标的作用
(1) 定义数据的空间/时间位置
坐标变量通常与维度一一对应,用于描述数据在物理空间或时间上的分布。例如:
- 空间坐标:经度(
lon
)、纬度(lat
)、高度(height
)。 - 时间坐标:时间(
time
),如2025-05-12
。 - 其他维度:深度(
depth
)、压力(pressure
)等。 - 支持数据的多维索引
通过坐标变量,可以快速定位数据在某个位置(如某经纬度、某时间点)的值。例如:data.sel(lat=30, lon=120, time='2025-05-12') # 使用 xarray 选取特定位置的数据
(2) 辅助 GIS 和科学工具的可视化
GIS 软件(如 ArcGIS、QGIS)和科学工具(如 Python 的 matplotlib
、cartopy
)依赖坐标变量来:
- 正确解析数据的 空间参考系统(地理坐标系或投影坐标系)。
- 自动匹配地图投影,避免数据错位(如经纬度与投影坐标不一致导致的偏移)。
(3) 遵循 CF 约定(Climate and Forecast Metadata Conventions)
NetCDF 社区广泛采用 CF 元数据约定,要求通过坐标变量的属性(如 units
、standard_name
)明确描述数据的物理意义。例如:
lat = rootgrp.createVariable("lat", "f4", ("lat",))
lat.units = "degrees_north" # 表示纬度单位
lat.standard_name = "latitude" # 标准名称
2. 坐标变量的定义方式
(1) 坐标变量(Coordinate Variables)
- 定义:与维度同名的一维变量,用于描述该维度的物理坐标。
- 示例:
# 定义维度 lat_dim = rootgrp.createDimension("lat", 73) # 创建坐标变量 lat = rootgrp.createVariable("lat", "f4", ("lat",)) lat[:] = np.arange(-90, 90, 2.5) # 纬度值
(2) 辅助坐标变量(Auxiliary Coordinate Variables)
- 定义:非维度同名的变量,用于描述复杂坐标(如三维经纬度、球面坐标)。
- 示例:
# 定义三维数据的经纬度(如球面坐标) lons = rootgrp.createVariable("longitude", "f4", ("time", "lat", "lon")) lats = rootgrp.createVariable("latitude", "f4", ("time", "lat", "lon"))
3. 坐标变量的关键属性
为确保数据的可读性和兼容性,坐标变量需要设置以下属性:
属性 | 作用 | 示例 |
---|---|---|
units | 描述坐标单位 | "degrees_east" 、"m" 、"hours since 2000-01-01" |
standard_name | 标准名称(CF 约定) | "latitude" 、"time" |
long_name | 详细描述 | "Surface Air Temperature" |
grid_mapping | 定义投影参数(用于投影坐标系) | "projection" 变量的名称 |
bounds | 定义坐标的范围(如经纬度网格的边界) | "lat_bnds" 、"lon_bnds" |
4. 坐标与空间参考系统(CRS)的关系
(1) 地理坐标系(GCS)
- 如果坐标变量的单位是
degrees_east
(经度)和degrees_north
(纬度),则默认使用 WGS 1984 地理坐标系。 - 示例:
lon.units = "degrees_east" lat.units = "degrees_north"
(2) 投影坐标系(PCS)
- 如果坐标变量的
standard_name
是projection_x_coordinate
和projection_y_coordinate
,并配合grid_mapping
属性,则表示投影坐标系。 - 示例:
x = rootgrp.createVariable("x", "f4", ("x",)) x.standard_name = "projection_x_coordinate" y = rootgrp.createVariable("y", "f4", ("y",)) y.standard_name = "projection_y_coordinate" grid_mapping = rootgrp.createVariable("projection", "i4") grid_mapping.grid_mapping_name = "lambert_conformal_conic"
5. 实际应用中的注意事项
(1) 遵循 CF 约定
- 为坐标变量设置
standard_name
和units
,确保与其他工具兼容。 - 对于时间变量,使用标准时间格式(如
days since 2000-01-01
)。
(2) 避免坐标错位
- 确保经纬度的范围和分辨率与数据匹配(如全球数据需覆盖
0°-360°
或-180°-180°
)。 - 使用
bounds
属性定义网格边界,避免插值错误。
(3) GIS 软件的兼容性
- 在 ArcGIS 中,若坐标变量未正确设置
units
或grid_mapping
,可能导致数据无法正确显示。 - 使用
Make NetCDF Table View
工具提取坐标信息,并通过插值算法(如 IDW)校正位置。
6. 代码示例:定义坐标变量
以下代码展示如何使用 netCDF4
库定义一个包含经纬度和时间坐标的 NetCDF 文件:
from netCDF4 import Dataset
import numpy as np
# 创建文件
rootgrp = Dataset("example.nc", "w", format="NETCDF4")
# 定义维度
time_dim = rootgrp.createDimension("time", None)
lat_dim = rootgrp.createDimension("lat", 73)
lon_dim = rootgrp.createDimension("lon", 144)
# 定义坐标变量
time = rootgrp.createVariable("time", "i4", ("time",))
lat = rootgrp.createVariable("lat", "f4", ("lat",))
lon = rootgrp.createVariable("lon", "f4", ("lon",))
# 写入数据
time.units = "days since 2000-01-01"
time[0] = 0
lat.units = "degrees_north"
lat[:] = np.arange(-90, 90, 2.5)
lon.units = "degrees_east"
lon[:] = np.arange(0, 360, 2.5)
# 关闭文件
rootgrp.close()
7. 总结
作用 | 关键点 |
---|---|
定义数据位置 | 通过坐标变量(如经纬度、时间)描述数据的空间/时间分布 |
多维索引 | 支持按坐标选取数据子集(如 data.sel(lat=30, lon=120) ) |
空间参考 | 配合 units 和 grid_mapping 属性定义地理或投影坐标系 |
兼容性 | 遵循 CF 约定,确保不同工具(如 GIS、Python 库)正确解析数据 |
通过合理设置坐标变量,NetCDF 文件能够高效存储和共享科学数据,并确保其在分析和可视化中的准确性。
三、NetCDF 常用工具介绍
(一) 命令行工具(CLI)
1. ncdump
查看 nc 文件内容的最常用命令。
ncdump -h filename.nc # 查看头信息(metadata)
ncdump -v varname filename.nc # 查看某个变量的内容
2. ncks
(来自 NCO)
提取子集、合并文件、修改变量。
ncks -d lat,30,50 -d lon,-120,-80 input.nc output.nc # 提取区域子集
3. cdo
(Climate Data Operators)
气候数据处理工具,可进行插值、统计、合并等操作。
cdo timmean input.nc output.nc # 计算时间平均
cdo seltimestep,1/12 input.nc output.nc # 提取前12个时间步
(二) 图形化工具
1. Panoply(NASA)
免费、跨平台、可视化 nc 文件数据。
2. QGIS + GDAL
可用于加载并显示 nc 格式的地理空间数据。
四、使用 Python 操作 NetCDF 文件
Python 是处理 NetCDF 的首选语言之一,主要依赖库包括:
netCDF4
: Python 接口,功能强大xarray
: 封装了 netCDF4,更易用numpy
: 支持数组运算matplotlib/cartopy
: 可视化
(一) 安装依赖
pip install netCDF4 xarray matplotlib cartopy
五、实战教程:读取、分析、绘制 NetCDF 数据
我们以一个全球气温数据 .nc
文件为例,完成以下任务:
- 读取 nc 文件
- 查看变量与维度
- 提取某个月份的气温数据
- 绘制全球气温分布图
(一) 步骤 1:准备数据
你可以使用 NOAA 或 CMIP6 提供的公开数据,比如 air.2m.mon.mean.nc
。
(二)步骤 2:读取 nc 文件(使用 xarray
)
import xarray as xr
# 加载 nc 文件
ds = xr.open_dataset('air.2m.mon.mean.nc')
# 显示基本信息
print(ds)
输出类似:
<xarray.Dataset>
Dimensions: (lat: 73, lon: 144, time: 852)
Coordinates:
* lat (lat) float32 -90.0 -87.5 -85.0 ... 85.0 87.5 90.0
* lon (lon) float32 0.0 2.5 5.0 ... 355.0 357.5
* time (time) datetime64[ns] 1979-01-01 ... 2020-12-01
Data variables:
air (time, lat, lon) float32 ...
(三) 步骤 3:提取某月份的数据(如 2000 年 1 月)
# 选择 2000年1月
data = ds['air'].sel(time='2000-01-01', method='nearest')
# 查看数据形状
print(data.shape) # 输出:(73, 144)
# 转换为 numpy 数组
temp_data = data.values # shape: (73, 144)
(四) 步骤 4:绘制全球气温分布图
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
# 设置绘图投影
fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(111, projection='platecarree')
# 绘制等值线图
cs = ax.contourf(data.lon, data.lat, temp_data, cmap='coolwarm', transform=ccrs.PlateCarree())
# 添加海岸线
ax.coastlines()
# 添加颜色条
plt.colorbar(cs, orientation='horizontal', label='Temperature (K)')
plt.title('Global Surface Air Temperature - January 2000')
plt.show()
六、进阶技巧:创建和写入 NetCDF 文件
(一) 示例:创建一个新的 nc 文件并写入数据
from netCDF4 import Dataset
import numpy as np
# 创建新文件
rootgrp = Dataset("example_output.nc", "w", format="NETCDF4")
# 定义维度
lat_dim = rootgrp.createDimension("lat", 73)
lon_dim = rootgrp.createDimension("lon", 144)
time_dim = rootgrp.createDimension("time", None) # 无限长维度
# 定义变量
latitudes = rootgrp.createVariable("lat", "f4", ("lat",))
longitudes = rootgrp.createVariable("lon", "f4", ("lon",))
times = rootgrp.createVariable("time", "i4", ("time",))
temps = rootgrp.createVariable("temperature", "f4", ("time", "lat", "lon"))
# 写入变量数据
lats = np.arange(-90, 91, 2.5)
lons = np.arange(0, 360, 2.5)
latitudes[:] = lats
longitudes[:] = lons
times[0] = 0
# 构造一个简单的二维温度场
temps[0, :, :] = np.random.rand(73, 144) * 30 + 273 # 单位 K
# 添加属性
temps.units = "Kelvin"
temps.long_name = "Surface Air Temperature"
# 关闭文件
rootgrp.close()
(二) 使用 xarray
简化操作
import xarray as xr
# 创建 Dataset
ds = xr.Dataset(
{
"temperature": (["time", "lat", "lon"], [temp_data]),
},
coords={
"time": [0],
"lat": lats,
"lon": lons,
},
attrs={"description": "Example using xarray"},
)
# 保存为 .nc 文件
ds.to_netcdf("example_output_xarray.nc")
七、常见问题解答(FAQ)
问题 | 解答 |
---|---|
❓ 如何判断 nc 文件是否是 NetCDF4 格式? | 使用 ncdump -k filename.nc 查看 |
❓ 是否可以在 Windows 上处理 nc 文件? | 是的,推荐使用 Anaconda 和 Jupyter Notebook |
❓ 如何将多个 nc 文件合并? | 使用 cdo mergetime *.nc merged.nc 或 xarray.open_mfdataset() |
❓ NetCDF 支持哪些编程语言? | C/C++, Fortran, Python, R, MATLAB, Java 等 |
八、推荐阅读资源
九、结语
NetCDF 是科学计算中极为重要的数据格式,尤其在大气、海洋、生态、遥感等领域不可或缺。通过本教程的学习,你应该已经掌握了:
✅ NetCDF 文件的基本结构
✅ 如何使用命令行工具查看和处理 nc 文件
✅ 如何使用 Python 进行读写与可视化
✅ 如何创建自己的 nc 文件
✅ 如何进一步扩展学习