fpnick
fpnick

Reputation: 439

Scale every row in a sparse matrix by an element of a vector in MATLAB

I have a sparse matrix

obj.resOp = sparse(row,col,val); 

and a vector containing the sums of each row in the matrix

sums = sparse(sum(obj.resOp,2));

Now what I want to do is

obj.resOp = obj.resOp ./ sums;

which would scale every row in the matrix so that the rowsum in each row is 1.

However in this last line, MATLAB internally seems to construct a full matrix from obj.resOp and hence I get this error:

Error using ./ Requested 38849x231827 (17.5GB) array exceeds maximum array size preference. Creation of arrays greater than this limit may take a long time and cause MATLAB to become unresponsive. See array size limit or preference panel for more information.

for sufficiently large matrices.

In theory I think that expanding to a full matrix is not necessary. Is there any MATLAB formulation of what I want to achieve while keeping the sparsity of obj.resOp?

Upvotes: 2

Views: 363

Answers (2)

fpnick
fpnick

Reputation: 439

The equivalent calculation

obj.resOp = inv(diag(sums)) * obj.resOp;

works smoothly.

Upvotes: 0

Wolfie
Wolfie

Reputation: 30101

You can do this with a method similar to the one described in this answer.

Start with some sparse matrix

% Random sparse matrix: 10 rows, 4 cols, density 20%
S = sprand(10,4, 0.2);

Get the row sums, note that sum returns a sparse matrix from sparse inputs, so no need for your additional conversion (docs).

rowsums = sum(S,2);

Find all non-zero indices and their values

[rowidx, colidx, vals] = find(S)

Now create a sparse matrix from the element-wise division

out = sparse(rowidx, colidx, vals./rowsums(rowidx), size(S,1), size(S,2));

Upvotes: 2

Related Questions