Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiplying elements in a sparse array with rows in matrix

If you have a sparse matrix X:

>> X = csr_matrix([[0,2,0,2],[0,2,0,1]])
>> print type(X)    
>> print X.todense()    
<class 'scipy.sparse.csr.csr_matrix'>
[[0 2 0 2]
 [0 2 0 1]]

And a matrix Y:

>> print type(Y)
>> print text_scores
<class 'numpy.matrixlib.defmatrix.matrix'>
[[8]
 [5]]

...How can you multiply each element of X by the rows of Y. For example:

[[0*8 2*8 0*8 2*8]
 [0*5 2*5 0*5 1*5]]

or:

[[0 16 0 16]
 [0 10 0 5]]

I've tired this but obviously it doesn't work as the dimensions dont match: Z = X.data * Y

like image 640
Zach Avatar asked Sep 02 '12 16:09

Zach


People also ask

How do you multiply matrices with different rows?

To multiply one matrix with another, we need to check first, if the number of columns of the first matrix is equal to the number of rows of the second matrix. Now multiply each element of the column of the first matrix with each element of rows of the second matrix and add them all.

Can you multiply matrix rows?

You can multiply any row by a number. (This means multiplying every entry in the row by the same number.) In this example, we have multiplied Row 3 of the matrix by 13 .


2 Answers

Unfortunatly the .multiply method of the CSR matrix seems to densify the matrix if the other one is dense. So this would be one way avoiding that:

# Assuming that Y is 1D, might need to do Y = Y.A.ravel() or such...

# just to make the point that this works only with CSR:
if not isinstance(X, scipy.sparse.csr_matrix):
    raise ValueError('Matrix must be CSR.')

Z = X.copy()
# simply repeat each value in Y by the number of nnz elements in each row: 
Z.data *= Y.repeat(np.diff(Z.indptr))

This does create some temporaries, but at least its fully vectorized, and it does not densify the sparse matrix.


For a COO matrix the equivalent is:

Z.data *= Y[Z.row] # you can use np.take which is faster then indexing.

For a CSC matrix the equivalent would be:

Z.data *= Y[Z.indices]
like image 165
seberg Avatar answered Nov 03 '22 17:11

seberg


Something I use to perform row-wise (resp. column-wise) multiplication is to use matrix multiplication with a diagonal matrix on the left (resp. on the right):

import numpy as np
import scipy.sparse as sp

X = sp.csr_matrix([[0,2,0,2],
                   [0,2,0,1]])
Y = np.array([8, 5])

D = sp.diags(Y) # produces a diagonal matrix which entries are the values of Y
Z = D.dot(X) # performs D @ X, multiplication on the left for row-wise action

Sparsity is preserved (in CSR format):

print(type(Z))
>>> <class 'scipy.sparse.csr.csr_matrix'>

And the output is also correct:

print(Z.toarray()) # Z is still sparse and gives the right output
>>> print(Z.toarray()) # Z is still sparse and gives the right output
[[ 0. 16.  0. 16.]
 [ 0. 10.  0.  5.]]
like image 43
ngazagna Avatar answered Nov 03 '22 17:11

ngazagna