python 使用布尔掩码数组进行花式索引
python fancy indexing with a boolean masked array
我有一个 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 -- --]
对应flag为True的数据元素。相反,我得到这个:
output_real = [7 -- 7 1 8 -- 1 1 -- -- 3 -- -- 3 --]
为了更清楚起见,我没有复制输出的掩码。
我不介意有一个标志大小的输出,只要它选择我想要的数据(对应于标志的真值的数据)。但我不明白为什么它会在实际输出中给出这些值!
像这样的东西怎么样:
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(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 = 999999)
masked_array(data = [1 0 0 1 -- -- -- 0 -- 1 -- -- -- -- 1],
mask = [False False False False True True True False True False True True True True False],
fill_value = 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)
如你所料(也可能不料),这里mask起到了一个“过滤器”的作用,过滤掉mask中对应位置为False的数据元素。由于我为 data
和 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
的数据类型为 bool
,而 mask2
的数据类型为 int32
。
然而,这里的输出是不同的: [2 1 2 1 2]
.
这是怎么回事?
事实上,索引的行为因用于索引的数组的数据类型而异。如前所述,当“掩码”的数据类型为布尔值时,它具有过滤功能。但是当“掩码”的数据类型是整数时,它提供了一个“选择”功能,使用索引的元素作为原始数组的索引。
因此,在第二个示例中,由于 data[1] = 2
和 data[0] = 1
,data[mask2]
的结果是长度为 5 的数组,而不是 3(在布尔情况下)。
换句话说,给定以下代码:
res = data[mask]
如果mask.dtype == int
,res的长度将等于mask的长度。
如果mask.dtype == bool
,res的长度将等于mask中True
个值的个数。
差别很大。
最后,您可以使用 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]
我弄清楚了使用屏蔽数组进行索引的工作原理。
事实上,python不处理这种索引。
当使用 flag
布尔掩码数组执行类似 data[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。
如果我用以下方法重建你的数组:
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 表示求和 v 1 表示乘积)。屏蔽数组通常不会遍历它们的值而跳过屏蔽的数组;相反,他们将屏蔽的值转换为无害的值,并使用常规的 numpy 操作。另一种策略是使用 compressed
.
删除屏蔽值
indices = np.where(flag.filled(False))
在另一个答案中提到,但普通的布尔形式也同样有效。
掩码数组具有 data
和 mask
属性。屏蔽不会直接更改 data
值。该任务留给 filled
.
这样的方法
我有一个 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 -- --]
对应flag为True的数据元素。相反,我得到这个:
output_real = [7 -- 7 1 8 -- 1 1 -- -- 3 -- -- 3 --]
为了更清楚起见,我没有复制输出的掩码。
我不介意有一个标志大小的输出,只要它选择我想要的数据(对应于标志的真值的数据)。但我不明白为什么它会在实际输出中给出这些值!
像这样的东西怎么样:
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(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 = 999999) masked_array(data = [1 0 0 1 -- -- -- 0 -- 1 -- -- -- -- 1], mask = [False False False False True True True False True False True True True True False], fill_value = 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)
如你所料(也可能不料),这里mask起到了一个“过滤器”的作用,过滤掉mask中对应位置为False的数据元素。由于我为 data
和 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
的数据类型为 bool
,而 mask2
的数据类型为 int32
。
然而,这里的输出是不同的: [2 1 2 1 2]
.
这是怎么回事?
事实上,索引的行为因用于索引的数组的数据类型而异。如前所述,当“掩码”的数据类型为布尔值时,它具有过滤功能。但是当“掩码”的数据类型是整数时,它提供了一个“选择”功能,使用索引的元素作为原始数组的索引。
因此,在第二个示例中,由于 data[1] = 2
和 data[0] = 1
,data[mask2]
的结果是长度为 5 的数组,而不是 3(在布尔情况下)。
换句话说,给定以下代码:
res = data[mask]
如果mask.dtype == int
,res的长度将等于mask的长度。
如果mask.dtype == bool
,res的长度将等于mask中True
个值的个数。
差别很大。
最后,您可以使用 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]
我弄清楚了使用屏蔽数组进行索引的工作原理。
事实上,python不处理这种索引。
当使用 flag
布尔掩码数组执行类似 data[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。
如果我用以下方法重建你的数组:
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 表示求和 v 1 表示乘积)。屏蔽数组通常不会遍历它们的值而跳过屏蔽的数组;相反,他们将屏蔽的值转换为无害的值,并使用常规的 numpy 操作。另一种策略是使用 compressed
.
indices = np.where(flag.filled(False))
在另一个答案中提到,但普通的布尔形式也同样有效。
掩码数组具有 data
和 mask
属性。屏蔽不会直接更改 data
值。该任务留给 filled
.