Search code examples
pythonnumpyscipyoperation

How to operate elementwise on a matrix of type scipy.sparse.csr_matrix?


In numpy if you want to calculate the sinus of each entry of a matrix (elementise) then

a = numpy.arange(0,27,3).reshape(3,3)
numpy.sin(a)

will get the job done! If you want the power let's say to 2 of each entry

a**2

will do it.

But if you have a sparse matrix things seem more difficult. At least I haven't figured a way to do that besides iterating over each entry of a lil_matrix format and operate on it.

I've found this question on SO and tried to adapt this answer but I was not succesful.

The Goal is to calculate elementwise the squareroot (or the power to 1/2) of a scipy.sparse matrix of CSR format.

What would you suggest?


Solution

  • The following trick works for any operation which maps zero to zero, and only for those operations, because it only touches the non-zero elements. I.e., it will work for sin and sqrt but not for cos.

    Let X be some CSR matrix...

    >>> from scipy.sparse import csr_matrix
    >>> X = csr_matrix(np.arange(10).reshape(2, 5), dtype=np.float)
    >>> X.A
    array([[ 0.,  1.,  2.,  3.,  4.],
           [ 5.,  6.,  7.,  8.,  9.]])
    

    The non-zero elements' values are X.data:

    >>> X.data
    array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
    

    which you can update in-place:

    >>> X.data[:] = np.sqrt(X.data)
    >>> X.A
    array([[ 0.        ,  1.        ,  1.41421356,  1.73205081,  2.        ],
           [ 2.23606798,  2.44948974,  2.64575131,  2.82842712,  3.        ]])
    

    Update In recent versions of SciPy, you can do things like X.sqrt() where X is a sparse matrix to get a new copy with the square roots of elements in X.