объединить дополнительные DataArrays - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть список массивов данных с тремя измерениями. Для каждого элемента в списке два измерения являются одним значением, но комбинация всех элементов приведет к полному комбинаторному значению.

import itertools
import numpy as np
import xarray as xr

ds = []
for vals_dim1, vals_dim2 in itertools.product(list(range(2)), list(range(3))):
    d = xr.DataArray(np.random.rand(1, 1, 4),
                     coords={'dim1': [vals_dim1], 'dim2': [vals_dim2], 'dim3': range(4)},
                     dims=['dim1', 'dim2', 'dim3'])
    ds.append(d)

Затем я хочу объединить эти бесплатные DataArray, но ничего из того, что я пробовал до сих пор, похоже, не работает. Результат должен быть DataArray с формой |2x3x4| и размерами dim1: |2|, dim2: |3|, dim3: |4|.

Следующие не работают:

# does not automatically infer dimensions and fails with
# "ValueError: conflicting sizes for dimension 'concat_dim': length 2 on 'concat_dim' and length 6 on <this-array>"
ds = xr.concat(ds, dim=['dim1', 'dim2'])

# will still try to insert a new `concat_dim` and fails with
# "ValueError: conflicting MultiIndex level name(s): 'dim1' (concat_dim), (dim1) 'dim2' (concat_dim), (dim2)"
import pandas as pd
dims = [[0] * 3 + [1] * 3, list(range(3)) * 2]
dims = pd.MultiIndex.from_arrays(dims, names=['dim1', 'dim2'])
ds = xr.concat(ds, dim=dims)

# fails with
# AttributeError: 'DataArray' object has no attribute 'data_vars'
ds = xr.auto_combine(ds)

1 Ответ

0 голосов
/ 02 мая 2018

К сожалению (как вы обнаружили здесь), вы в настоящее время не можете объединить несколько измерений одновременно в xarray.

Есть несколько способов обойти это. Наиболее эффективным будет stack() всех объектов в новом измерении, а затем unstack() после объединения:

>>> xr.concat([d.stack(z=['dim1', 'dim2']) for d in ds], 'z').unstack('z')
<xarray.DataArray (dim3: 4, dim1: 2, dim2: 3)>
array([[[0.300328, 0.544551, 0.751339],
        [0.612358, 0.937376, 0.67688 ]],

       [[0.065146, 0.85845 , 0.962857],
        [0.102126, 0.395406, 0.245373]],

       [[0.309324, 0.362568, 0.676552],
        [0.709206, 0.719578, 0.960803]],

       [[0.613187, 0.205054, 0.021796],
        [0.434595, 0.779576, 0.937855]]])
Coordinates:
  * dim3     (dim3) int64 0 1 2 3
  * dim1     (dim1) int64 0 1
  * dim2     (dim2) int64 0 1 2

(Здесь z - это заполнитель, на самом деле просто произвольное имя для временного нового измерения.)

Другой вариант - использовать merge(). Слияние немного неудобно для использования с объектами DataArray (мы должны это исправить), но это приведет к тому же результату:

>>> xr.merge([x.rename('z') for x in ds])['z'].rename(None)
<xarray.DataArray (dim1: 2, dim2: 3, dim3: 4)>
array([[[0.300328, 0.065146, 0.309324, 0.613187],
        [0.544551, 0.85845 , 0.362568, 0.205054],
        [0.751339, 0.962857, 0.676552, 0.021796]],

       [[0.612358, 0.102126, 0.709206, 0.434595],
        [0.937376, 0.395406, 0.719578, 0.779576],
        [0.67688 , 0.245373, 0.960803, 0.937855]]])
Coordinates:
  * dim1     (dim1) int64 0 1
  * dim2     (dim2) int64 0 1 2
  * dim3     (dim3) int64 0 1 2 3

(z здесь также указывается имя заполнителя.)

Обратите внимание, что merge использует алгоритм, отличный от concat, который распределяет полные выходные массивы для каждого аргумента. Так что это будет намного медленнее для больших массивов.

...