Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calculating the length of identical entries in list in python

Tags:

python

I have a time series representing regular queries into the functionality of a system, where 1 = working and 0 = not working. For example, expressing the time series as a list

U = [0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,0]

I am interested in calculating things like the mean time to failure (how long the system stays up) and the mean time to repair (how long the system stays down) and other similar statistics so what I want to do is count the sequential 1 entries and the sequential 0 entries. I want to trim off the beginning and end sets since, for the example above, I don't know when the system went down initially nor when it will come back up in the future. So the output I'd be looking to generate in this case would be

uptime = [6, 4, 9, 2] # 6 ones followed by zeros, then 4 ones followed by zeros, etc.
downtime = [3, 3, 2] # like uptime but ignoring zeros at indices [0,1] and [-1] 

I've written a script that does this but it seems a little bit awkward and I'm wondering if there's a better, more pythonic way to do it. Here's what I have.

def count_times(U, down=False):
    if down:
        U = [1 - u for u in U]
    T = [] 
    # Skip the first entry as you don't know when it started
    m = U.index(0)
    m += U[m:].index(1)
    while m < len(U):
        try:
            T.append(U[m:].index(0))
            m += U[m:].index(0)
            m += U[m:].index(1)
        except ValueError:
            # skip the last entry as you don't know when it will end
            return T

yielding:

print count_times(U)
# [6, 4, 9, 2]
print count_times(U, down = True)
# [3, 3, 2]

This works, but I can't help but wonder if there is a cleaner way to do this?

like image 736
ramzeek Avatar asked Nov 22 '25 12:11

ramzeek


1 Answers

My approach is similar to Ruben's, but it initially keeps the up and down times in the same list after applying groupby, so it's easier to trim the beginning and ending sets.

import itertools
U = [0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,0]
run_lengths = [(value, len(list(group))) for value, group in itertools.groupby(U)]

#discard first and last runs
run_lengths = run_lengths[1:-1]

#split runs into separate up and down time lists
uptime = [length for value, length in run_lengths if value == 1]
downtime = [length for value, length in run_lengths if value == 0]

print uptime
print downtime

Result:

[6, 4, 9, 2]
[3, 3, 2]
like image 140
Kevin Avatar answered Nov 24 '25 01:11

Kevin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!