1

I had a weird behaviour trying to change the value of an element of a numpy array today, and I would like to understand why it didn't work. I have two arrays (a and b), and I want to change the values of b where a > 0.

a = array([[ 1.,  0.,  0.],
           [ 0.,  1.,  0.],
           [ 0.,  0.,  1.]])

b = array([[ 5.,  0.,  0.],
           [ 0.,  5.,  0.],
           [ 0.,  0.,  5.]])

mask = a > 0

print b[mask][0]
   => 5.0

b[mask][0] = 10

print b[mask][0]
   => 5.0

Could someone please explain why the assignment b[mask][0] didn't change my value 5.0?

1 Answer 1

2

b[mask] is a copy of b. b[mask][0] = 1 is effectively:

 c = b[mask]
 c[0] = 1

The data elements of c are not (in general) a contiguous block of the elements of b.

 b[mask] = 10
 b[mask] = [10, 11, 12]

You can assign values to b[mask] when it is the only thing on the left. You need to change all the masked elements.

If you need to change one or two, then first change the mask so it selects only those elements.

In general

 b[...][...] = ...

is not good practice. Sometimes it works (if the first indexing is a slice that produces a view), but you shouldn't count on it. It takes a while to full grasp the difference between a view and copy.


The [] get translated by the Python interpreter into calls to __getitem__ or __setitem__. The following pairs are equivalent:

 c = b[mask]
 c = b.__getitem__(mask)

 b[mask] = 10
 b.__setitem__(mask, 10)

 b[mask][0] = 10
 b.__getitem__(mask).__setitem__(0, 10)

b[mask][10] is 2 operations, a get followed by a set. The set operates on the result of the get. It modifies b only if the result of the get is a view.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. I'm not quite sure i understand though. b[mask] = 10 would give b[mask] = [10,10,10] but b[mask][0] = 10 would be [5,5,5]. So is b[mask] a view and b[mask][0] a copy?
Does expressing the indexing in terms of calls to __getitem__ and __setitme__ help?

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.