在NumPy中使用多级布尔索引掩码

Hem*_*mer 9 python numpy

我有以下代码,它首先选择具有逻辑索引掩码的NumPy数组的元素:

import numpy as np

grid = np.random.rand(4,4) 
mask = grid > 0.5
Run Code Online (Sandbox Code Playgroud)

我希望对这个使用第二个布尔掩码来挑选对象:

masklength = len(grid[mask])
prob = 0.5
# generates an random array of bools
second_mask = np.random.rand(masklength) < prob 

# this fails to act on original object
grid[mask][second_mask] = 100
Run Code Online (Sandbox Code Playgroud)

这与SO问题中列出的问题不完全相同: Numpy数组,如何选择满足多个条件的索引? - 因为我使用随机数生成,我不想生成完整的掩码,仅用于第一个掩码选择的元素.

Ste*_*fan 8

使用平面索引避免了很多令人头痛的问题:

grid.flat[np.flatnonzero(mask)[second_mask]] = 100
Run Code Online (Sandbox Code Playgroud)

分解它:

ind = np.flatnonzero(mask)
Run Code Online (Sandbox Code Playgroud)

生成一个平面索引数组,其中mask为真,然后通过应用进一步抽取second_mask

ind = ind[second_mask] 
Run Code Online (Sandbox Code Playgroud)

我们可以继续:

ind = ind[third_mask]
Run Code Online (Sandbox Code Playgroud)

最后

grid.flat[ind] = 100
Run Code Online (Sandbox Code Playgroud)

索引gridwithind和assigns的平面版本100grid.ravel()[ind] = 100也可以,因为ravel()将平面视图返回到原始数组中。


NPE*_*NPE 6

我相信以下内容符合您的要求:

grid[[a[second_mask] for a in np.where(mask)]] = 100
Run Code Online (Sandbox Code Playgroud)

它的工作原理如下:

  • np.where(mask)将布尔掩码转换为索引,其中mask为True;
  • [a[second_mask] for a in ...]将索引子集设置为仅选择其中second_mask为True的那些索引.

您的原始版本不起作用的原因是grid[mask]涉及花哨的索引.这会创建数据的副本,从而导致...[second_mask] = 100修改该副本而不是原始数组.