3

Consider some array arr and advanced indexing mask mask:

import numpy as np

arr = np.arange(4).reshape(2, 2)
mask = A < 2

Using advanced indexing creates a new copy of an array. Accordingly, one cannot "chain" a mask with an an additional mask or even with a basic slicing operation to replace elements of an array:

submask = [False, True]
arr[mask][submask] = -1  # chaining 2 masks
arr[mask][:] = -1  # chaining a mask with a basic slicing operation

print(arr)
[[0 1]
 [2 3]]

I have two related questions:

1/ What is the best way to replace elements of an array using chained masks?

2/ If advanced indexing returns a copy of an array, why does the following work?

arr[mask] = -1

print(arr)
[[-1 -1]
 [ 2  3]]

2 Answers 2

3

The short answer:

  • you have to figure out a way of combining the masks. Since masks can "chain" in different ways I don't think there's a simple all-purpose substitute.

  • indexing can either be a __getitem__ call, or a __setitem__. Your last case is a set.

With chained indexing, a[mask1][mask2] =value gets translated into

a.__getitem__(mask1).__setitem__(mask2, value)

Whether a gets modified or not depends on what the first getitem produces (a view vs copy).

In [11]: arr = np.arange(4).reshape(2,2)
In [12]: mask = arr<2
In [13]: mask
Out[13]: 
array([[ True,  True],
       [False, False]])
In [14]: arr[mask]
Out[14]: array([0, 1])

Indexing with a list or array may preserve the number of dimensions, but a boolean like this returns a 1d array, the items where the mask is true.

In your example, we could tweak the mask (details may vary with the intent of the 2nd mask):

In [15]: mask[:,0]=False
In [16]: mask
Out[16]: 
array([[False,  True],
       [False, False]])
In [17]: arr[mask]
Out[17]: array([1])
In [18]: arr[mask] += 10
In [19]: arr
Out[19]: 
array([[ 0, 11],
       [ 2,  3]])

Or a logical combination of masks:

In [26]: (np.arange(4).reshape(2,2)<2)&[False,True]
Out[26]: 
array([[False,  True],
       [False, False]])
Sign up to request clarification or add additional context in comments.

2 Comments

I accepted this for generality, but see the other answer for a inspiration for how to chain masks that may work in some circumstances.
I added a possibility for your first example.
2

Couple of good questions! My take:

  1. I would do something like this:
x,y=np.where(mask)
arr[x[submask],y[submask]] = -1
  1. From the official document:

Most of the following examples show the use of indexing when referencing data in an array. The examples work just as well when assigning to an array. See the section at the end for specific examples and explanations on how assignments work.

which means arr[mask]=1 is referrencing, while arr[mask] is extracting data and creates a copy.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.