# How to find indices in a vector satisfying a condition for a minimum consecutive number of entries

3 views (last 30 days)
brandon burkholder on 13 Jan 2022
Edited: Jon on 13 Jan 2022
I have some time series
>> y = [2.1,2.5,4.6,2.2,3.4,2.1,3.3,4.4,2.4,5.6,4.3,4.4,2.3,3.0,5.7,3.4,3.8,3.9,1.6,2.0];
What I want to know is where in my time series I have consecutive numbers that satisfy some logical, lets say the logical is
condition = y < 4 & y > 1
Of course I know I can do
>> y(condition)
ans =
2.1000 2.5000 3.6000 2.2000 3.4000 2.1000 3.3000 2.4000 2.3000 3.0000 3.4000 3.8000 3.9000 1.6000 2.0000
But that is not what I want. I want to know where in the vector y this condition is satisfied but only when it is satisfied n times in a row. So if n = 3 then I would like to construct the logical below
condition2 = [0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1]
I have true where the elements of y satisfy the condition as part of 3 or more consecutive numbers, and false everywhere else. Even though the first 2 elements of y satisfy the logical condition, I don't want them because they aren't part of 3 or more values that satisfy the logical. For the solution I'd like to be able to vary n.

Jon on 13 Jan 2022
Edited: Jon on 13 Jan 2022
Here's one approach.
You could shorten this up a little by combining some of the individual statements into more complicated ones, but I expanded it out here to makeit easier to follow
y = [2.1,2.5,4.6,2.2,3.4,2.1,3.3,4.4,2.4,5.6,4.3,4.4,2.3,3.0,5.7,3.4,3.8,3.9,1.6,2.0];
% check where condition applies
idl = y<4 & y>1
% mark begin and end of each group where condition is met with a 1 or -1
% resp
ijmp = diff([0,idl]);
% just keep marks where groups begin
ibeg = ijmp>0;
% assign a group number to each group of ones
igroup = cumsum(ibeg).*idl
% find number of elements in each group, and where they come from
[count,edges,bin] = histcounts(igroup)
% assign number of repeats to each element according to which group it is
% in
numrep = count(bin)
% make a logical vector set true for each element that is in a group with a
% sufficient number of repeats
irep = numrep >= 3 & idl % don't include elements that are not in groups
Jon on 13 Jan 2022
Here's a further simplified approach
y = [2.1,2.5,4.6,2.2,3.4,2.1,3.3,4.4,2.4,5.6,4.3,4.4,2.3,3.0,5.7,3.4,3.8,3.9,1.6,2.0];
% check where condition applies
idl = y<4 & y>1
% mark begin and end of each group where condition is met with a 1 or -1
% resp
ijmp = diff([0,idl,0]);
% find number of elements in each group
itot = cumsum(cumsum(ijmp));
counts = itot(ijmp < 0) - itot(ijmp > 0) + 1;
% assign number of repeats to each element according to which group it is
% in
ijmp(ijmp>0) = counts;
ijmp(ijmp<0) = -counts;
numrep = cumsum(ijmp(1:end-1));
% make a logical vector set true for each element that is in a group with a
% sufficient number of repeats
irep = numrep >= 3