Question

I have just found a problem and I don't know if it is meant to be this way or I am just doing it wrong. When I use logical addressing in a numpy matrix to change all the values of a matrix that are, say, equal to a 1. All other matrices that somehow have something to do with this matrix will also be modified.

In [1]: import numpy as np
In [2]: from numpy import matrix as mtx
In [3]: A=mtx(np.eye(6))
In [4]: A
Out[4]: 
matrix([[ 1.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  1.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  1.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  1.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  1.]])

In [5]: B=A

In [6]: C=B

In [7]: D=C

In [8]: A[A==1]=5

In [9]: A
Out[9]: 
matrix([[ 5.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  5.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  5.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  5.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  5.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  5.]])

In [10]: B
Out[10]: 
matrix([[ 5.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  5.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  5.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  5.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  5.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  5.]])

In [11]: C
Out[11]: 
matrix([[ 5.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  5.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  5.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  5.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  5.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  5.]])

In [12]: D
Out[12]: 
matrix([[ 5.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  5.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  5.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  5.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  5.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  5.]])

Can anyone tell me what am I doing wrong? is this a bug?

Was it helpful?

Solution

This is not a bug. Saying B=A in python means that both B and A point to the same object. You need to copy the matrix.

>>> import numpy as np
>>> from numpy import matrix as mtx
>>> A = mtx(np.eye(6))
>>> B = A.copy()
>>> C = A

#Check memory locations.
>>> id(A)
19608352
>>> id(C)
19608352    #Same object as A
>>> id(B)
19607992    #Different object then A

>>> A[A==1] = 5
>>> B   #B is a different object then A
matrix([[ 1.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  1.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  1.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  1.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  1.]])

>>> C   #C is the same object as A
matrix([[ 5.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  5.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  5.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  5.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  5.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  5.]])

The same issue can be seen with python list:

>>> A = [5,3]
>>> B = A
>>> B[0] = 10
>>> A
[10, 3]

Note that this is different then returning a numpy view as in this case:

>>> A = mtx(np.eye(6))
>>> B = A[0]  #B is a view and now points to the first row of A

>>> id(A)
28088720
>>> id(B)  #Different objects!
28087568  
#B still points to the memory location of A's first row, but through numpy trickery

>>> B
matrix([[ 1.,  0.,  0.,  0.,  0.,  0.]])
>>> B *= 5 #In place multiplication, updates B which is the same as A's first row
>>> A
matrix([[ 5.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  1.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  1.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  1.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  1.]])

As the view B points to the first row of A, A is changed. Now lets force a copy.

>>> B = B*10 #Assigns B*10 to a different chunk of memory
>>> A
matrix([[ 5.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  1.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  1.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  1.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  1.]])
>>> B
matrix([[ 50.,   0.,   0.,   0.,   0.,   0.]])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top