Finding consecutive data with non zero in array
20 views (last 30 days)
Show older comments
edward kabanyas
on 15 Sep 2019
Edited: edward kabanyas
on 7 Oct 2019
Hi all;
I want to find consecutive data with non zero value in array. However, as long as the data with 0 value is less than 3 points, it is still considered as part of the previous data set. The data with the same length is classified into same array.
For example:
xx = [1 2 3 0 1 2 0 0 0 1 2 3 4 0 1 0 0 0 1 1 1];
The expected result
xx1 =[1 2 3 0 1 2; 1 2 3 4 0 1];
xx2=[1 1 1];
I try to find it using looping procedure but it takes only onsecutive data with non zero value and I can not find the solution for this criteria "as long as the data with 0 value is less than 3 points".
Hope some help.
Thank you.
Edward
2 Comments
Rik
on 16 Sep 2019
Comment posted as answer by edward kabanyas:
Thank you Rik. The following is my code:
threshold = 0;
transitions = diff([0, xx > threshold, 0]);
runstarts = find(transitions == 1);
runends = find(transitions == -1) - 1;
blocks = arrayfun(@(s, e) xx(s:e), runstarts, runends, 'UniformOutput', false);
celldisp(blocks)
However, it takes only onsecutive data with non zero value and I can not find the solution for the criteria "as long as the data with 0 value is less than 3 points". Then, the cell with same size in blocks is not merged into one cell as I need above.
Accepted Answer
Andrei Bobrov
on 16 Sep 2019
Edited: Andrei Bobrov
on 5 Oct 2019
for R2013a (and for your data from all_data.txt)
f = fopen('all_data.txt');
Data = textscan(f,'%f %f %f %f %f %f %f','CollectOutput',1);
fclose(f);
Data = Data{:};
lo = any(Data(:,6:7) ~= 0,2);
d = find(lo);
ii = [true;diff(d) > 3];
i2 = ii([2:end,1]);
i = zeros(size(Data,1),1);
i(d(ii)) = 1;
i(d(i2) + 1) = -1;
j = cumsum(i);
jj = cumsum([false;diff(j) == 1]).*j;
out = accumarray(jj+1,(1:size(Data,1))',[],@(x){Data(sort(x),:)});
out = out(2:end);
10 Comments
More Answers (1)
Rik
on 16 Sep 2019
I used the mfile version of Jan's FEX submission RunLength, because I can't get my compiler to work right now. With the runlegth determined it is relatively easy to find the groups that need to be merged. Then you can still use the code you proposed to find the transitions.
xx = [1 2 3 0 1 2 0 0 0 1 2 3 4 0 1 0 0 0 1 1 1];
[a,b]=RunLength_M(xx~=0);
L= a(:)==false & b<3;%to be merged
%checks for egde cases should be perfomed here:
%-first group is a small group of zeros
%-last group is a small group of zeros
L_prev=[L(2:end);false];
L_next=[false;L(1:(end-1))];
b(L_prev)=b(L_prev)+b(L)+b(L_next);
a(L | L_next)=[];%remove merged parts
b(L | L_next)=[];%remove merged parts
x=RunLength_M(a,b);
transitions = diff([0, RunLength_M(a,b), 0]);
runstarts = find(transitions == 1);
runends = find(transitions == -1) - 1;
blocks = arrayfun(@(s, e) xx(s:e), runstarts, runends, 'UniformOutput', false);
celldisp(blocks)
5 Comments
Rik
on 5 Oct 2019
Edited: Rik
on 5 Oct 2019
It turns out you also need to use (:) for b if your input is a column vector. I just tested this on R2011a, so it should also works on ancient releases. I'll edit my answer.
Edit: except that your example is integer only and your data isn't, which seems to be causing problems.
See Also
Categories
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!