在xarray中过滤数据的简洁方法

问题描述 投票:0回答:4

我需要对 xarray 数组中的值应用一个非常简单的“匹配语句”:

  1. 当值 > 0 时,设为 2
  2. 当值 == 0 时,设为 0
  3. 当值为
    NaN
    时,使
    NaN

这是我当前的解决方案。我正在使用

NaN
.fillna
和类型强制来代替 2d 索引。

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

在 pandas 中

df[df>0] = 2
就足够了。我肯定在做一些平淡无奇的事情,并且有更简洁的方法吗?

python python-xarray
4个回答
17
投票

xarray 现在支持

.where(condition, other)
,所以现在有效:

result = date_by_items.where(date_by_items > 0, 2)

5
投票

如果您愿意将数据作为 NumPy 数组加载到内存中,则可以使用 NumPy 修改 DataArray 值:

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

处理这个问题的最干净的方法是 xarray 支持

other
参数到
where
,但我们还没有实现(希望很快 - 基础工作已经奠定了!)。当它起作用时,你就可以写
date_by_items.where(date_by_items > 0, 2)

无论哪种方式,您都需要执行此操作两次才能应用您的两个标准。


0
投票

确实可以使用

where(condition, other)
方法。但请注意,当条件为 false 时,将使用
other
参数。因此,其他答案中的行为是不正确的,因为他们会将 2 放在 date_by_items > 0
 成立的地方。
>>> date = list(range(0,6))
>>> item = list(range(0,5))
>>> date_by_items = xr.DataArray(np.asarray((list(range(3)) * 10)).reshape(6,5), coords=[date, item], dims=('date','item'))
>>> date_by_items
<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


>>> date_by_items.where(date_by_items > 0, 2)  # wrong behavior
<xarray.DataArray (date: 6, item: 5)>
array([[2, 1, 2, 2, 1],
       [2, 2, 1, 2, 2],
       [1, 2, 2, 1, 2],
       [2, 1, 2, 2, 1],
       [2, 2, 1, 2, 2],
       [1, 2, 2, 1, 2]])
Coordinates:
  * date     (date) int64 0 1 2 3 4 5
  * item     (item) int64 0 1 2 3 4

相反,当您想要请求的行为时,您必须反转条件或使用 

xarray.where(condition, x, y) 方法

>>> date_by_items.where(date_by_items <= 0, 2) # inverted condition <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 >>> xarray.where(date_by_items > 0, 2, date_by_items) <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



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

    

© www.soinside.com 2019 - 2024. All rights reserved.