Numpy array assignment with copy
All three versions do different things:
B = A
This binds a new name
B
to the existing object already namedA
. Afterwards they refer to the same object, so if you modify one in place, you'll see the change through the other one too.B[:] = A
(same asB[:]=A[:]
?)This copies the values from
A
into an existing arrayB
. The two arrays must have the same shape for this to work.B[:] = A[:]
does the same thing (butB = A[:]
would do something more like 1).numpy.copy(B, A)
This is not legal syntax. You probably meant
B = numpy.copy(A)
. This is almost the same as 2, but it creates a new array, rather than reusing theB
array. If there were no other references to the previousB
value, the end result would be the same as 2, but it will use more memory temporarily during the copy.Or maybe you meant
numpy.copyto(B, A)
, which is legal, and is equivalent to 2?
Strange numpy array assignment after copy
LAC = label
does NOT copy label
into a new array. It is simply assigning the same object to LAC
. Thus, when you change one, the other also changes. Think of it as both being the same array with different names.
If you wish to make a new copy of your array, use np.copy
. Here is an example to make it clear:
label = np.array([0., 1., 2., 3., 4., 0., 1., 2., 3., 4.])
print(np.unique(label))
#[0. 1. 2. 3. 4.]
#LAC and label point to the same object
LAC = label
#this changes both LAC and label
LAC[LAC != 4] = 0
print(np.unique(LAC))
#[0. 4.]
print(np.unique(label))
#[0. 4.]
label = np.array([0., 1., 2., 3., 4., 0., 1., 2., 3., 4.])
#make a new copy of label
LAC = label.copy()
#this changes ONLY LAC
LAC[LAC != 4] = 0
print(np.unique(LAC))
#[0. 4.]
print(np.unique(label))
#[0. 1. 2. 3. 4.]
how to create a new numpy array by masking another numpy array with a single assignment
I must preface this by saying any attempt in doing so massively decreases readability. Just use two lines if you don't want to other people (or yourself) to ever work with that code again. This answer is just supposed to demonstrate what could be done, not what should be done.
The expression A=B=x
assigns x
to both A
and B
. If you really want to squeeze everything onto one line you could try something like
import numpy as np
a = np.arange(5)
(b:=a.copy())[a!=0]=1
The :=
(walrus) operator actually evaluates to the assigned value, unlike the assignment (=
) operator. (Note that A=B=x
works because it is basically a shorthand for t=x; A=t; B=t
, but A=(B=x)
will not work as the assignment does not evaluate to anything. You chould write A=(B:=x)
though.) Then a
remains unchanged, which corresponds to your first version, so
>>> b
array([0, 1, 1, 1, 1])
>>> a
array([0, 1, 2, 3, 4])
Python - array copying/assign, unexpected '=array[:]' behaviour for numpy
EDITED - see @juanpa.arrivillaga's comments below.
In all of your examples, values of the ndarrays
arenumpy.int32
objects, which are mutable.
So from your 3rd example, both e
and ArrayE
point to the same numpy.int32
objects.
That's why the changes are reflected on both.
You can verify that by checking their ids.
print(id(e[0]) == id(ArrayE[0]))
Numpy variable assignment is by reference?
This is in general python behaviour and not specific to numpy. If you have an object such as list
you will see a similar behaviour.
a = [1]
b = a
b[0] = 7
print a
print b
will output
[7]
[7]
This happens because variable a is pointing to a memory location where the array [1] is sitting and then you make b point to the same location. So if the value at that location changes, both the variables are still pointing there. If you want to get around this behaviour you'll need to use the .copy() function like this.
A = np.zeros((2,2))
B = A.copy()
A[0,0] = 2
print A
print B
which outputs..
[[2. 0.]
[0. 0.]]
[[0. 0.]
[0. 0.]]
Using the copy() function will spawn a whole new object instead of pointing to the old one.
Caution: This may not be the ideal way to do it since copying a huge numpy array can be computationally expensive
EDIT: Removed the word mutable since the behaviour is also applicable to immutables.
NumPy array loses dimension upon assignment/copy, why?
Looking at the openCV script mentioned in the comments, the reshape to three dimensions is necessary because a dimension is being lost via Boolean indexing, and not by the assignment alone.
The names of the arrays in that script which motivated the question are p0
and good_new
.
Here is a breakdown of the operations in that script:
p0
is a 3D array with shape(17, 1, 2)
.The line:
p1, st, err = cv.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
creates new arrays, with array
p1
having shape(17, 1, 2)
and arrayst
having shape(17, 1)
.The assignment
good_new = p1[st==1]
creates a new array object by a Boolean indexing operation onp1
. This is a 2D array has shape(17, 2)
. A dimension has been lost through the indexing operation.The name
p0
needs to be assigned back to the array data contained ingood_new
, butp0
also needs to be 3D. To achieve this, the script usesp0 = good_new.reshape(-1, 1, 2)
.
For completeness, it is worth summarising why the Boolean indexing operation in step (3) results in a dimension disappearing.
The Boolean array st == 1
has shape (17, 1)
which matches the initial dimensions of p1
, (17, 1, 2)
.
This means that the selection occurs in the second dimension of p1
: the indexer array st == 1
is determining which arrays of shape (2,)
should be in the resulting array. The final array will be of shape (n, 2)
, where n
is the number of True
values in the Boolean array.
This behaviour is detailed in the NumPy documentation here.
Numpy array assignment by boolean indices array
If IDX
is a NumPy array of Boolean type, and X
and Y
are NumPy arrays then your intuition works:
X = np.array(X)
Y = np.array(Y)
IDX = np.array(IDX).astype(bool)
X[IDX] = Y[IDX]
This changes X
in place.
If you don't want to do all this type casting, or don't want to overwrite X
, then np.where()
does what you want in one go:
np.where(IDX==1, Y, X)
Related Topics
Convert String Date to Timestamp in Python
Error When Configuring Tkinter Widget: 'Nonetype' Object Has No Attribute
Most Efficient Way of Making an If-Elif-Elif-Else Statement When the Else Is Done the Most
Using Django Time/Date Widgets in Custom Form
Speeding Up Pandas.Dataframe.To_SQL with Fast_Executemany of Pyodbc
Datetime to String with Series in Pandas
How to Write Png Image to String with the Pil
Creating a Pandas Dataframe from a Numpy Array: How to Specify the Index Column and Column Headers
Not Letting the Character Move Out of the Window
How to Check a String for Specific Characters
Run a .Bat File Using Python Code