I am new to numpy.Recently only I started learning.I am doing one practice problem and getting error. Question is to replace all even elements in the array by -1.
import numpy as np
np.random.seed(123)
array6 = np.random.randint(1,50,20)
slicing_array6 = array6[array6 %2==0]
print(slicing_array6)
slicing_array6[:]= -1
print(slicing_array6)
print("Answer is:")
print(array6)
I am getting output as :
[46 18 20 34 48 10 48 26 20]
[-1 -1 -1 -1 -1 -1 -1 -1 -1]
Answer is:
[46 3 29 35 39 18 20 43 23 34 33 48 10 33 47 33 48 26 20 15]
My doubt is why original array not replaced? Thank you in advance for help
CodePudding user response:
In [12]: np.random.seed(123)
...: array6 = np.random.randint(1,50,20)
...: slicing_array6 = array6[array6 %2==0]
In [13]: array6.shape
Out[13]: (20,)
In [14]: slicing_array6.shape
Out[14]: (9,)
slicing_array6
is not a view
; it's a copy. It does not use or reference the array6
data:
In [15]: slicing_array6.base
Modifying this copy does not change array6
:
In [16]: slicing_array6[:] = -1
In [17]: slicing_array6
Out[17]: array([-1, -1, -1, -1, -1, -1, -1, -1, -1])
In [18]: array6
Out[18]:
array([46, 3, 29, 35, 39, 18, 20, 43, 23, 34, 33, 48, 10, 33, 47, 33, 48,
26, 20, 15])
But if the indexing and modification occurs in the same step:
In [19]: array6[array6 %2==0] = -1
In [20]: array6
Out[20]:
array([-1, 3, 29, 35, 39, -1, -1, 43, 23, -1, 33, -1, -1, 33, 47, 33, -1,
-1, -1, 15])
slicing_array6 = array6[array6 %2==0]
has actually done
array6.__getitem__(array6%2==0)
array6[array6 %2==0] = -1
does
array6.__setitem__(array6 %2==0, -1)
A __setitem__
applied to a view
does change the original, the base.
An example with view
that works:
In [32]: arr = np.arange(10)
In [33]: arr
Out[33]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [34]: x = arr[::3] # basic indexing, with a slice
In [35]: x
Out[35]: array([0, 3, 6, 9])
In [36]: x.base # it's a `view` of arr
Out[36]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [37]: x[:] = -1
In [38]: arr
Out[38]: array([-1, 1, 2, -1, 4, 5, -1, 7, 8, -1])
CodePudding user response:
Explanation
Let's move step by step. We start with
array6 = np.array([46, 3, 29, 35, 39, 18, 20, 43, 23, 34, 33, 48, 10, 33, 47, 33, 48, 26, 20, 15])
print(array6 %2==0)
# array([ True, False, False, False, False, True, True, False, False,
# True, False, True, True, False, False, False, True, True,
# True, False])
You just made a mask (%2==0
) to array6
. Then you apply the mask to it and assign to a new variable:
slicing_array6 = array6[array6 %2==0]
print(slicing_array6)
# [46 18 20 34 48 10 48 26 20]
Note that this returns a new array:
print(id(array6))
# 2643833531968
print(id(slicing_array6))
# 2643833588112
print(array6)
# [46 3 29 35 39 18 20 43 23 34 33 48 10 33 47 33 48 26 20 15]
# unchanged !!
Final step, you assign all elements in slicing_array6
to -1
:
slicing_array6[:]= -1
print(slicing_array6)
# [-1 -1 -1 -1 -1 -1 -1 -1 -1]
Solution
Instead of assigning masked array to a new variable, you apply new value directly to the original array:
array6[array6 %2==0] = -1
print(array6)
print(id(array6))
# [-1 3 29 35 39 -1 -1 43 23 -1 33 -1 -1 33 47 33 -1 -1 -1 15]
# 2643833531968
# same id !!
CodePudding user response:
Numpy's slicing functionality directly modifies the array, but you have to assign the value you want to it. Not to completely ruin your learning, here is a similar example to what you are trying to achieve:
import numpy as np
a = np.arange(10)**3
print(f"start: {a}")
#start: [ 0 1 8 27 64 125 216 343 512 729]
# to assign every 3rd item as -99
a[2::3] = -99
print(f"answer: {a}")
#answer: [ 0 1 -99 27 64 -99 216 343 -99 729]