布尔索引数组到不带循环的布尔索引数组

时间:2019-06-13 13:52:53

标签: python arrays numpy matrix-indexing

我想通过多个布尔数组而不是循环来索引带有布尔掩码的数组。

这是我想要实现的,但没有循环,只有numpy。

import numpy as np
a = np.array([[0, 1],[2, 3]])
b = np.array([[[1, 0], [1, 0]], [[0, 0], [1, 1]]], dtype=bool)

r = []
for x in b:
    print(a[x])
    r.extend(a[x])

# => array([0, 2])
# => array([2, 3])

print(r)
# => [0, 2, 2, 3]

# what I would like to do is something like this
r = some_fancy_indexing_magic_with_b_and_a
print(r)
# => [0, 2, 2, 3]

1 个答案:

答案 0 :(得分:6)

方法1

使用np.broadcast_toa广播到b'的形状,然后使用b对其进行遮罩-

In [15]: np.broadcast_to(a,b.shape)[b]
Out[15]: array([0, 2, 2, 3])

方法2

另一种方法是按a的大小来获取所有索引和 mod ,也就是2D中每个b块的大小然后索引到展平的a-

a.ravel()[np.flatnonzero(b)%a.size]

方法3

与App#2相同,但保持2D格式,并在b的最后两个轴上使用非零索引-

_,r,c = np.nonzero(b)
out = a[r,c]

大型数组上的定时(给定的样本形状放大了100倍)-

In [50]: np.random.seed(0)
    ...: a = np.random.rand(200,200)
    ...: b = np.random.rand(200,200,200)>0.5

In [51]: %timeit np.broadcast_to(a,b.shape)[b]
45.5 ms ± 381 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [52]: %timeit a.ravel()[np.flatnonzero(b)%a.size]
94.6 ms ± 1.64 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [53]: %%timeit
    ...: _,r,c = np.nonzero(b)
    ...: out = a[r,c]
128 ms ± 1.46 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)