Let's say I have an array a
:
a = np.array([1,2,3,4,5])
I can make a mask:
mask1 = a > 2
and then view the masked array:
[In]: a[mask1]
[Out]: array([3, 4, 5])
or modify it:
a[mask1] = [8, 9, 10]
[In]: a
[Out]: array([ 1, 2, 8, 9, 10])
Now I want to mask the masked array again, based on some other criteria, e.g.:
mask2 = a[mask1] > 8
and I can view it:
[In]: a[mask1][mask2]
[Out]: array([ 9, 10])
Now here is the problem; when I try to modify the doubly-masked array, it doesn't work anymore:
a[mask1][mask2] = [20, 30]
[In]: a
[Out]: array([ 1, 2, 8, 9, 10])
I know it has to do with numpy returning views of arrays and so, but why does it work with one mask, but not with multiple masks, and how can I make it work with multiple masks?
CodePudding user response:
Update array with chained index should generally be avoided.
You can convert the masks into range index and update, something like this:
idx = np.arange(len(a))[mask1][mask2]
a[idx] = [20, 30]
Output:
array([ 1, 2, 8, 20, 30])
CodePudding user response:
Ok I found 'a' solution, but don't know if it's the best solution:
I create a current_mask
array with the shape of my array, and initialize it to all True
:
a = np.array([1,2,3,4,5])
current_mask = np.ones(a.shape, dtype=np.bool_)
Then, whenever I create a new mask, I update my current_mask
with it:
mask1 = a > 2
current_mask[current_mask] &= mask1
Like before, I can view and modify the elements using current_mask
:
[In]: a[current_mask]
[Out]: array([3, 4, 5])
[In]: a[current_mask] = [8,9,10]
[In]: a
[Out]: array([ 1, 2, 8, 9, 10])
Now, I can create a new mask using the current mask, and update the current mask with it:
mask2 = a[current_mask] > 8
current_mask[current_mask] &= mask2
Now, I can both view AND modify the elements:
[In]: a[current_mask]
[Out]: array([ 9, 10])
[In]: a[current_mask] = [20, 30]
[In]: a
[Out]: array([ 1, 2, 8, 20, 30])