Краткий способ фильтрации данных в xarray

Мне нужно применить очень простой «оператор соответствия» к значениям в массиве xarray:

  1. Где значение > 0, сделайте 2
  2. Где значение == 0, сделать 0
  3. Где значение NaN, сделайте NaN

Вот мое текущее решение. Я использую NaNs, .fillna и приведение типов вместо двухмерной индексации.

valid = date_by_items.notnull()
positive = date_by_items > 0
positive = positive * 2
result = positive.fillna(0.).where(valid)
result

Это меняет это:

In [20]: date_by_items = xr.DataArray(np.asarray((list(range(3)) * 10)).reshape(6,5), dims=('date','item'))
    ...: date_by_items
    ...: 
Out[20]: 
<xarray.DataArray (date: 6, item: 5)>
array([[0, 1, 2, 0, 1],
       [2, 0, 1, 2, 0],
       [1, 2, 0, 1, 2],
       [0, 1, 2, 0, 1],
       [2, 0, 1, 2, 0],
       [1, 2, 0, 1, 2]])
Coordinates:
  * date     (date) int64 0 1 2 3 4 5
  * item     (item) int64 0 1 2 3 4

... к этому:

Out[22]: 
<xarray.DataArray (date: 6, item: 5)>
array([[ 0.,  2.,  2.,  0.,  2.],
       [ 2.,  0.,  2.,  2.,  0.],
       [ 2.,  2.,  0.,  2.,  2.],
       [ 0.,  2.,  2.,  0.,  2.],
       [ 2.,  0.,  2.,  2.,  0.],
       [ 2.,  2.,  0.,  2.,  2.]])
Coordinates:
  * date     (date) int64 0 1 2 3 4 5
  * item     (item) int64 0 1 2 3 4

В то время как в пандах df[df>0] = 2 было бы достаточно. Конечно, я делаю что-то пешеходное, и есть более лаконичный способ?


person Maximilian    schedule 10.08.2016    source источник


Ответы (2)


xarray теперь поддерживает .where(condition, other), так что теперь это допустимо:

result = date_by_items.where(date_by_items > 0, 2)
person Maximilian    schedule 23.03.2018

Если вы готовы загружать свои данные в память в виде массива NumPy, вы можете изменить значения DataArray на месте с помощью NumPy:

date_by_items.values[date_by_items.values > 0] = 2

Самый чистый способ справиться с этим был бы, если бы xarray поддерживал аргумент other для where, но мы еще не реализовали это (надеюсь, скоро - основа заложена!). Когда это сработает, вы сможете написать date_by_items.where(date_by_items > 0, 2).

В любом случае вам нужно будет сделать это дважды, чтобы применить оба ваших критерия.

person shoyer    schedule 10.08.2016