2017-05-01 3 views
2

관측 시간을 나타내는 float 값 목록이 있습니다. (각 float 값은 실제로 정수로 나타낼 수 있지만 가능한 미래 상황에 대해 일반화하기를 희망합니다.)중복을 포함하는 정렬 된 목록의 비 연속 부동 소수점 요소 사이에 한 개의 0을 어떻게 칠할 수 있습니까?

list_hrs = [4,6,8,8,10] # actual list is thousands of floats 

중복 항목이 한 번만 나오는 동안 색인과 일치하지 않는 값을 0으로 채우려고합니다. 예 목록 당, 나는 0에서 3에 포괄적으로 네 개의 숫자가 있기 때문에

list_hrs = [0,0,0,0,4,0,6,0,8,8,0,10] 

처음 네 개의 항목이 0입니다하려는 것입니다. 5이 없기 때문에 0 사이에 46이 필요합니다. 마찬가지로 068 사이입니다. 값이 9이므로 0810 사이에 있어야합니다. 또한, 복제본 8은 그대로두고 나중에 내 코드에서 다루게 될 것입니다. 0의 패딩을 수행하기 전에 8의 복제본을 한 번만 계산해야합니다. 그때 다른 SO 게시물을 읽고 처음 0 's의 목록,있는 길이가해야 할 것이 가장 인상 멀리 온

for index in range(len(list_hrs)): 
    if list_hrs != index: 
     list_hrs.insert(index, 0) 

>> [0, 0, 0, 0, 0, 4, 6, 8, 8, 10] 

:

내 첫 번째 시도는 이것을 시도했다 고려 된 데이터 포인트의 수와 같습니다. 그런 다음 0이 아닌 항목을 0 항목으로 바꿀 수 있습니다.

def make_zeros(hrs=list_hrs): # make list of 0's 
    num_zer = int(max(hrs)) 
    list_zer = [0 for index in range(num_zer+1)] 
    return list_zer 

하지만이 시점 이후에 원하는 결과를 달성하기 위해 조건을 구현하는 방법이 확실하지 : 그래서, 나는 다음 시도했다. 인덱스가 해당 인덱스의 값과 일치하는지 확인하려면 enumerate을 사용하는 방법이 있지만 중복 항목 (예 : 위의 예에서 8)으로 인해 진행 방법이 확실하지 않습니다.

이 방법을 계속 사용할 좋은 방향입니까? 아니면 원하는 결과를 얻으려면보다 효율적이고 간단한 방법이 있습니까? 도움이나 조언을 주시면 감사하겠습니다.

def make_zeros_vectorized(A, dtype=float): 
    a = np.asarray(A).astype(int) 
    idx = a + np.r_[0, (a[1:] == a[:-1]).cumsum()] 
    out = np.zeros(idx[-1]+1,dtype=dtype) 
    out[idx] = A 
    return out 

샘플 실행 - -

+0

그들은 왜 떠 다니는가, 거기에 10 진수를 기대합니까? '4.2'처럼 말할 수 있을까요? 그렇다면 출력은 어떻게 생겼을 까? – Divakar

+0

또한 입력은 항상 정렬됩니까? – Divakar

+0

각 플로트는 실제로 정수로 해석 될 수 있습니다. 예제 목록은 실제로는 [4.0,6.0,8.0,8.0,10.0]'이어야합니다. 나는 코드를 일반화하기를 희망했다. 그러나 정수의 경우에 대한 해결책이 있다면,이 경우에 잘 작동 할 것입니다. – mikey

답변

2

여기에 하나 벡터화 된 접근 방식과 관련된

In [95]: A 
Out[95]: [4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0] 

In [96]: make_zeros_vectorized(A) 
Out[96]: 
array([ 0., 0., 0., 0., 4., 0., 6., 0., 8., 8., 0., 
     10., 10., 10., 0., 0., 0., 14., 0., 16.]) 

In [100]: A 
Out[100]: [4.0, 4.0, 4.0, 4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0] 

In [101]: make_zeros_vectorized(A) 
Out[101]: 
array([ 0., 0., 0., 0., 4., 4., 4., 4., 0., 6., 0., 
     8., 8., 0., 10., 10., 10., 0., 0., 0., 14., 0., 
     16.]) 

단계

입력 목록

In [71]: A = [4.0,6.0,8.0,8.0,10.0,10.0,10.0,14.0,16.0] 

배열로 변환

In [72]: a = np.asarray(A).astype(int) 

In [73]: a 
Out[73]: array([ 4, 6, 8, 8, 10, 10, 10, 14, 16]) 

중복 마스크를 생성하십시오. 이 방법의 핵심은 나중에 누적 합계를 사용할 계획이므로중복이 참으로 표현되면서 누적 증분 값 초래 요약하면, 출력 배열에 입력 배열 값을 배치하는 증가 지표로서 사용

In [74]: a[1:] == a[:-1] 
Out[74]: array([False, False, True, False, True, True, False, False], dtype=bool) 

In [75]: (a[1:] == a[:-1]).cumsum() 
Out[75]: array([0, 0, 1, 1, 2, 3, 3, 3]) 

이전처럼 시작에서 제로를 추가 "A는 [1] [- 1] =="한 소자 적은 배열 이어질 것이다를

In [76]: np.r_[0, (a[1:] == a[:-1]).cumsum()] 
Out[76]: array([0, 0, 0, 1, 1, 2, 3, 3, 3]) 

중복 시프트되도록 마지막 입력 배열에 추가/하나 위로 첨가 따라서 출력 배열이 할당 될 인덱스를 제공합니다

In [77]: a + np.r_[0, (a[1:] == a[:-1]).cumsum()] 
Out[77]: array([ 4, 6, 8, 9, 11, 12, 13, 17, 19]) 

이후 단계는 기본적으로 출력 배열을 만들고 앞서 얻은 색인을 사용하여 a의 값을 할당합니다. 당신이 제로 또는 그 인덱스의 마스크가 필요한 경우


, 여기에 수정 된 버전입니다 -

def get_zeros_mask(A): 
    a = np.asarray(A).astype(int) 
    idx = a + np.r_[0, (a[1:] == a[:-1]).cumsum()] 
    mask = np.ones(idx[-1]+1,dtype=bool) 
    mask[idx] = 0 
    return mask 

샘플 실행 -

In [93]: A 
Out[93]: [4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0] 

In [94]: make_zeros_vectorized(A) 
Out[94]: 
array([ 0., 0., 0., 0., 4., 0., 6., 0., 8., 8., 0., 
     10., 10., 10., 0., 0., 0., 14., 0., 16.]) 

In [95]: get_zeros_mask(A) 
Out[95]: 
array([ True, True, True, True, False, True, False, True, False, 
     False, True, False, False, False, True, True, True, False, 
     True, False], dtype=bool) 

In [96]: np.flatnonzero(get_zeros_mask(A)) 
Out[96]: array([ 0, 1, 2, 3, 5, 7, 10, 14, 15, 16, 18]) 
+0

코드가 완벽하게 작동합니다! 당신이 한 일을 이해한다면,'np.r_'는 엔트리를 하나의리스트로 연결합니다. 나는'cumsum'이 누적 합계가되었지만 실제로 그 코드 행은 무엇입니까? – mikey

+0

설명해 주셔서 감사합니다. 다른 코드는 부동 소수점 처리 측면에서보다 유연하지만이 코드는 훨씬 빠르며 수천 개의 데이터 요소에 유용합니다. – mikey

+0

실제로 제로가 패딩되어야하는 인덱스를 찾는 것이 내 목적에 더 도움이됩니다. 그렇게하면 관찰 시간과 그 시간에 관측 값을 0으로 채울 수 있습니다 (관측이 발생하지 않은 시간은 관측 값이 0에 해당하므로). 나는이 목적을 위해이 코드를 적용 할 수 없었다. 당신은 내 원래 질문에 대한 완전한 작동 코드를 제공하기 위해 관대했다. 이 일을 처리하는 방법을 알아내는 것을 도와 주실 수 있습니까? 'out [idx] = A'를'out [not idx] = A'와 같은 것으로 바꾸려고 시도하는 것을 수정합니까? (나는 정확한 구문을 모른다.) – mikey

1

그냥 또 다른 예 :

list_hrs = [4,6,8,8,10] 
lh = iter(list_hrs) 
fit = range(int(max(list_hrs))+1) 

result = [0 if i not in list_hrs else next(lh) for i in fit for _ in range(list_hrs.count(i)) or [1]] 
+0

이전에 iter를 사용 해본 적이 없지만 이것은 나에게 의미가 있습니다. 다른 접근법에 감사드립니다. – mikey

+0

환영합니다 :) – zipa

+0

이 코드는 수레도 처리 할 수 ​​있기 때문에 더욱 다양합니다. – mikey

관련 문제