Length (count) of sequences with start and end condition Python
Using itertools.dropwhile
and takewhile
:
l = [-1.1, -1, 0, 1.2, 1.8, 2, 2.88, 2.86, 2.53, 1.98, 1.21, 0.89, 0.11, -0.21]
list(takewhile(lambda x: x > 0, dropwhile(lambda x: x < 2.78, l)))
Output:
[2.88, 2.86, 2.53, 1.98, 1.21, 0.89, 0.11]
Or just to get len
:
sum(1 for _ in takewhile(lambda x: x > 0, dropwhile(lambda x: x < 2.78, l)))
# 7
will this work if there are multiple times this occurs in the dataset? I want to identify each one.
Let's switch from takewhile
and dropwhile
to groupby
with a global boolean flag to identify multiple sequences. I'm simply going to concatenate your data onto itself to simulate two sequences:
from itertools import groupby
def keyfunc(datum):
global in_sequence
if datum < 0:
in_sequence = False
elif datum > 2.78:
in_sequence = True
return in_sequence
data = [
-1.1, -1, 0, 1.2, 1.8, 2, 2.88, 2.86,
2.53, 1.98, 1.21, 0.89, 0.11, -0.21,
-1.1, -1, 0, 1.2, 1.8, 2, 2.88, 2.86,
2.53, 1.98, 1.21, 0.89, 0.11, -0.21,
]
sequences = []
in_sequence = False
for valid, sequence in groupby(data, keyfunc):
if valid:
sequences.append(list(sequence))
print(*sequences, sep='\n')
print(*map(len, sequences), sep='\n')
OUTPUT
> python3 test.py
[2.88, 2.86, 2.53, 1.98, 1.21, 0.89, 0.11]
[2.88, 2.86, 2.53, 1.98, 1.21, 0.89, 0.11]
7
7
>
Is it possible to tighten it up though to only provide the len numbers as I want to then convert into a df and export to csv?
Perhaps something like this:
from itertools import groupby
data = [
-1.1, -1, 0, 1.2, 1.8, 2, 2.88, 2.86,
2.53, 1.98, 1.21, 0.89, 0.11, -0.21,
-1.1, -1, 0, 1.2, 1.8, 2, 2.88, 2.86,
2.53, 1.98, 1.21, 0.89, 0.11, -0.21,
]
def sequence_lengths(data):
in_sequence = False
def keyfunc(datum):
nonlocal in_sequence
if datum < 0:
in_sequence = False
elif datum > 2.78:
in_sequence = True
return in_sequence
lengths = []
for valid, sequence in groupby(data, keyfunc):
if valid:
lengths.append(len(list(sequence)))
return lengths
print(sequence_lengths(data))