跳转至

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()
读 NetCDFxr.open_dataset("file.nc")
写 NetCDFds.to_netcdf("out.nc")
转 pandasda.to_dataframe()
转 numpyda.values