# CSR scipy matrix does not update after updating its values

I have the following code in python:

import numpy as np
from scipy.sparse import csr_matrix
M = csr_matrix(np.ones([2, 2],dtype=np.int32))
print(M)
print(M.data.shape)
for i in range(np.shape(M)[0]):
for j in range(np.shape(M)[1]):
if i==j:
M[i,j] = 0
print(M)
print(M.data.shape)


The output of the first 2 prints is:

  (0, 0)    1
(0, 1)    1
(1, 0)    1
(1, 1)    1
(4,)


The code is changing the value of the same index (i==j) and setting the value to zero. After executing the loops then the output of the last 2 prints is:

  (0, 0)    0
(0, 1)    1
(1, 0)    1
(1, 1)    0
(4,)


If I understand the concept of sparse matrices correctly, it should not be the case. It should not show me the zero values and the output of last 2 prints should be like this:

  (0, 1)    1
(1, 0)    1
(2,)


Does anyone have explanation for this? Am I doing something wrong?

It appears that CSR does not remove the zeros by default. You will first have to call eliminate_zeros() on your object. Once you do this you will see that the data contains only the non zero elements of your matrix.

after running the loop in your code:

print(M)


gives

  (0, 0)    0
(0, 1)    1
(1, 0)    1
(1, 1)    0


let us inspect the data

print(M.data)


we see that the zero elements are stored,

[0 1 1 0]


let us remove the zero elements to make our matrix sparse

M.eliminate_zeros()


and inspect whether the matrix is sparse,

print(M.data)


this confirms that the zero elements are removed and hence the matrix is sparse,

[1 1]


I hope this helps.

Sparse matrix is a matrix that has most of its elements as zero. Matrix on the other side of it, is Dense. csr_matrix creates an all zero element matrix and if you are updating the elements as

m[i,j] = 0.


Well, you're not really doing anything as elements are already zero. For example

import numpy as np
from scipy.sparse import csr_matrix
mat = csr_matrix((2,2), dtype = np.int16).toarray()
print mat,"\n"
for i in range(np.shape(mat)[0]):
for j in range(np.shape(mat)[1]):
mat[i,j] = i+j
print mat


gives

[[0 0]
[0 0]]

[[0 1]
[1 2]]


which is true, the first matrix,an all zero matrix created and the second, is the updated one.

Edit:

After substituting when $i==j$, the resultant matrix still has four elements but this time with $(0,0)$ and $(1,1)$ indices being $0$. So the result is

(0, 0)    0
(0, 1)    1
(1, 0)    1
(1, 1)    0
(4,)


(0, 1)    1

The result has basically two elements with $(0,1)$ and $(1,0)$ indices being $1$ and $1$ and shape is just $(2,)$ when flattened which does not make sense as matrix is still of size $(4,)$ . So python output is basically giving all the values in the matrix with index. If I am rightly understanding what you are assuming, since the matrix is sparse, you are expecting it to give only the values where the elements are non-zero, well this does not do that.