首页
学习
活动
专区
圈层
工具
发布

xarray | 数据结构(1)

本来是作为一部分内容的,但是推送有字数限制。因此拆分为三个部分,每部分都是单独的内容,基本不影响阅读。

DataArray

xarray.DataArray 是 xarray 库中带标签的多维数组。具有如下特性:

  • values: 包含数组值的 numpy.ndarray
  • dims: 每个轴的维度名 (比如: ('x', 'y', 'z'))
  • coords: 包含了每一个点信息的类字典容器 (比如:数字,日期或字符串1D数组)
  • attrs:包含元数据信息

xarray 使用 dims 和 coords 实现核心的元数据操作。维度提供了xarray使用的维度名称,从而代替大多数 numpy 函数所使用的 axis(轴) 参数。基于 pandas 中 DataFrame 和 Series 的索引功能,坐标可进行更快速的索引和对齐操作。

DataArray 对象有 name 和 attrs 属性,attrs 包含了元数据信息。名称和属性严格应用于用户代码,并且xarray 不会试图解释这些信息,仅在特定情况下才会传播这些信息。

创建 DataArray

DataArray 构造器使用以下参数:

  • data : 多维数组值 (比如:numpy.ndarray, Series, DataFrame, Panel)
  • coords: 坐标字典或列表
  • dims : 维度名,如果缺省的话,可能会从 coords 中获取维度名信息,否则会默认指定维度名:dim_+数字
  • attrs : 属性字典
  • name:实例名称
代码语言:javascript
复制
# 加载库
import pandas as pd
import numpy as np
import xarray as xr
代码语言:javascript
复制
data = np.random.rand(4, 3)
locs = ['IA', 'IL', 'IN']
times = pd.date_range('2000-01-01', periods=4)
foo = xr.DataArray(data, coords=[times, locs], dims=['time', 'space'])

变量 foo 包含的信息如下:

代码语言:javascript
复制
<xarray.DataArray (time: 4, space: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Coordinates:
  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * space    (space) <U2 'IA' 'IL' 'IN'

如果不指定 dims 的话,foo变量信息:

代码语言:javascript
复制
<xarray.DataArray (dim_0: 4, dim_1: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Coordinates:
  * dim_0    (dim_0) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * dim_1    (dim_1) <U2 'IA' 'IL' 'IN'

坐标信息的维度名称会指定为默认值。

通过属性可以获取 foo 数组中的变量信息:

代码语言:javascript
复制
>> foo.dims
('dim_0', 'dim_1')

>> foo.dim_0
<xarray.DataArray 'dim_0' (dim_0: 4)>
array(['2000-01-01T00:00:00.000000000', '2000-01-02T00:00:00.000000000',
       '2000-01-03T00:00:00.000000000', '2000-01-04T00:00:00.000000000'], dtype='datetime64[ns]')
Coordinates:
  * dim_0    (dim_0) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04

>> foo.dim_0.data
array(['2000-01-01T00:00:00.000000000', '2000-01-02T00:00:00.000000000',
       '2000-01-03T00:00:00.000000000', '2000-01-04T00:00:00.000000000'], dtype='datetime64[ns]')

>> foo.dim_0.data.shape
(4,)

因为每个维度的变量数组是 numpy.ndarray 数组,因此获取信息的方式和numpy中操作数组方式相同。

除了 data 参数是必须的外,其余参数均会指定默认值。

代码语言:javascript
复制
>> xr.DataArray(data)
<xarray.DataArray (dim_0: 4, dim_1: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Dimensions without coordinates: dim_0, dim_1

如上所示,维度名总是出现在 xarray 数组中。如果维度名缺省,默认以dim_N的方式创建。坐标是可选的,而且维度不会自动扩展坐标标签。

注:

和 pandas 不同的是,pandas 中默认的轴标签总是以 0, ..., n-1的整数。 在 V0.9之前,xarray会仿照这种方式:如果没有指定坐标参数的话,xarray会提供默认值。

以下方式可以指定坐标信息:

  • 值列表和维度数大小相同,为每个维度提供坐标标签。每个值必须是以下形式:
    • DataArray 或 Variable
    • (dims, data [, attrs]) 形式的元组,然后被转换为 Variable 的参数
    • 被转换为 DataArray 的 pandas 对象或标量
    • 1D数组或列表 (与坐标名称相同的维度名对应的1D坐标变量的值)
  • {coord_name: coord} 字典,值与列表形式相同。如果使用 coords 作为字典,必须明确指定 dims,否则会出错。

元组形式:

代码语言:javascript
复制
>> xr.DataArray(data, coords=[('time', times), ('space', locs)])
<xarray.DataArray (time: 4, space: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Coordinates:
  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * space    (space) <U2 'IA' 'IL' 'IN'

字典形式:

代码语言:javascript
复制
>> xr.DataArray(data, coords={'time': times, 'space': locs, 'const': 42, 'ranking': ('space', [1, 2, 3])},
 dims=['time', 'space'])

<xarray.DataArray (time: 4, space: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Coordinates:
    ranking  (space) int32 1 2 3
  * space    (space) <U2 'IA' 'IL' 'IN'
  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
    const    int32 42

如果不明确指定 dims 参数的话,则会出错:

代码语言:javascript
复制
>> xr.DataArray(data, coords={'time': times, 'space': locs, 'const': 42, 'ranking': ('space', [1, 2, 3])})

ValueError: coordinate ranking has dimensions ('space',), but these are not a subset of the DataArray dimensions ('dim_0', 'dim_1')

跨越多个维度的坐标的字典形式

代码语言:javascript
复制
ds = xr.DataArray(data, coords={'time': times, 'space': locs, 'const': 42,
                            'ranking': (('time', 'space'), np.arange(12).reshape(4,3))},
              dims=['time', 'space'])<xarray.DataArray (time: 4, space: 3)>
代码语言:javascript
复制
<xarray.DataArray (time: 4, space: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Coordinates:
    ranking  (time, space) int32 0 1 2 3 4 5 6 7 8 9 10 11
  * space    (space) <U2 'IA' 'IL' 'IN'
  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
    const    int32 42

上述 coords 字典中,ranking 的值是以元组的形式给定的:

代码语言:javascript
复制
>> ds.ranking
<xarray.DataArray 'ranking' (time: 4, space: 3)>
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
Coordinates:
    ranking  (time, space) int32 0 1 2 3 4 5 6 7 8 9 10 11
  * space    (space) <U2 'IA' 'IL' 'IN'
  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
    const    int32 42

如果使用 pandas 的 Series,DataFrame或Panel来创建 DataArray,其它没有指定数值的参数都会用 pandas 对象填充:

代码语言:javascript
复制
>> df = pd.DataFrame({'x': [0, 1], 'y': [2, 3]}, index=['a', 'b'])
>> df.index.name = 'abc'
>> df.columns.name = 'xyz'
>> df
xyz   x   y
abc     
a   0   2
b   1   3

>> xr.DataArray(df)
<xarray.DataArray (abc: 2, xyz: 2)>
array([[0, 2],
       [1, 3]], dtype=int64)
Coordinates:
  * abc      (abc) object 'a' 'b'
  * xyz      (xyz) object 'x' 'y'

DataArray 属性

下面看一下 DataArray 数组的一些重要属性:

代码语言:javascript
复制
>> foo.values
array([[ 0.70391552,  0.14570178,  0.62329702],
       [ 0.60670694,  0.69258581,  0.68338181],
       [ 0.70963331,  0.03819467,  0.31418265],
       [ 0.82451064,  0.31041086,  0.81095621]])

>> foo.dims
('dim_0', 'dim_1')

>> foo.coords
Coordinates:
  * dim_0    (dim_0) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * dim_1    (dim_1) <U2 'IA' 'IL' 'IN'

>> foo.attrs
OrderedDict()

利用 values 属性可以直接修改其数值:

代码语言:javascript
复制
foo.values = 2.0 * foo.values

注:

DataArray 中的数值具有相同的类型。如果要对相同类型的数值进行操作的话,需要使用坐标或是分离DataArray对象为单个的Dataset。

使用 DataArray 构造数组时,如果一开始有些属性没有给出的话,可以对其赋值指定:

代码语言:javascript
复制
>> foo.name = 'foo'
>> foo.attrs['units'] = 'meters'
>> foo
<xarray.DataArray 'foo' (dim_0: 4, dim_1: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Coordinates:
  * dim_0    (dim_0) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * dim_1    (dim_1) <U2 'IA' 'IL' 'IN'
Attributes:
    units:    meters

还可以使用 rename 方法进行重命名操作,这不会改变原变量的信息,而是新创建一个变量

代码语言:javascript
复制
>> foo.rename('bar')
<xarray.DataArray 'bar' (dim_0: 4, dim_1: 3)>
array([[ 0.703916,  0.145702,  0.623297],
       [ 0.606707,  0.692586,  0.683382],
       [ 0.709633,  0.038195,  0.314183],
       [ 0.824511,  0.310411,  0.810956]])
Coordinates:
  * dim_0    (dim_0) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * dim_1    (dim_1) <U2 'IA' 'IL' 'IN'
Attributes:
    units:    meters

DataArray坐标

coords 属性是类字典变量。通过指定名称可以获取但坐标信息,或是通过数组索引。

代码语言:javascript
复制
>> foo.coords['dim_0']
<xarray.DataArray 'dim_0' (dim_0: 4)>
array(['2000-01-01T00:00:00.000000000', '2000-01-02T00:00:00.000000000',
       '2000-01-03T00:00:00.000000000', '2000-01-04T00:00:00.000000000'], dtype='datetime64[ns]')
Coordinates:
  * dim_0    (dim_0) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04

>> foo['dim_0']
<xarray.DataArray 'dim_0' (dim_0: 4)>
array(['2000-01-01T00:00:00.000000000', '2000-01-02T00:00:00.000000000',
       '2000-01-03T00:00:00.000000000', '2000-01-04T00:00:00.000000000'], dtype='datetime64[ns]')
Coordinates:
  * dim_0    (dim_0) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04

DataArray 对象的每个维度都可以包含标签。

通过类似字典操作的语法可以设置或删除坐标。

代码语言:javascript
复制
>> foo['ranking'] = ('space', [1, 2, 3])
>> foo.coords 
Coordinates:
  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * space    (space) <U2 'IA' 'IL' 'IN'
    ranking  (space) int64 1 2 3

>>del foo['ranking']
>> foo.coords 
Coordinates:
  * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03 2000-01-04
  * space    (space) <U2 'IA' 'IL' 'IN'
举报
领券