0

I am trying to apply a simple boolean mask to a np array. Following is an easy example.

temp = np.arange(5)
print(temp)
temp1 = temp
temp1[temp1 < 2] = 0
print(temp1)
print(temp)

I have already assign the value of temp to a new variable temp1, so what I expected is that the mask only applies on the variable temp1. However, the value of temp is also updated. I wonder why is this happening.

Result:

[0 1 2 3 4]
[0 0 2 3 4]
[0 0 2 3 4]
1
  • Welcome to SO. If one of the answers below fixes your issue, you should accept it (click the check mark next to the appropriate answer). That does two things. It lets everyone know your issue has been resolved, and it gives the person that helps you credit for the assist. See here for a full explanation. Commented Oct 22, 2018 at 20:20

3 Answers 3

5

Your variables temp1 and temp refer to the same object. Use .copy() to get a shallow copy of the item so it will not modify the original.

temp = np.arange(5)
print(temp)
temp1 = temp.copy()
temp1[temp1 < 2] = 0
print(temp1)
print(temp)

If you want to learn more about names and referencing, https://nedbatchelder.com/text/names.html/

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

4 Comments

I believe you mean "deep copy" rather than "shallow copy"
I meant shallow copy. If you do a = b, you are referencing a name to the object and it does not copy. Some extra material; docs.python.org/3.6/library/copy.html
Interesting. I had misunderstood the definition of shallow copy then
@Woody1193 Nope you are right, it is a deep copy, since the stuff contained in temp is also copied np.shares_memory(temp, temp1) yields False; a shallow copy would be temp1 = temp[...] in which case temp and temp1 are still distinct objects but np.shares_memory(temp, temp1) yields True.
1

As was stated before, you're only getting a new reference to temp. What that means is that although the variables are named differently, they both point to the same piece of memory. So, by changing the value in one, you actually change the value in both. To avoid this, you need to use, at the very least, a shallow copy. Here's two ways to do this using numpy:

temp1 = numpy.copy(temp)

or

temp1 = np.array(temp, copy = True)

Comments

0

As others have noted, you need to explicitly ask for a copy when you're dealing with collection-like objects in python. The same behavior you're seeing here can happen with lists and dictionaries as well. Numpy has the nice helper method numpy.copy() that should solve your problems.

# one way
temp1 = temp.copy()

#another way
temp1 = numpy.copy(temp)

To add something that I thought might be useful, you can save the mask itself and then apply it by multiplying.

mask = temp < 2
masked_temp = temp * mask

This is useful in case you want to visualize or reuse this mask and makes the copy problem from before irrelevant (as masked_temp is not a copy, but a newly calculated array).

1 Comment

@Jean-FrançoisFabre I think he meant temp.copy()

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.