Asked by gianluca scutiero
on 3 Nov 2017

Hello everybody ... I have a big matrix [N] as shown in Figure. I need to extract sub-matrix from [N]: [A],[B],[C],[D], [E] .... The end of each row can contain some zeros (red part). So I need to extract these sub-matrix. If [A] has the same number of columns of [E], I have to combine them in a unique matrix ([F]=[A];[E]). [N] does not contain zeros in the white part. Could you help me with this problem? Thank you very much for your time

Answer by Cedric Wannaz
on 3 Nov 2017

Edited by Cedric Wannaz
on 3 Nov 2017

Accepted Answer

Here is an example; we first build a test data set:

>> N = randi( 10, 10, 4 ) ;

>> for k = 1 : 10, N(k,1+randi(3,1):end) = 0 ; end

>> N

N =

8 0 0 0

3 3 9 0

6 0 0 0

7 3 0 0

9 0 0 0

10 4 0 0

6 0 0 0

2 3 0 0

2 7 4 0

3 5 6 0

Then sorting/grouping can be achieved as follows:

>> gId = sum( N == 0, 2 ) ;

>> groups = splitapply( @(x){x}, N, gId ) ;

With that you get:

>> groups

groups =

3×1 cell array

{3×4 double}

{3×4 double}

{4×4 double}

>> groups{1}

ans =

3 3 9 0

2 7 4 0

3 5 6 0

>> groups{2}

ans =

7 3 0 0

10 4 0 0

2 3 0 0

>> groups{3}

ans =

8 0 0 0

6 0 0 0

9 0 0 0

6 0 0 0

This assumes that there is no zero aside from the trailing ones on each row. We can work releasing this requirement if there can be zeros elsewhere, and on truncation to the non-zero part if you really need it.

EDIT : Here are the few extra steps if you wanted to deal with situations with zeros in the middle of non-zeros, and if you needed truncation: I start by adding a zeros in N(9,2) to test that it is working:

>> N(9,2) = 0 ;

Then

>> [r, c] = find( N ) ;

last_nzc = splitapply( @max, c, r ) ;

gId = findgroups( size(N, 2) - last_nzc + 1 ) ;

groups = splitapply( @(x,c){x(:,1:c(1))}, N, last_nzc, gId ) ;

With that we get:

>> groups{1}

ans =

3 3 9

2 0 4

3 5 6

>> groups{2}

ans =

7 3

10 4

2 3

>> groups{3}

ans =

8

6

9

6

Cedric Wannaz
on 3 Nov 2017

Note that I initially wrote x(:,1:c) in the call to SPLITAPPLY, which went through. That is surprising(!) This lead me to evaluate the following:

>> 1 : [4,5,6]

ans =

1 2 3 4

which is interesting ...

Sign in to comment.

Answer by Guillaume
on 3 Nov 2017

If I understood correctly:

%N: your big matrix

rowswithnozeros = cellfun(@(row) nonzeros(row).', num2cell(N, 2), 'UniformOutput', false);

rowlength = cellfun(@numel, rowswithnozeros);

[~, ~, subs] = unique(rowlength, 'stable'); %s'stable' optional

matriceswithnozeros = accumarray(subs, (1:numel(rowswithnozeros))', [], @(rows) {vertcat(rowswithnozeros{rows})});

gianluca scutiero
on 3 Nov 2017

Guillaume
on 3 Nov 2017

"But is there the possibility to join the rows generated with the same numbers of columns ?"

That's the whole purpose of the last three lines.

gianluca scutiero
on 3 Nov 2017

Sorry !!!! I appreciated very much your help ... thank you :)

Sign in to comment.

Answer by gianluca scutiero
on 3 Nov 2017

Thank you very much, Cedric Wannaz. It works very well. :)

Cedric Wannaz
on 3 Nov 2017

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 2 Comments

## KL (view profile)

## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/364987-how-extract-sub-matrix-without-zeros-from-a-big-matrix#comment_500787

## gianluca scutiero (view profile)

## Direct link to this comment

https://fr.mathworks.com/matlabcentral/answers/364987-how-extract-sub-matrix-without-zeros-from-a-big-matrix#comment_500792

Sign in to comment.