Elementwise division of sparse matrices, ignoring 0/0 Elementwise division of sparse matrices, ignoring 0/0 numpy numpy

Elementwise division of sparse matrices, ignoring 0/0


Update: (Inspired by sacul) Create an empty dok_matrix and modify only D's nonzero part with nonzero. (This should work for sparse matrices other than dok_matrix as well.)

F = scipy.sparse.dok_matrix(E.shape)F[D.nonzero()] = E[D.nonzero()] / D[D.nonzero()]

You can try the update + nonzero method for dok_matrix.

nonzero_idx = [tuple(l) for l in np.transpose(D.nonzero())]D.update({k: E[k]/D[k] for k in nonzero_idx})

First, we use nonzero to nail down the indices in the matrix D that is not 0. Then, we put the indices in the update method where we supply a dictionary

{k: E[k]/D[k] for k in nonzero_idx}

such that the values in D will be updated according to this dictionary.

Explanation:

What D.update({k: E[k]/D[k] for k in nonzero_idx}) does is

for k in {k: E[k]/D[k] for k in nonzero_idx}.keys():    D[k] = E[k]/D[k]

Note that this changes D in place. If you want to create a new sparse matrix rather than modifying D in place, copy D to another matrix, say ret.

nz = [tuple(l) for l in np.transpose(D.nonzero())]ret = D.copy()ret.update({k: E[k]/D[k] for k in nz})


A simple implementation using multiply:

def sparse_divide_nonzero(a, b):    inv_b = b.copy()    inv_b.data = 1 / inv_b.data    return a.multiply(inv_b)

To be used as:

import scipy as spimport scipy.sparseN, M = 4, 4M1 = sp.sparse.random(N, M, 0.5, 'csr')M2 = sp.sparse.random(N, M, 0.5, 'csr')M3 = sparse_divide_nonzero(M1, M2)print(M1, '\n')#   (0, 1)  0.9360024198546736#   (1, 1)  0.625073080022902#   (1, 2)  0.4086612951451881#   (2, 0)  0.06864456080221182#   (2, 1)  0.9871542989102963#   (2, 3)  0.4371900022237898#   (3, 0)  0.12121502419640318#   (3, 3)  0.22950388104392383 print(M2, '\n')#   (1, 0)  0.9753308317090571#   (1, 2)  0.29870724277296024#   (1, 3)  0.21116220574550637#   (2, 1)  0.5039729514070662#   (2, 2)  0.4463809800134303#   (3, 0)  0.36751994181969416#   (3, 1)  0.6189763803260612#   (3, 2)  0.3870101687623324 print(M3, '\n')#   (1, 2)  1.368099719817645#   (2, 1)  1.9587446035629748#   (3, 0)  0.3298189034212229 


I don't think this is problem that you have nan values, it's expected result.

If you wanna replace nan with 0 you can use np.nan_to_num (doc: https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html)