Val K
Val K

Reputation: 143

Removing zeros and then vertically collapse the matrix

In MATLAB, say I have a set of square matrices, say A, with trace(A)=0 as follows:

For example,

A = [0 1 2; 3 0 4; 5 6 0] 

How can I remove the zeros and then vertically collapse the matrix to become as follow:

A_reduced = [1 2; 3 4; 5 6]

More generally, what if the zeroes can appear anywhere in the column (i.e., not necessarily at the long diagonal)? Assuming, of course, that the total number of zeros for all columns are the same.

The matrix can be quite big (hundreds x hundreds in dimension). So, an efficient way will be appreciated.

Upvotes: 4

Views: 422

Answers (6)

Luis Mendo
Luis Mendo

Reputation: 112679

  • To compress the matrix vertically (assuming every column has the same number of zeros):

    A_reduced_v = reshape(nonzeros(A), nnz(A(:,1)), []);
    
  • To compress the matrix horizontally (assuming every row has the same number of zeros):

    A_reduced_h = reshape(nonzeros(A.'), nnz(A(1,:)), []).';
    

Upvotes: 4

Divakar
Divakar

Reputation: 221574

Case #1

Assuming that A has equal number of zeros across all rows, you can compress it horizontally (i.e. per row) with this -

At = A' %//'# transpose input array
out = reshape(At(At~=0),size(A,2)-sum(A(1,:)==0),[]).' %//'# final output

Sample code run -

>> A
A =
     0     3     0     2
     3     0     0     1
     7     0     6     0
     1     0     6     0
     0    16     0     9
>> out
out =
     3     2
     3     1
     7     6
     1     6
    16     9

Case #2

If A has equal number of zeros across all columns, you can compress it vertically (i.e. per column) with something like this -

out = reshape(A(A~=0),size(A,1)-sum(A(:,1)==0),[])  %//'# final output

Sample code run -

>> A
A =
     0     3     7     1     0
     3     0     0     0    16
     0     0     6     6     0
     2     1     0     0     9
>> out
out =
     3     3     7     1    16
     2     1     6     6     9

Upvotes: 3

Robert Seifert
Robert Seifert

Reputation: 25232

As your zeros are always in the main diagonal you can do the following:

l = tril(A, -1);
u = triu(A,  1);
out = l(:, 1:end-1) + u(:, 2:end)

Upvotes: 1

hbaderts
hbaderts

Reputation: 14316

I came up with almost the same solution as Mr E's though with another reshape command. This solution is more universal, as it uses the number of rows in A to create the final matrix, instead of counting the number of zeros or assuming a fixed number of zeros..

B = A.';
B = B(:);
C = reshape(B(B~=0),[],size(A,1)).'

Upvotes: 0

Kapoios
Kapoios

Reputation: 712

A correct and very simple way to do what you want is:

A = [0 1 2; 3 0 4; 5 6 0]

A =

 0     1     2
 3     0     4
 5     6     0

A = sort((A(find(A))))

A =

 1
 2
 3
 4
 5
 6

A = reshape(A, 2, 3)

A =

 1     3     5
 2     4     6

Upvotes: 0

YXD
YXD

Reputation: 32511

This seems to work, quite fiddly to get the behaviour right with transposing:

>> B = A';
>> C = B(:);
>> reshape(C(~C==0), size(A) - [1, 0])'

ans =

     1     2
     3     4
     5     6

Upvotes: 2

Related Questions