第2章:Python气象数据处理库:xarray、pandas、netCDF4、cfgrib的安装与基本使用

气象数据,说白了就是一堆带着时间戳和经纬度的数字。你想想看,一个全球再分析数据,动辄几百GB,用普通的Python列表去处理?那简直是拿自行车拉火车。我刚开始接触气象数据时,就吃过这个亏——用pandas硬扛一个10GB的NetCDF文件,结果内存直接爆了,电脑卡死半小时。

从那以后,我学乖了。处理气象数据,必须用对工具。今天咱们就聊聊这四个库:xarray、pandas、netCDF4、cfgrib。它们各有各的脾气,但配合好了,就是一套黄金组合。

2.1 为什么是这四个库?

先说说我的理解。这四个库,其实分工很明确:

  • netCDF4:底层读写器。它直接跟NetCDF文件打交道,就像用open()函数读写文本文件一样。但说实话,我很少直接用,因为太底层了,操作起来像在拧螺丝。
  • xarray:气象界的pandas。它把NetCDF里的维度(时间、纬度、经度)变成了标签,你可以像操作DataFrame一样操作多维数组。我个人习惯,90%的场景都用它。
  • pandas:处理表格数据的利器。虽然xarray很强大,但有些统计计算、时间序列分析,还是pandas更顺手。我经常把xarray的数据转成pandas来做可视化。
  • cfgrib:专门对付GRIB格式的。欧洲中心的数据很多是GRIB格式,xarray读不了,这时候就得靠它。我记得第一次用cfgrib时,还踩了个坑——版本不兼容,折腾了一下午。

一句话总结:netCDF4是底层引擎,xarray是主力框架,pandas是辅助工具,cfgrib是GRIB专用插件。

2.2 安装:看似简单,实则暗藏玄机

安装这四个库,理论上就一行命令:

pip install xarray pandas netCDF4 cfgrib

但实际项目中,我建议你用conda。为什么?因为netCDF4和cfgrib都有C语言依赖,pip安装有时会报错。我曾经在Windows上装cfgrib,折腾了三个小时,最后发现是Visual C++ Redistributable没装。

避坑指南:我曾经在macOS上直接用pip install netCDF4,结果编译失败。后来换成conda install -c conda-forge netCDF4,一分钟搞定。conda-forge频道对气象库的支持是最好的。

如果你用conda,推荐这样安装:

conda create -n weather python=3.9
conda activate weather
conda install -c conda-forge xarray pandas netCDF4 cfgrib

嗯,这里要注意:cfgrib依赖eccodes库。如果你在Linux上,可能需要先装eccodes:

conda install -c conda-forge eccodes

安装完成后,验证一下:

import xarray as xr
import pandas as pd
import netCDF4
import cfgrib

print("All libraries imported successfully!")

如果没报错,恭喜你,环境搭好了。

2.3 基本使用:从打开文件开始

咱们先拿一个NetCDF文件练手。假设你有一个全球温度数据文件 temperature.nc

2.3.1 用xarray打开NetCDF

import xarray as xr

# 打开数据集
ds = xr.open_dataset('temperature.nc')
print(ds)

你会看到类似这样的输出:

<xarray.Dataset>
Dimensions:    (time: 365, lat: 181, lon: 360)
Coordinates:
  * time       (time) datetime64[ns] 2020-01-01 ... 2020-12-31
  * lat        (lat) float64 -90.0 -89.0 -88.0 ... 89.0 90.0
  * lon        (lon) float64 0.0 1.0 2.0 ... 359.0
Data variables:
    t2m        (time, lat, lon) float32 ...

看到没?xarray自动识别了维度(time、lat、lon)和坐标。这就是它的核心优势——带标签的多维数组

我个人习惯,拿到数据后第一件事就是看维度大小:

print(ds.dims)
# 输出:Frozen({'time': 365, 'lat': 181, 'lon': 360})

如果数据太大,我建议先取一小块看看:

# 只取前10天,纬度范围30°N-60°N
subset = ds.isel(time=slice(0,10)).sel(lat=slice(30, 60))
print(subset)

2.3.2 用netCDF4直接读写

虽然xarray好用,但有些场景必须用netCDF4。比如,你要读取文件的全局属性(global attributes):

from netCDF4 import Dataset

nc = Dataset('temperature.nc', 'r')
print(nc.title)  # 输出文件的标题
print(nc.institution)  # 输出数据来源机构
nc.close()

嗯,这里要注意:netCDF4操作完一定要close(),不然文件锁住了,下次打不开。我刚开始学的时候经常忘,结果调试半天才发现是文件没释放。

2.3.3 用cfgrib打开GRIB文件

GRIB文件是气象界的另一种常见格式。欧洲中期天气预报中心(ECMWF)的很多数据都是GRIB格式。用cfgrib打开很简单:

import cfgrib

# 打开GRIB文件
ds = cfgrib.open_dataset('forecast.grib')
print(ds)

cfgrib会把GRIB文件解析成xarray的Dataset。但有个坑——GRIB文件里可能有多个变量,你需要指定参数:

# 只读取温度数据
ds_temp = cfgrib.open_dataset('forecast.grib', filter_by_keys={'paramId': 130})
# paramId=130 是温度

小技巧:如果你不知道GRIB文件里有哪些参数,可以用 cfgrib.open_dataset('forecast.grib', engine='cfgrib') 先看看,它会打印出所有可用的变量。

2.4 数据操作:切片、索引、计算

打开文件只是第一步。真正干活的时候,是数据操作。我总结了几种最常用的操作:

2.4.1 按时间选择

# 选择某一天
ds_20200101 = ds.sel(time='2020-01-01')

# 选择某个月
ds_jan = ds.sel(time='2020-01')

# 选择时间范围
ds_jan_feb = ds.sel(time=slice('2020-01-01', '2020-02-29'))

2.4.2 按空间选择

# 选择北京附近(39.9°N, 116.4°E)
ds_beijing = ds.sel(lat=39.9, lon=116.4, method='nearest')

# 选择中国区域(15°N-55°N, 70°E-140°E)
ds_china = ds.sel(lat=slice(55, 15), lon=slice(70, 140))
# 注意:纬度slice是从大到小,因为xarray默认纬度从-90到90

避坑指南:我曾经在选中国区域时,把纬度写成了slice(15, 55),结果发现数据是反的。因为xarray的纬度是从南到北递增,所以中国区域(北半球)应该是从大到小选。

2.4.3 简单计算

# 计算全球平均温度
global_mean = ds['t2m'].mean(dim=['lat', 'lon'])
print(global_mean)

# 计算时间平均
climatology = ds['t2m'].mean(dim='time')

# 计算距平(异常值)
anomaly = ds['t2m'] - climatology

你想想看,如果用传统的循环去算全球平均,365天×181纬度×360经度,得算到猴年马月?xarray一行代码搞定,底层用的是NumPy的向量化计算。

2.5 与pandas的配合

xarray虽然强大,但有些场景还是pandas更顺手。比如,你要做时间序列的滑动平均:

# 把xarray转成pandas DataFrame
df = ds['t2m'].sel(lat=39.9, lon=116.4, method='nearest').to_dataframe()
print(df.head())

# 计算7天滑动平均
df_rolling = df['t2m'].rolling(window=7).mean()

# 用matplotlib画图
import matplotlib.pyplot as plt
df_rolling.plot()
plt.title('Beijing 7-day Rolling Mean Temperature')
plt.show()

我个人习惯,做统计分析时用pandas,做多维数据操作时用xarray。两者配合,效率翻倍。

2.6 保存数据

处理完数据,总要保存吧?xarray保存NetCDF很简单:

# 保存为NetCDF
ds_china.to_netcdf('china_temperature.nc')

# 保存为NetCDF,并压缩(减少文件大小)
ds_china.to_netcdf('china_temperature_compressed.nc', 
                   encoding={'t2m': {'zlib': True, 'complevel': 5}})

压缩参数很重要。我处理过的一个全球数据,不压缩是50GB,压缩后只有8GB。磁盘空间不够的时候,这招很管用。

2.7 本章小结

好了,四个库的基本用法就这些。总结一下我的经验:

  • 安装用conda,别用pip自找麻烦
  • 主力用xarray,它让多维数据操作变得像pandas一样简单
  • 底层用netCDF4,需要读属性或精细控制时再用
  • GRIB用cfgrib,记得装eccodes依赖
  • 统计用pandas,xarray搞不定的交给它

这些库就像工具箱里的扳手、螺丝刀、钳子。每个都有它的用途,关键是要知道什么时候用哪个。下一章,咱们会拿真实的气象数据,一步步做预测。到时候,这些工具就派上大用场了。