Home > Mobile >  How to modify numpy arrays using multiple masks
How to modify numpy arrays using multiple masks

Time:08-04

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])
  • Related