zxmn1476
zxmn1476

Reputation: 3

numpy slice assign to another value

Suppose I have a 1D numpy array:

 arr = np.arange(10)

Then I slice arr and assign to another variable:

 arr2 = arr[5:8]

And I want to change arr :

 arr2 *= 10

or:

 arr2 = arr2 * 10

The results are different. Why are they different?

 arr

array([ 0, 1, 2, 3, 4, 50, 60, 70, 8, 9])

 arr

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Upvotes: 0

Views: 401

Answers (2)

hpaulj
hpaulj

Reputation: 231385

In [639]: arr = np.arange(10)         

By indexing with a slice (basic indexing), arr2 is a view of arr. It shares the data buffer with arr:

In [640]: arr2 = arr[5:8]                                                                             
In [641]: arr2                                                                                        
Out[641]: array([5, 6, 7])

If we make a copy, values are copied, not shared:

In [642]: arr3 = arr[5:8].copy()     # arr[[5,6,7]] is also a copy

By modifying arr2 in-place, we also modify part of arr:

In [643]: arr2 *= 10                                                            
In [644]: arr2                                                                                        
Out[644]: array([50, 60, 70])
In [645]: arr                                                                                         
Out[645]: array([ 0,  1,  2,  3,  4, 50, 60, 70,  8,  9])

But not arr3:

In [646]: arr3                                                                                        
Out[646]: array([5, 6, 7])

arr2 = arr2*10 does not modify the arr2 array, but rather assigns a whole new array to the arr2 variable.

So you need to understand what it means to assign an object to a variable. The difference between assign a variable, and modifying a mutable object. And the difference between array copy and view (and between basic and advanced indexing). This last one is specific to numpy, the rest to Python as well.

Upvotes: 0

Ken Wei
Ken Wei

Reputation: 3130

In simplified terms, arr2 = arr[5:8] assigns a reference to the 5:7th elements of arr to a variable arr2.

Thus the operation arr2 *= 10 boils down to "multiply those elements by 10 in place", which modifies arr in place (you are performing an in-place operation, a modification, on a reference, which therefore affects the original).

However, arr2 = arr2 * 10 says "take the result of multiplying the 5:7th elements by 10, then assign it to a variable called arr2". Here, you perform an operation on a reference (not a modification), take the output (to be explicit, the operation arr2 * 10 returns a new object), and assign it to arr2, which incidentally destroys the original reference (but this part is somewhat irrelevant).

Or compare these:

arr[5:8] *= 10
arr[5:8] = arr[5:8] * 10
arr2 = arr[5:8] * 10

The first two are equivalent. Your code is essentially a comparison between the first and the third (equivalently, the second and third). The second and third are not equal, because in your code, your earlier assignment of arr2 = arr[5:8] has nothing to do with the LHS of arr2 = arr[5:8] * 10.

Upvotes: 1

Related Questions