Xarray — 带坐标标签的多维数组,气候/地理/科学数据必备
一句话说明
Xarray 给 NumPy 数组加上了"有名字的维度和坐标",就像给 Excel 的行列加了真实的时间、经纬度标签,让气候、遥感、生信数据的操作变得直观。
安装与配置
# pip 安装
pip install xarray netcdf4 scipy # netcdf4 用于读 .nc 文件
# conda 安装(推荐,依赖更完整)
conda install -c conda-forge xarray netcdf4
# 验证
python -c "import xarray as xr; print(xr.__version__)"
核心用法
DataArray — 单个带标签数组
import xarray as xr
import numpy as np
# 创建 DataArray(数据 + 维度名 + 坐标)
da = xr.DataArray(
data = np.random.rand(4, 3), # 4x3 的数据
dims = ["time", "space"], # 维度名称
coords = {
"time": ["2024-01", "2024-02", "2024-03", "2024-04"], # 时间坐标
"space": ["北京", "上海", "广州"], # 空间坐标
},
name = "temperature", # 数组名称
)
print(da) # 打印带坐标的数组
print(da.sel(space="北京")) # 按名字选取北京的数据
print(da.isel(time=0)) # 按位置选第一个时间步
Dataset — 多变量容器
# Dataset 相当于多个 DataArray 的字典
ds = xr.Dataset({
"temperature": xr.DataArray( # 温度变量
np.random.rand(4, 3),
dims=["time", "city"],
coords={"time": range(4), "city": ["BJ", "SH", "GZ"]},
),
"humidity": xr.DataArray( # 湿度变量(同维度)
np.random.rand(4, 3) * 100,
dims=["time", "city"],
),
})
print(ds["temperature"]) # 取出温度 DataArray
print(ds.data_vars) # 列出所有变量名
实战案例
读写 NetCDF 文件(气候数据)
import xarray as xr
# 读取 .nc 文件(气象数据标准格式)
ds = xr.open_dataset("era5_temperature.nc")
print(ds) # 查看数据结构
print(ds.dims) # 维度:time, lat, lon
print(ds["t2m"]) # 2米温度变量
# 选取特定区域和时间
subset = ds.sel(
lat = slice(20, 55), # 纬度 20-55°N(中国范围)
lon = slice(70, 140), # 经度 70-140°E
time = "2024-07-01", # 选特定日期
)
# 保存为新的 NetCDF
subset.to_netcdf("china_2024-07.nc")
分组与聚合
# 按月计算均值(类似 pandas groupby)
monthly_mean = ds["t2m"].groupby("time.month").mean()
# 空间均值(沿纬度方向加权平均)
weights = np.cos(np.deg2rad(ds.lat)) # 纬度余弦权重
spatial_avg = ds["t2m"].weighted(weights).mean(dim=["lat", "lon"])
# 滚动平均(7天滑动窗口)
rolling_7d = ds["t2m"].rolling(time=7, center=True).mean()
常见报错与解决
| 报错 | 原因 | 解决 |
|---|
ValueError: coordinate ... not found | 坐标名写错 | 用 ds.coords 检查坐标名 |
KeyError: '...' 选取变量 | 变量名不存在 | 用 ds.data_vars 列出所有变量 |
SerializationWarning 写 NetCDF | 数据类型不支持 | 加 encoding={"var": {"dtype": "float32"}} |
| 内存不足 | 文件太大全量加载 | 用 open_mfdataset() + dask 懒加载 |
速查表
| 操作 | 代码 |
|---|
| 按标签选 | da.sel(time="2024-01") |
| 按位置选 | da.isel(time=0) |
| 均值 | da.mean(dim="time") |
| 分组聚合 | da.groupby("time.month").mean() |
| 读 NetCDF | xr.open_dataset("file.nc") |
| 写 NetCDF | ds.to_netcdf("out.nc") |
| 转 pandas | da.to_dataframe() |
| 转 numpy | da.values |