Yes, you are trying to change the matrix elements one by one. :)
Well, it works like that, but if you change the situation in another way (setting 0 to nonzero), you will get a warning about the effectiveness.
To save your view of changes quickly, it only changes the value in the M.data array and does not recount the indices. You must call the separate csr_matrix.eliminate_zeros matrix cleaning method. To get maximum speed, call it once at the end of the loop.
There is a csr_matrix.setdiag method that allows you to set the entire diagonal in one call. It still needs to be cleaned.
In [1633]: M=sparse.csr_matrix(np.arange(9).reshape(3,3)) In [1634]: M Out[1634]: <3x3 sparse matrix of type '<class 'numpy.int32'>' with 8 stored elements in Compressed Sparse Row format> In [1635]: MA Out[1635]: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=int32) In [1636]: M.setdiag(0) /usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient. SparseEfficiencyWarning) In [1637]: M Out[1637]: <3x3 sparse matrix of type '<class 'numpy.int32'>' with 9 stored elements in Compressed Sparse Row format> In [1638]: MA Out[1638]: array([[0, 1, 2], [3, 0, 5], [6, 7, 0]]) In [1639]: M.data Out[1639]: array([0, 1, 2, 3, 0, 5, 6, 7, 0]) In [1640]: M.eliminate_zeros() In [1641]: M Out[1641]: <3x3 sparse matrix of type '<class 'numpy.int32'>' with 6 stored elements in Compressed Sparse Row format> In [1642]: M.data Out[1642]: array([1, 2, 3, 5, 6, 7])