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 !

 採用された回答

Ameer Hamza
Ameer Hamza 2020 年 4 月 26 日
編集済み: Ameer Hamza 2020 年 4 月 26 日

1 投票

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 件のコメント

Geraldine Ejimadu
Geraldine Ejimadu 2020 年 4 月 26 日
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
Ameer Hamza
Ameer Hamza 2020 年 4 月 26 日
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'.
Geraldine Ejimadu
Geraldine Ejimadu 2020 年 4 月 26 日
Ok, got it!
What do you mean by "connected"/connectivity referred to the non zero rows?
Ameer Hamza
Ameer Hamza 2020 年 4 月 26 日
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.
Geraldine Ejimadu
Geraldine Ejimadu 2020 年 4 月 27 日
It works, thank you so much!!!

サインインしてコメントする。

その他の回答 (1 件)

dpb
dpb 2020 年 4 月 26 日

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 件のコメント

Geraldine Ejimadu
Geraldine Ejimadu 2020 年 4 月 26 日
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?
dpb
dpb 2020 年 4 月 27 日
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.
Geraldine Ejimadu
Geraldine Ejimadu 2020 年 4 月 27 日
Thank you!! This is really helpful!
dpb
dpb 2020 年 4 月 27 日
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...

サインインしてコメントする。

カテゴリ

ヘルプ センター および File ExchangeLoops and Conditional Statements についてさらに検索

質問済み:

2020 年 4 月 26 日

コメント済み:

dpb
2020 年 4 月 27 日

Community Treasure Hunt

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

Start Hunting!

Translated by