Max / Min of sparse matrices
이전 댓글 표시
I previously asked this question:
It was answered perfectly, except now I realize that I need to deal with a sparse matrix. If I set the zero elements to be NaN, I run out of memory. So the question is, how to find the row and column max and min of a sparse matrix, excluding the zero elements. Creating a full matrix is not an option. Any help would be appreciated.
채택된 답변
추가 답변 (3개)
Richard Brown
2012년 4월 12일
Can't do this one quite so cutely :)
Try this (for rows), you can do the same thing for columns with a trivial modification
[m,n] = size(A);
rowMin = zeros(m, 1);
rowMax = zeros(m, 1);
[I,J,S] = find(A)
for i = 1:m
s = S(I == i);
% you may need this condition, depending on your matrix
if ~isempty(s)
rowMin(i) = min(s);
rowMax(i) = max(s);
end
end
댓글 수: 3
Edward Umpfenbach
2012년 4월 12일
Richard Brown
2012년 4월 12일
Have you tried it? for loops are not as bad as you might think - your performance will depend on the sparsity of your matrix
Richard Brown
2012년 4월 12일
Oh, and if you can get rid of the isempty condition, then that will help a little
Geoff
2012년 4월 12일
Here is a solution for rows (similar for columns)...
If you know that every row contains at least one non-zero value, you can do this:
rmax = arrayfun( @(row) full(max( A(row, A(row,:)~=0) )), 1:size(A,1) );
rmin = arrayfun( @(row) full(min( A(row, A(row,:)~=0) )), 1:size(A,1) );
If a row can be empty, you will need to do:
rmax = arrayfun( @(row) blahblah, 1:size(A,1), 'UniformOutput', false );
rmin = likewise
In that case your rmax, rmin will be cell arrays. You possibly want to turn the empty cells into NaNs and get the whole thing back as a vector:
rmax( cellfun(@(c) isempty(c), rmax) ) = {NaN};
rmin( cellfun(@(c) isempty(c), rmin) ) = {NaN};
rmax = cell2mat(rmax);
rmin = cell2mat(rmin);
댓글 수: 1
Hesameddin KHosravi
2019년 2월 18일
Thank you so much, this function wrorks for me but how can I get index of minimal array?
Oleg Komarov
2012년 4월 12일
For the max you should not have any problems:
% Find the max (along columns)
[mmax,Imax] = max(A,[],2);
[rmax,~,mmax] = find(mmax);
cmax = Imax(rmax);
% Similarly, find the max along rows
[mmax,Imax] = max(A);
[~,cmax,mmax] = find(mmax);
rmax = Imax(cmax);
In case of all positive numbers, to find the min, e.g. along columns, you can take the negative of A and shift the numbers by the maximum you found before:
% Take negative and shift to positive
[nnzr,nnzc] = find(A);
B = -A + sparse(nnzr,nnzc,max(mmax),m, n);
% Now find the MIN which involves taking the max (along columns)
[mmin,Imin] = max(B,[],2);
[rmin,~,mmin] = find(mmin);
cmin = Imin(rmin);
% Shift back and retake negative
mmin = -(mmin - max(mmax));
WARNING: you may have the same numbers for min and max because it's the only one.
NOTE: if you have negative numbers as well, then using simply max and min wors fine.
Elapsed time is 0.029157 seconds.
댓글 수: 4
Richard Brown
2012년 4월 12일
Assuming the max > 0 ...
Edward Umpfenbach
2012년 4월 13일
Oleg Komarov
2012년 4월 13일
@Edward: I wrote a full example on how to retrieve the min.
@Richard: if max < 0, then the min is trivial and the max involves the shifting procedure.
In case you numbers are on the domain [-,+] then it's trivial to take max and min.
Richard Brown
2012년 4월 13일
I like this approach - it will certainly be faster.
카테고리
도움말 센터 및 File Exchange에서 Creating and Concatenating Matrices에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!