0

我有一个 numpy 掩码的数据数组:

data = masked_array(data = [7 -- 7 1 8 -- 1 1 -- -- 3 -- -- 3 --],
                    mask = [False True False False False True False False True True False True True False True])

我有一个特定类型数据的标志,它是一个布尔掩码数组:

flag = masked_array(data = [True False False True -- -- -- False -- True -- -- -- -- True],
                    mask = [False False False False True True True False True False True True True True False])

我想做类似的事情data[flag]并获得以下输出:

output_wanted = [7 1 -- --]

它对应于标志为 True 的数据元素。相反,我得到了这个:

output_real = [7 -- 7 1 8 -- 1 1 -- -- 3 -- -- 3 --]

为了更清楚,我没有复制输出的掩码。

我不介意输出带有标志大小的输出,只要它选择我想要的数据(对应于标志的 True 值的数据)。但我无法弄清楚为什么它会在实际输出中给出这些值!

4

3 回答 3

2

怎么样的东西:

import numpy as np
from numpy.ma import masked_array

data = masked_array(data = [7,     0,     7,     1,     8,     0,    1,     1,     0,    0,     3,     0,    0,    3,     0],
                    mask = [False, True,  False, False, False, True, False, False, True, True,  False, True, True, False, True])
flag = masked_array(data = [True,  False, False, True,  0,     0,    0,     False, 0,    True,  0,     0,    0,    0,     True],
                    mask = [False, False, False, False, True,  True, True,  False, True, False, True,  True, True, True,  False])

print(repr(data))
print(repr(flag))

indices = np.where(flag & ~flag.mask)
print(data[indices])

flag请注意,如果无法将 中的掩码值与 进行比较,您可能会遇到麻烦&,但您的情况似乎并非如此。

输出:

masked_array(数据 = [7 -- 7 1 8 -- 1 1 -- -- 3 -- -- 3 --],
             掩码 = [假真假假假真假假真真假真真假真],
       填充值 = 999999)

masked_array(数据 = [1 0 0 1 -- -- -- 0 -- 1 -- -- -- -- 1],
             掩码 = [假假假假真真真假真假真真真真假],
       填充值 = 999999)

[7 1 -- --]

编辑:

获取索引的另一种方法也可能是:

indices = np.where(flag.filled(False))

更新(编辑 2):

注意使用数组索引数组的微妙之处。

考虑以下代码:

import numpy as np

data = np.array([1,2,3,4,5])
mask = np.array([True, False, True, False, True])

res  = data[mask]
print(res)

正如您可能(或可能不会)期望的那样,在这里,掩码用作“过滤器”,过滤掉掩码中相应位置为 False 的数据元素。由于我为dataand选择的值mask,其效果是索引用于过滤掉偶data数值,只留下奇数值。

这里的输出是:[1 3 5].

现在,考虑非常相似的代码:

import numpy as np

data = np.array([1,2,3,4,5])
mask = np.array([1, 0, 1, 0, 1])

res  = data[mask]
print(res)

在这里,唯一改变的是掩码元素的数据类型,它们的布尔值是相同的。我们称第一个掩码(由True/False值组成)mask1和第二个掩码(由1/0值组成)mask2

dtype您可以通过属性(例如print(mask.dtype)) 检查数组的数据类型。mask1具有 dtype bool,而mask2具有 dtype int32

但是,这里的输出是不同的: [2 1 2 1 2] .

这里发生了什么?

事实上,索引的行为因用于索引的数组的数据类型而异。如前所述,当“掩码”的数据类型为布尔值时,它具有过滤功能。但是当“掩码”的数据类型是整数时,它提供“选择”功能,使用索引的元素作为原始数组的索引。

因此,在第二个示例中,由于data[1] = 2data[0] = 1的结果data[mask2]是长度为 5 的数组,而不是 3(在布尔情况下)。

换句话说,给定以下代码:

res = data[mask]

如果mask.dtype == int, res 的长度将等于 mask 的长度。

如果mask.dtype == bool, res 的长度将等于Truemask 中值的数量。

很不一样。

astype最后,您可以使用该方法将一种数据类型的数组强制转换为另一种数据类型。

演示片段:

import numpy as np

data = np.array([1,2,3,4,5])

# Create a boolean mask
mask1 = np.array([True, False, True, False, True])

# Create an integer "mask", using the same logical values 
mask2 = np.array([1,0,1,0,1])

# Coerce mask2 into a boolean mask
mask3 = mask2.astype(bool)

print(data)         # [1 2 3 4 5]
print("-" * 80)
print(mask1)        # [True  False  True  False  True]
print(mask1.dtype)  # bool
print(data[mask1])  # [1 3 5]
print("-" * 80)
print(mask2)        # [1 0 1 0 1]
print(mask2.dtype)  # int32
print(data[mask2])  # [2 1 2 1 2]
print("-" * 80)
print(mask3)        # [True  False  True  False  True]
print(mask3.dtype)  # bool
print(data[mask3])  # [1 3 5]
于 2016-07-19T10:17:25.400 回答
1

如果我用以下方法重建你的数组:

In [28]: d=np.ma.masked_equal([7,0,7,1,8,0,1,1,0,0,3,0,0,3,0],0)

In [29]: f=np.ma.MaskedArray([True,False,False,True, False,False,False,False,True,True,True,True,True,True,True],[False, False, False, False, True, True, True, False, True, False, True, True, True, True, False])

In [30]: d
Out[30]: 
masked_array(data = [7 -- 7 1 8 -- 1 1 -- -- 3 -- -- 3 --],
             mask = [False  True False False False  True False False  True  True False  True
  True False  True],
       fill_value = 0)

In [31]: f
Out[31]: 
masked_array(data = [True False False True -- -- -- False -- True -- -- -- -- True],
             mask = [False False False False  True  True  True False  True False  True  True
  True  True False],
       fill_value = True)

蒙面显示匹配,但我猜蒙面值是什么。

In [32]: d[f]
Out[32]: 
masked_array(data = [7 1 -- -- 3 -- -- 3 --],
             mask = [False False  True  True False  True  True False  True],
       fill_value = 0)

In [33]: d[f.data]
Out[33]: 
masked_array(data = [7 1 -- -- 3 -- -- 3 --],
             mask = [False False  True  True False  True  True False  True],
       fill_value = 0)

索引与使用其属性f索引相同。data它的面具什么也没做。显然我的蒙面价值观与你的不同。

但是如果我用filled数组索引,我会得到所需的数组:

In [34]: d[f.filled(False)]
Out[34]: 
masked_array(data = [7 1 -- --],
             mask = [False False  True  True],
       fill_value = 0)

filled在代码中被大量使用np.ma,根据np操作使用不同的填充值(例如,0 表示 sum v 1 表示产品)。掩码数组通常不会遍历它们的值而跳过掩码数组;相反,他们将屏蔽的值转换为无害的值,并使用常规的 numpy 操作。另一种策略是使用 删除掩码值compressed

indices = np.where(flag.filled(False))在另一个答案中提到了,但普通的布尔形式也可以。

掩码数组具有dataandmask属性。屏蔽不会data直接更改值。该任务留给诸如filled.

于 2016-07-19T20:06:53.617 回答
0

我弄清楚了使用掩码数组进行索引的工作原理。

事实上,python 并不处理这种索引。

data[flag]当使用布尔掩码数组执行类似操作时flag,python 会获取flag. 换句话说,它在被屏蔽之前获取被屏蔽值的值。

所以要注意:如果掩码值没有用它们明确填充fill_value,索引可能看起来是随机的。

例子:

>>> arr = np.array([0, 1, 2, 3, 4])
>>> flag = np.ma.masked_array([True, False, False, True, True],
                              [False, True, False, False, True])

>>> arr[flag])
array([0, 3, 4])

一种方法就像 jedwards answer。

但我认为应该避免使用掩码数组来标记数据,它不会带来足够的洞察力。

对于用于访问某种类型数据的标志数组,应将掩码值设置为False. 例如,如果您想插入未标记的数据。

如果标志数组用于屏蔽某种类型的数据,屏蔽值应设置为True。

于 2016-07-19T12:29:11.890 回答