переменная xarray из списка списков разной длины

У меня есть функция для создания набора данных xarray на основе различных выходных данных модели. Одна из частей информации, которую я собираю, — это список списков (разной длины). Эта переменная называется cids и имеет ту же размерность repo_id, что и другие переменные.

До сих пор следующее всегда работало нормально:

datetime = pd.date_range('20010101', periods=100, freq='D')
obs = [xr.DataArray(np.random.rand(100), dims={'datetime': datetime}),xr.DataArray(np.random.rand(100), dims={'datetime':datetime}) ]
cids = [[1, 2, 3], [1, 2, 3, 4]]
keys = np.array([['A', 'A', 'B'], ['C', 'D', 'E']])
xr.Dataset({'obs': (['repo_id', 'datetime'], np.array(obs)), 'cig_id': ('repo_id', keys[:, 0]), 'repo': ('repo_id', keys[:, 2]), 'cids': ('repo_id', cids)},  coords={'repo_id': keys[:, 1], 'datetime': obs[0].datetime})

Это дает следующие результаты, как и ожидалось:

<xarray.Dataset>
Dimensions:   (datetime: 100, repo_id: 2)
Coordinates:
  * repo_id   (repo_id) <U1 'A' 'D'
  * datetime  (datetime) int64 0 1 2 3 4 5 6 7 8 ... 91 92 93 94 95 96 97 98 99
Data variables:
    obs       (repo_id, datetime) float64 0.9393 0.468 0.7168 ... 0.03513 0.8771
    cig_id    (repo_id) <U1 'A' 'C'
    repo      (repo_id) <U1 'B' 'E'
    cids      (repo_id) object [1, 2, 3] [1, 2, 3, 4]

Однако недавно у меня был случай, когда длина списков в моей переменной cids была одинаковой:

datetime = pd.date_range('20010101', periods=100, freq='D')
obs = [xr.DataArray(np.random.rand(100), dims={'datetime': datetime}),xr.DataArray(np.random.rand(100), dims={'datetime':datetime}) ]
# see here that length of elements in cids are both equal
cids = [[1, 2, 3], [1, 2, 3]]
keys = np.array([['A', 'A', 'B'], ['C', 'D', 'E']])
xr.Dataset({'obs': (['repo_id', 'datetime'], np.array(obs)), 'cig_id': ('repo_id', keys[:, 0]), 'repo': ('repo_id', keys[:, 2]), 'cids': ('repo_id', cids)},  coords={'repo_id': keys[:, 1], 'datetime': obs[0].datetime})

Что выдает следующую ошибку:

cids = [[1, 2, 3], [1, 2, 3]]
keys = np.array([['A', 'A', 'B'], ['C', 'D', 'E']])
xr.Dataset({'obs': (['repo_id', 'datetime'], np.array(obs)), 'cig_id': ('repo_id', keys[:, 0]), 'repo': ('repo_id', keys[:, 2]), 'cids': ('repo_id', cids)},  coords={'repo_id': keys[:, 1], 'datetime': obs[0].datetime})
Traceback (most recent call last):
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/variable.py", line 107, in as_variable
    obj = Variable(*obj)
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/variable.py", line 309, in __init__
    self._dims = self._parse_dimensions(dims)
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/variable.py", line 503, in _parse_dimensions
    "number of data dimensions, ndim=%s" % (dims, self.ndim)
ValueError: dimensions ('repo_id',) must have the same length as the number of data dimensions, ndim=2
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 3331, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-48-9a2b518ac4d3>", line 2, in <module>
    xr.Dataset({'obs': (['repo_id', 'datetime'], np.array(obs)), 'cig_id': ('repo_id', keys[:, 0]), 'repo': ('repo_id', keys[:, 2]), 'cids': ('repo_id', cids)},  coords={'repo_id': keys[:, 1], 'datetime': obs[0].datetime})
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/dataset.py", line 537, in __init__
    data_vars, coords, compat="broadcast_equals"
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/merge.py", line 467, in merge_data_and_coords
    objects, compat, join, explicit_coords=explicit_coords, indexes=indexes
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/merge.py", line 552, in merge_core
    collected = collect_variables_and_indexes(aligned)
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/merge.py", line 277, in collect_variables_and_indexes
    variable = as_variable(variable, name=name)
  File "/auto/anaconda3/envs/commod_staging/lib/python3.6/site-packages/xarray/core/variable.py", line 113, in as_variable
    "{} to Variable.".format(obj)
ValueError: Could not convert tuple of form (dims, data[, attrs, encoding]): ('repo_id', [[1, 2, 3], [1, 2, 3]]) to Variable.

Вклад будет оценен, не знаю, как лучше всего справиться с этим. Кажется, xarray пытается быть умным и предполагает, что размерность cids равна не repo_id длины два, а длине 3... ошибка??


person user5781    schedule 10.04.2020    source источник


Ответы (2)


В настоящее время в первом примере создается переменная cids, содержащая список:

In [6]: datetime = pd.date_range('20010101', periods=100, freq='D')
   ...: obs = [xr.DataArray(np.random.rand(100), dims={'datetime': datetime}),xr.DataArray(np.random.rand(100), dims={'datetime':datetime}) ]
   ...: cids = [[1, 2, 3], [1, 2, 3, 4]]
   ...: keys = np.array([['A', 'A', 'B'], ['C', 'D', 'E']])
   ...: xr.Dataset({'obs': (['repo_id', 'datetime'], np.array(obs)), 'cig_id': ('repo_id', keys[:, 0]), 'repo': ('repo_id', keys[:, 2]), 'cids': ('repo_id', cids)},  coords={'repo_id': keys[:, 1], 'datetime': obs[0].datetime})
   ...:
Out[6]:
<xarray.Dataset>
Dimensions:   (datetime: 100, repo_id: 2)
Coordinates:
  * repo_id   (repo_id) <U1 'A' 'D'
  * datetime  (datetime) int64 0 1 2 3 4 5 6 7 8 ... 91 92 93 94 95 96 97 98 99
Data variables:
    obs       (repo_id, datetime) float64 0.4451 0.9134 ... 0.8266 0.07039
    cig_id    (repo_id) <U1 'A' 'C'
    repo      (repo_id) <U1 'B' 'E'
    cids      (repo_id) object [1, 2, 3] [1, 2, 3, 4]

In [9]: ds=_

In [11]: ds.cids
Out[11]:
<xarray.DataArray 'cids' (repo_id: 2)>
array([list([1, 2, 3]), list([1, 2, 3, 4])], dtype=object)  # <- here
Coordinates:
  * repo_id  (repo_id) <U1 'A' 'D'

Это намеренно? Как правило, вы хотите хранить одно значение по каждому измерению, а не список.

Я понимаю, что это запутанная пара случаев, потому что удивительно, что она будет работать для списков разного размера, но не для списков одинакового размера. Xarray пытается поместить значения в список по другому измерению и пропускает дополнительное измерение; не пытаясь сделать это для списков разного размера.

Сообщение об ошибке плохое. Но я не уверен, что бы я изменил в функциональности: потенциально это может вызвать ошибку в вашем первом примере, учитывая, что маловероятно, что кому-то нужны объекты, являющиеся списками.

person Maximilian    schedule 11.04.2020
comment
Спасибо за ответ. Да, поведение преднамеренное. «Cids» — это списки разной длины, но списков cid должно быть столько же, сколько repo_id. Мне не нужна переменная для каждого списка в cid, так как это создаст сотни переменных. По сути, я пытаюсь включить рваный массив. - person user5781; 14.04.2020

Я подозреваю, что это может быть не самый "xarrayonic" подход, но следующее, кажется, дает мне "исправление":

datetime = pd.date_range('20010101', periods=100, freq='D')
obs = [xr.DataArray(np.random.rand(100), dims={'datetime': datetime}),xr.DataArray(np.random.rand(100), dims={'datetime':datetime}) ]
# see here that length of elements in cids are both equal
## HERE IS THE FIX, CONVERT THEM TO SETS
cids = [set(_e) for _e in [[1, 2, 3], [1, 2, 3]]]

## THAT'S ALL
keys = np.array([['A', 'A', 'B'], ['C', 'D', 'E']])
xr.Dataset({'obs': (['repo_id', 'datetime'], np.array(obs)), 'cig_id': ('repo_id', keys[:, 0]), 'repo': ('repo_id', keys[:, 2]), 'cids': ('repo_id', cids)},  coords={'repo_id': keys[:, 1], 'datetime': obs[0].datetime})
person user5781    schedule 17.04.2020