Select matrices with nonzero rows from a bigger matrix ?

Hello guys!
I am struggling with this problem:
I have a big matrix that is made of few zeros raws and many nonzero raws.
This is a fake simple example to explain, because in reality I am working with big data :(:
B= [0 0 0 0;
0 0 0 0;
0 0 0 0;
0 0 0 0 ;
1 1 2 3;
0 0 0 3;
1 1 1 0;
4 4 4 4;
0 0 0 0 ;
0 0 0 0;
0 0 0 0 ;
0 0 0 8;
0 0 1 0;
0 1 1 0;
0 0 0 0;
0 0 0 0 ];
The zero rows in this matrix, indicate that the signal stopped and I just need to analyse the non zero raws in chunks.
Therefore would like to obtain:
chunk_1=[1 1 2 3;0 0 0 3;1 1 1 0;4 4 4 4]
chunk_2=[0 0 0 8;0 0 1 0;0 1 1 0;]
As you can see the chunks don't have to have the same amount of raws, since I analyse them individually, and the zero chunks also don't have the same number of rows.
I hope you guys have more knowledge than ve and could help me!
Thanks in advance !

 Accepted Answer

This nice little function from the image processing toolbox (bwconncomp) will be very useful here.
B = [0 0 0 0;0 0 0 0;0 0 0 0;0 0 0 0 ;1 1 2 3;0 0 0 3;1 1 1 0;4 4 4 4; 0 0 0 0 ;0 0 0 0;0 0 0 0 ;0 0 0 8;0 0 1 0;0 1 1 0;0 0 0 0;0 0 0 0 ];
mask = sum(B, 2)~=0;
comps = bwconncomp(mask);
compMaskList = comps.PixelIdxList;
B_components = cell(numel(compMaskList), 1);
for i=1:numel(compMaskList)
B_components{i} = B(compMaskList{i}, :);
end
This shorter version is equivalent to the above code
comps = bwconncomp(sum(B, 2)~=0);
B_comps = cellfun(@(x) {B(x, :)}, comps.PixelIdxList);

5 Comments

woow, thank you. I didn't expect such a fast response :)
If you don't mind, what does the function bwconncomp do exactly? I am still at a basic level so I don't understand the code so well.
Thank You
bwconncomp is actually an image processing function. It is used to find out connected components in a black-white image (binary). So we can use it to find out connected non-zero rows by creating a mask with this term 'sum(B, 2)~=0'.
Ok, got it!
What do you mean by "connected"/connectivity referred to the non zero rows?
If you run 'sum(B, 2)~=0', you get
>> sum(B, 2)~=0
ans =
16×1 logical array
0
0
0
0
1
1
1
1
0
0
0
1
1
1
0
0
So bwconncomp detects that there are two groups of 1s and gives back their row number.
It works, thank you so much!!!

Sign in to comment.

More Answers (1)

Any number of these kinds of Q? on Answers -- under "runs" or any number of other terms...but, it's pretty simple to code from scratch--
d=diff([false;any(B,2)]); % locations with any observations--T
ix=[find(d==1) find(d==-1)]; % find start, end of sections 0->1, 1->0
C=arrayfun(@(i) B(ix(i,1):ix(i,2),:),1:size(ix,1),'UniformOutput',false); % cell array of contents by group

4 Comments

Thank You so much! I am trying to understand line 2 and 3, so that I can make it work for my data.
Could you please explain them to me? Line 2, and the use of arrayfun and the indexing in line 3?
Try it with your simple example data...start from inside out--first what is "d"?---
>> [B d]
ans =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 2 3 1
0 0 0 3 0
1 1 1 0 0
4 4 4 4 0
0 0 0 0 -1
0 0 0 0 0
0 0 0 0 0
0 0 0 8 1
0 0 1 0 0
0 1 1 0 0
0 0 0 0 -1
0 0 0 0 0
>>
any(x,2) gave us a true everywhere there was any nonzero row; diff() on that is only +/-1 when the value changes -- an initial start, then stop, ...
Next, simply extract those start:stop locations to an array of two vectors.
arrayfun is just a for...end loop on one line -- it uses the anonymous function @(i) B(ix(i,1):ix(i,2),:) as its action -- that's just a colon operation of B(i1:i2) for rows and : for all columns.
The next term is the indices over which to loop: 1:size(ix,1) which is just the number of row in our indexing array we built. Could write the function to use two input arguments and pass ix(:,1), ix(:,2); I just used the one index to the array and put the ix array inside.
Lastly, since returns a variable number of outputs, arrayfun needs to know to return results as a cell array or 'uniformoutput', false Otherwise, it'll fail as the output would have to be able to be concatenated into a single ouptut. But, you don't really want that here,anyway; you get the cell array of the data you're looking for for each case in a cell containing the array of doubles.
Thank you!! This is really helpful!
Very common type problem and typical use of diff for pattern-matching. "Trick" worth knowing; can adapt to many situations with thought.
May not always have Image Processing TB (as I don't) so need to be able to do oneself...

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!