2014-04-11 3 views
3

시스템 기능에 대한 일반적인 쿼리를 나타내는 시계열이 있습니다 (1 = working0 = not working). 예를 들어, (시스템이 다운 켜져있는 시간을파이썬에서리스트의 동일한 항목 길이를 계산합니다.

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] 

내가 수리 실패합니다 (시스템이 켜져있는 시간), 평균 시간 평균 시간 같은 것들을 계산에 관심이 목록으로 시계열을 표현) 및 다른 유사한 통계 그래서 내가하고 싶은 것은 순차적 인 1 항목과 순차적 인 0 항목을 세는 것입니다. 위의 예에서 시스템이 처음 시작될 때나 앞으로 다시 올 때가 언제인지를 알 수 없기 때문에 시작과 끝 세트를 잘라 내고 싶습니다. 그래서이 경우 생성하고자하는 거라고 출력 내가이 작업을 수행하는 스크립트를 작성했습니다

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] 

것하지만 조금 어색한 것 같다 내가 더 나은, 더 파이썬이 있는지 궁금하네요 그것을하는 방법. 여기에 내가 가진 것이있다. 이 작품

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

,하지만 난 도움이되지만이 할 수있는 청소기 방법이 있는지 궁금 할 수 없습니다

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 

항복?

답변

1

당신은 itertools 모듈에서 groupby를 사용할 수 있습니다

from itertools import groupby 

testvalue = [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] 

def count_times(U, down=False): 
    if down: 
     return [len(list(group)) for key, group in groupby(U) if key == 0] 
    else: 
     return [len(list(group)) for key, group in groupby(U) if key == 1] 

print count_times(testvalues, True) # [2, 3, 3, 2, 1] 
print count_times(testvalues, False) # [6, 4, 9, 2] 
+0

무엇 OP는 물었다. 그는 다음과 같이 말했다. "위의 예에서 시스템이 처음 시작된 시점과 미래에 다시 나타날 시점을 알 수 없으므로 시작과 끝 세트를 정리해야합니다. 이 경우 생성해야 할 출력은' –

1

내 접근 방식은 루벤의 비슷하지만 처음 트림 쉽게 그래서 처음에, groupby을 적용 후 같은 목록의 배 아래로 유지 끝 세트.

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 

결과 :

[6, 4, 9, 2] 
[3, 3, 2] 
0

reduce 사용.

def groups(U,i): 
    a = reduce(lambda u,v: (u[0],u[1]+1) if v==i else (u[0] + [u[1]], 0) if u[1]>0 else u, U,([],0))[0] 
    if U[0]== i: a=a[1:] # truncate begining 
    if U[-1]==i: a=a[:-1] # truncate end 
    return a 


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] 

uptime = groups(U,1) 
downtime = groups(U,0) 
0

가끔은 런 길이 인코딩이라고도합니다. R에는 rle()에 대한 기본 제공 기능이 있습니다. 어쨌든 여기 내 접근 방식은 원래 takewhile() 사용에 대한 생각하지만 내가 생각할 수있는 가장 깨끗한 방법입니다 : 그럼 당신은 중단 또는 가동 시간과 같이 얻을 수

from itertools import chain 

def rle(x): 
    x = chain(x) 
    last = x.next() 
    i = 1 
    for item in x: 
     if item != last: 
      yield (last, i) 
      i = 1 
     else: 
      i += 1 
     last = item 
    yield (last, i) 

: 그것은 반환하지 않습니다

[L for v,L in rle(U) if v == 1] 
[L for v,L in rle(U) if v == 0] 
관련 문제