# Repeated consecutive values above a threshold

I would like to know if a list has repeated consecutive values above a threshold. Lets say for this example the threshold is 5.

list={0, 0, 1, 2, 3, 3, 4, 2, 1, 2, 0, 2, 6, 7, 6, 5, 4, 3, 3, 4, 6, 2, 7, 6, 5, 3, 5, 4, 5, 2, 2, 1, 2, 4, 3, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 3, 0, 1, 2}


because of the run 6, 7, 6, and 7, 6,the function should return True or 1 or some indication that consecutive values in the list are above the threshold.

If the threshold is 6 the function would yield False or 0 as there are no consecutive values above 6.

This code fails

Select[Split[list], First[#] > 5 && Length[#] > 1 &, Infinity]


The Split only works for consecutive values of the same value where I need it to split for consecutive values above a threshold.

I tried SplitBy but my pattern is incorrect.

SplitBy[list, Repeated[#] > 5 &]


I understand that neither of these functions above will give True or 1 but once the pattern is correct, taking it to the True or 1 is easy.

Fundamental operation:

t = 5;
us = UnitStep[list - (t+1)];

(* {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} *)


Then look for sequential ones by any method:

us*list // Differences // FreeQ[1] // Not

MatchQ[us, {___, 1, 1, ___}]

Max @ ListConvolve[{1, 1}, us] > 1

• Thank you. I'm so grateful. I would have never approached the problem in this way. I was killing myself on finding the correct pattern. Jan 20, 2017 at 20:50
• you could directly use MatchQ on the list as MatchQ[list, {___, x_Integer /; x > #, y_Integer /; y > #, ___}] &@5 (I guess the above performs better though) Jan 20, 2017 at 21:45
• I think Clip[list, {t+1, t}, {0, 1}] is slightly faster than UnitStep[list - (t+1)]. Jan 20, 2017 at 22:08
• @CarlWoll I don't believe that I was aware that in the second parameter of Clip min could be larger than max. However on my system UnitStep is several times faster than your Clip expression. Jan 20, 2017 at 23:02

For short lists we could also use SequenceSplit (new in 11.3)

f = DeleteCases[{_}] @ SequenceSplit[# - (th + 1), {_?Negative}] != {} &;

th = 5;


No repetitions above th

list = {6, 0, 0, 5, 5, 8, 0, 6};

f @ list

(* False *)


Repetition(s) above th

list = {6, 0, 0, 6, 6, 5, 5, 8, 0, 6};

f @ list

(* True *)


SequenceSplit is, however, much slower than the accepted answer

list = RandomInteger[{0, 7}, 10^6];

f @ list // RepeatedTiming


{1.445, True}

UnitStep[list - (th + 1)] // Differences // FreeQ[1] // Not // RepeatedTiming


{0.008, True}

• I tried to look for a faster alternative than the accepted one, but I definitely couldn't think of anything better. Hopefully soon the Wolfram developers will improve the speed of the functions dedicated to sequences, since they are more practical and flexible. Jan 9 at 23:44
• Yes, many functions have become much faster over the years. In the meanwhile I use the very nice and readable sequence-functions for short lists.
– eldo
Jan 9 at 23:52

Grabbing the @eldo's examples, a faster version using Split is as follows:

list1 = {6, 0, 0, 5, 5, 8, 0, 6};
list2 = {6, 0, 0, 6, 6, 5, 5, 8, 0, 6};
list3 = RandomInteger[{0, 7}, 10^6];

f[list_, th_] := Module[{sp, pos},
sp = Split[list];
pos = First@FirstPosition[{_, __}]@Reverse@sp;
Length@Catenate@DeleteCases[{_}]@sp[[;; pos]] > th]

f[list1, 5]

(*False*)

f[list2, 5]

(*True*)

f[list3, 5] // RepeatedTiming

(*{0.347102, True}*)