xarray指南:合并数据 - 连接

目录

本文翻译自 xarray 官方文档 Combining data 的部分内容。

本文介绍如何使用 xarray 实现沿单个纬度合并 DataArrayDataset

简介

  • 有关沿单个维度组合数据集或数据数组的信息,请参阅 concatenate。
  • 有关合并具有不同变量的数据集,请参见 merge。
  • 有关合并具有不同索引或缺失值的数据集或数据数组的信息,请参见 combine。
  • 有关沿多个维度组合数据集或数据数组的信息,请参见 combining.multi。

准备

加载需要使用到的库。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import xarray as xr

xr.set_options(display_style="text")

Concatenate

想要沿着已经存在或新的维度将数组合并为一个更大的数组,可以使用 concat()concat 接收一个可迭代的 DataArrayDataset 对象,以及一个维度名称,沿着该维度进行连接。

arr = xr.DataArray(
    np.random.randn(2, 3),
    [
        ('x', ['a', 'b']), 
        ('y', [10, 20, 30])
    ]
)
arr[:, :1]
<xarray.DataArray (x: 2, y: 1)>
array([[0.89269944],
       [0.05413846]])
Coordinates:
  * x        (x) <U1 'a' 'b'
  * y        (y) int64 10

类似于使用 np.concatenate 的方式

xr.concat([arr[:, :1], arr[:, 1:]], dim='y')
<xarray.DataArray (x: 2, y: 3)>
array([[ 0.89269944,  0.73344603, -0.96442539],
       [ 0.05413846, -2.15066399, -1.54335184]])
Coordinates:
  * x        (x) <U1 'a' 'b'
  * y        (y) int64 10 20 30

除了沿现有维度合并外,concat 可以通过将较低维度的数组堆叠在一起来创建新维度。

arr[0]
<xarray.DataArray (y: 3)>
array([ 0.89269944,  0.73344603, -0.96442539])
Coordinates:
    x        <U1 'a'
  * y        (y) int64 10 20 30

想要将一维数组合并为二维数组,可以用 np.array

xr.concat([arr[0], arr[1]], "x")
<xarray.DataArray (x: 2, y: 3)>
array([[ 0.89269944,  0.73344603, -0.96442539],
       [ 0.05413846, -2.15066399, -1.54335184]])
Coordinates:
  * y        (y) int64 10 20 30
  * x        (x) object 'a' 'b'

如果 concat 的第二个参数是一个新的维度名称,数据将会沿着该维度连接,该维度将成为第一个维度。

xr.concat([arr[0], arr[1]], 'new_dim')
<xarray.DataArray (new_dim: 2, y: 3)>
array([[ 0.89269944,  0.73344603, -0.96442539],
       [ 0.05413846, -2.15066399, -1.54335184]])
Coordinates:
  * y        (y) int64 10 20 30
    x        (new_dim) <U1 'a' 'b'
Dimensions without coordinates: new_dim

concat 第二个参数也可以是 IndexDataArray 对象,或者字符串,这种情况下,将用于标记新维度。

xr.concat([arr[0], arr[1]], pd.Index([-90, -100], name='new_dim'))
<xarray.DataArray (new_dim: 2, y: 3)>
array([[ 0.89269944,  0.73344603, -0.96442539],
       [ 0.05413846, -2.15066399, -1.54335184]])
Coordinates:
  * y        (y) int64 10 20 30
    x        (new_dim) <U1 'a' 'b'
  * new_dim  (new_dim) int64 -90 -100

当然,concat 也可以用在 Dataset 对象中。

ds = arr.to_dataset(name='foo')
xr.concat([ds.sel(x='a'), ds.sel(x='b')], 'x')
<xarray.Dataset>
Dimensions:  (x: 2, y: 3)
Coordinates:
  * y        (y) int64 10 20 30
  * x        (x) object 'a' 'b'
Data variables:
    foo      (x, y) float64 0.8927 0.7334 -0.9644 0.05414 -2.151 -1.543

concat 有一些参数,可以更深入地控制变量如何连接以及如何处理数据集之间的变量冲突。 使用默认参数时,xarray 将在内存中加载部分坐标变量,用于不同数据集间的比较。 如果通过使用 Dask 并行计算来延迟操纵数据集,这可能会导致过高的代价。

实战

使用 nwpc-oper/nwpc-data 封装的 cfgrib 接口加载数据,使用该项目封装的数据查找接口在 CMA-PI 上查找业务系统生成的数据文件。

from nwpc_data.grib.cfgrib import load_field_from_file
from nwpc_data.data_finder import find_local_file

从 000 时效文件中加载 4 个层次的温度场。

temp_vars = []
for level in [500, 700, 850, 900]:
    t = load_field_from_file(
        file_path=find_local_file(
            "grapes_gfs_gmf/grib2/orig",
            start_time="2020031800",
            forecast_time="0h"
        ),
        parameter="t",
        level_type="isobaricInhPa",
        level=level,
    )
    temp_vars.append(t)

沿层次坐标 isobaricInhPa 连接

xr.concat(temp_vars, dim="isobaricInhPa")
<xarray.DataArray 't' (isobaricInhPa: 4, latitude: 720, longitude: 1440)>
array([[[232.26372, 232.00372, 232.04172, ..., 232.08672, 232.11572,
         231.90472],
        ...skip...
        [238.72554, 238.78555, 238.74554, ..., 238.51555, 238.93555,
         238.80554]]], dtype=float32)
Coordinates:
    time           datetime64[ns] 2020-03-18
    step           timedelta64[ns] 00:00:00
    valid_time     datetime64[ns] 2020-03-18
  * latitude       (latitude) float64 89.88 89.62 89.38 ... -89.38 -89.62 -89.88
  * longitude      (longitude) float64 0.0 0.25 0.5 0.75 ... 359.2 359.5 359.8
  * isobaricInhPa  (isobaricInhPa) int64 500 700 850 900
Attributes:
    GRIB_paramId:                             130
    ...skip...
    standard_name:                            air_temperature

使用一个新的维度 level 连接

xr.concat(temp_vars, dim="level")
<xarray.DataArray 't' (level: 4, latitude: 720, longitude: 1440)>
array([[[232.26372, 232.00372, 232.04172, ..., 232.08672, 232.11572,
         231.90472],
        ...skip...
        [238.72554, 238.78555, 238.74554, ..., 238.51555, 238.93555,
         238.80554]]], dtype=float32)
Coordinates:
    time           datetime64[ns] 2020-03-18
    step           timedelta64[ns] 00:00:00
    valid_time     datetime64[ns] 2020-03-18
  * latitude       (latitude) float64 89.88 89.62 89.38 ... -89.38 -89.62 -89.88
  * longitude      (longitude) float64 0.0 0.25 0.5 0.75 ... 359.2 359.5 359.8
    isobaricInhPa  (level) int64 500 700 850 900
Dimensions without coordinates: level
Attributes:
    GRIB_paramId:                             130
    ...skip...
    standard_name:                            air_temperature

使用 pandas.Index 作为参数

xr.concat(
    temp_vars, 
    pd.Index(["500hPa", "700hPa", "850hPa", "900hPa"], name="level"),
)
<xarray.DataArray 't' (level: 4, latitude: 720, longitude: 1440)>
array([[[232.26372, 232.00372, 232.04172, ..., 232.08672, 232.11572,
         231.90472],
        ...skip...
        [238.72554, 238.78555, 238.74554, ..., 238.51555, 238.93555,
         238.80554]]], dtype=float32)
Coordinates:
    time           datetime64[ns] 2020-03-18
    step           timedelta64[ns] 00:00:00
    valid_time     datetime64[ns] 2020-03-18
  * latitude       (latitude) float64 89.88 89.62 89.38 ... -89.38 -89.62 -89.88
  * longitude      (longitude) float64 0.0 0.25 0.5 0.75 ... 359.2 359.5 359.8
    isobaricInhPa  (level) int64 500 700 850 900
  * level          (level) object '500hPa' '700hPa' '850hPa' '900hPa'
Attributes:
    GRIB_paramId:                             130
    ...skip...
    standard_name:                            air_temperature

参考

http://xarray.pydata.org/en/stable/combining.html

https://github.com/nwpc-oper/nwpc-data