如何在numpy中从索引数组创建布尔数组?

4

假设我有一个多维数组的索引,如何从中创建一个布尔数组?对于1D情况,它看起来像这样:

a = [1,5,6]
b = somefunction(total_array_length=10, a)
>>> [False, True, False, False, False, True, True, False, False, False]

对于2D情况,它看起来像这样:
a = [[1,3],[4,2]]
b = somefunction(total_array_length=5, a)
>>> [[False, True, False, True, False], [False, False, True, False, True]]

我想用这个方法为数组创建一个掩码。我有一个8维的多维数组,对于最后一个轴,我可以找到我想要保留的元素的索引。换句话说,在原始数组中,我有一个8D数组,其中最后一个轴包含所有我想要保留的索引。有人知道如何做吗?
在上面的函数中,total_array_length将等于原始数组的长度。
那么,如何在形状为(23,5,76,32,1,3,8,9)的数组和形状为(23,5,76,32,1,3,8,4)的索引数组上执行此操作?请注意,4 < 9,但除此之外,它们具有相同的维度。
a.shape = (23,5,76,32,1,3,8,4) 
b = somefunction(total_array_length=9, a)
b.shape =(23,5,76,32,1,3,8,9) 

不清楚total_array_length是什么,以及为什么在任何一个示例中b的形状都与a的形状不匹配。此外,关于您的8d数组的最后一个轴,您试图表达什么并不清楚。它听起来与您的示例不相似。 - Imran
如果您遇到困难,请尝试编写代码并发布它,不要要求我们从头开始。 - John Zwinck
我让它更清晰了吗? - Perm. Questiin
2个回答

9

对于第一个案例:

In [23]: a = [1,5,6]
In [24]: b = np.zeros(10, dtype=bool)
In [25]: b[a] = True
In [26]: b
Out[26]: array([False,  True, False, False, False,  True,  True, False, False, False], dtype=bool)

一个同样简单,可能同样快速的列表版本:
In [27]: [True if i in a else False for i in range(10)]
Out[27]: [False, True, False, False, False, True, True, False, False, False]

对于列表的列表,只需要嵌套那个列表推导式:

In [34]: [[True if i in a1 else False for i in range(5)] for a1 in a]
Out[34]: [[False, True, False, True, False], [False, False, True, False, True]]

这种情况下的数组版本如下所示:
In [41]: a = [[1,3],[4,2]]
In [42]: b = np.zeros((len(a),5), bool)
In [43]: b[[[0],[1]],a]
Out[43]: 
array([[False, False],
       [False, False]], dtype=bool)
In [44]: b[[[0],[1]],a]=True
In [45]: b
Out[45]: 
array([[False,  True, False,  True, False],
       [False, False,  True, False,  True]], dtype=bool)

然而,这只对a的子列表长度相同的情况有效。如果它们不同,我认为我们将不得不使用该列表的扁平版本。实际上,将2D情况转换为原始的1D情况。


对于不规则的a,列表版本仍然很容易:

In [49]: a = [[1,2,3],[4,2],[1]]
In [50]: [[True if i in a1 else False for i in range(5)] for a1 in a]
Out[50]: 
[[False, True, True, True, False],
 [False, False, True, False, True],
 [False, True, False, False, False]]

但是数组版本会更复杂一些:
构造两个索引数组,一个用于行,一个用于列:
In [53]: a0 = np.repeat(np.arange(3),[len(i) for i in a])
In [54]: a0
Out[54]: array([0, 0, 0, 1, 1, 2])
In [55]: a1 = np.hstack(a)
In [56]: a1
Out[56]: array([1, 2, 3, 4, 2, 1])

获取等效的展平(1d)索引:

In [57]: np.ravel_multi_index((a0,a1),(3,5))
Out[57]: array([ 1,  2,  3,  9,  7, 11], dtype=int32)

通过flat将其应用于二维数组:

In [58]: b = np.zeros((3,5),bool)
In [59]: b.flat[Out[57]] = True
In [60]: b
Out[60]: 
array([[False,  True,  True,  True, False],
       [False, False,  True, False,  True],
       [False,  True, False, False, False]], dtype=bool)

我如何处理形状为(23,5,76,32,1,3,8,9)的数组和形状为(23,5,76,32,1,3,8,4)的索引数组?请注意,4<9,但除此之外它们具有相同的维度。 - Perm. Questiin
尝试将数组重塑为(n,4)和(n,9)。进行映射(例如作为44)。然后再次重塑。 - hpaulj
1
True if i in a1 else Falsei in a1 是一样的,使用后者会更快更易读。 - Gregory Morse

2

对于1D:

n = 10
inds_all = np.arange(n)
inds = [1, 5, 6]

b = np.isin(inds_all, inds)
# array([False, True, False, False, False, True, True, False, False, False])

对于二维数据,情况会稍微有些棘手,特别是当列表索引的大小不一致时:

n = 5
inds_all = np.arange(len(inds)*n).reshape(len(inds), n)
inds = [[1,3], [4,2], [3]]
inds = np.concatenate(inds) + np.repeat(inds_all[:,0], list(map(len, inds)))

b = np.isin(inds_all, inds)
# array([[False,  True, False,  True, False],
#        [False, False,  True, False,  True],
#        [False, False, False,  True, False]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接