2

说我有以下二维数组

>>> import numpy as np
>>> budgets = np.array([
       [np.nan, 450.],
       [500.  , 100.],
       [np.nan, 900.],
    ])

其值的位置如下

>>> coords = [
        ('name' , ['Jack_teen' , 'John_adult', 'John_teen']), # over rows
        ('hobby', ['books', 'bicyle']),                       # over columns
    ]

使用xarray我可以创建一个二维标签数组,做

>>> import xarray as xr
>>> x = xr.DataArray(budgets, coords=coords)

因此,当约翰十几岁的时候,他不喜欢书,如果当时有预算,这是显而易见的

>>> x.sel(name='John_teen', hobby='books')
<xarray.DataArray ()>
array(nan)
Coordinates:
    name     |S10 'John_teen'
    hobby    |S6 'books'

什么随着年龄而改变

>>> x.sel(name='John_adult', hobby='books')
<xarray.DataArray ()>
array(500.0)
Coordinates:
    name     |S10 'John_adult'
    hobby    |S6 'books'


我的问题:

您将如何将这个 2dl-array 变成一个 3dl-array,它考虑一个名为的新维度age(其坐标将因此['adult','teen'])同时简化维度的坐标name

请注意,name的坐标始终使用分隔的下划线构成,我的意思是 NAME_AGE。当然,您开始执行此操作的对象是x.

是否有 xarray-builtin 方式来做到这一点?或者至少什么是最快/最便宜的方法?

4

2 回答 2

1

由于我们最终需要一个维度'name',因此我将当前重命名'name''name_age'

In [5]: x = x.rename({'name': 'name_age'})

我们可以MultiIndex直接从坐标值构造 a 并将其分配为堆叠DataArray坐标:

In [6]: x.coords['name_age'] = pd.MultiIndex.from_tuples(
   ...:     [tuple(s.split('_')) for s in x.coords['name_age'].values],
   ...:     names=['name', 'age'])

In [7]: x
Out[7]:
<xarray.DataArray (name_age: 3, hobby: 2)>
array([[  nan,  450.],
       [ 500.,  100.],
       [  nan,  900.]])
Coordinates:
  * name_age  (name_age) MultiIndex
  - name      (name_age) object 'Jack' 'John' 'John'
  - age       (name_age) object 'teen' 'adult' 'teen'
  * hobby     (hobby) |S6 'books' 'bicyle'

如果你然后 unstack ,你会得到你想要'name_age'的 3-D :DataArray

In [8]: x.unstack('name_age')
Out[8]:
<xarray.DataArray (hobby: 2, name: 2, age: 2)>
array([[[  nan,   nan],
        [ 500.,   nan]],

       [[  nan,  450.],
        [ 100.,  900.]]])
Coordinates:
  * hobby    (hobby) |S6 'books' 'bicyle'
  * name     (name) object 'Jack' 'John'
  * age      (age) object 'adult' 'teen'
于 2017-09-14T00:30:35.723 回答
0

实际上,这种肮脏的方法是我要做的,但这并不是最好的解决方案。

首先,让这个 2dl-array 变成一个由元组键组成的字典。

dict_ = {}
for hobby in x['hobby'].data:
    for name_age in x['name'].data:
        name,age = name_age.split('_')
        dict_[(hobby, name, age,)] = x.sel(name=name_age, hobby=hobby).data

这些值所在的空间由以下维度列表构成:['hobby', 'name', 'age']。让分配它

>>> space = ['hobby', 'name', 'age']

然后,可以使用pandasMultiIndexfrom_tuples对象的方法来构建我们数据的布尔定位结构

>>> import pandas as pd 
>>> index = pd.MultiIndex.from_tuples(dict_.keys(), names=space)    

最后,

>>> hyper_x = pd.Series(dict_, index=index).to_xarray()

因此

>>> hyper_x.sel(name='John', age='teen', hobby='books')
<xarray.DataArray ()>
array(nan)
Coordinates:
    hobby    |S5 'books'
    name     |S4 'John'
    age      |S4 'teen'
>>> hyper_x.sel(name='John', age='adult', hobby='books')
<xarray.DataArray ()>
array(500.0)
Coordinates:
    hobby    |S5 'books'
    name     |S4 'John'
    age      |S5 'adult'


这种方法的优点是它可以很容易地推广到任意数量的维度,无论是x还是hyper_x。它也可以用来降低维度。

于 2017-09-06T22:57:46.133 回答