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)