2017-09-04 3 views
1

팬더 데이터 프레임에 시계열이 있습니다. 타임 스탬프는 고르지 않을 수 있지만 (1 ~ 5 분마다 하나씩), 항상 5 분마다 하나씩 있습니다 (05101520253035404550으로 끝나는 타임 스탬프가 있음). , 55).Python - 시간 가중 평균 팬더 시간 간격으로 그룹화

예 :

2017-01-01 2:05:00 32.90 
2017-01-01 2:07:30 29.83 
2017-01-01 2:10:00 45.76 
2017-01-01 2:15:00 16.22 
2017-01-01 2:20:00 17.33 
2017-01-01 2:25:00 23.40 
2017-01-01 2:28:45 150.12 
2017-01-01 2:30:00 100.29 
2017-01-01 2:35:00 38.45 
2017-01-01 2:40:00 67.12 
2017-01-01 2:45:00 20.00 
2017-01-01 2:50:00 58.41 
2017-01-01 2:55:00 58.32 
2017-01-01 3:00:00 59.89 

내가 15 분 블록의 시간 가중 평균 싶어. 15 분 마크 구간 끝 (0,15,30,45 끝나는 분 타임 스탬프)에 바로 타임 스탬프 행하므로 그룹핑은 다음과 같다 :

Group 1 (interval 2017-01-01 2:00:00): 
    2017-01-01 2:05:00 32.90 
    2017-01-01 2:07:30 29.83 
    2017-01-01 2:10:00 45.76 
    2017-01-01 2:15:00 16.22 

Group 2 (interval 2017-01-01 2:15:00): 
    2017-01-01 2:20:00 17.33 
    2017-01-01 2:25:00 23.40 
    2017-01-01 2:28:45 150.12 
    2017-01-01 2:30:00 100.29 

Group 3 (interval 2017-01-01 2:30:00): 
    2017-01-01 2:35:00 38.45 
    2017-01-01 2:40:00 67.12 
    2017-01-01 2:45:00 20.00 

Group 4 (interval 2017-01-01 2:45:00): 
    2017-01-01 2:50:00 58.41 
    2017-01-01 2:55:00 58.32 
    2017-01-01 3:00:00 59.89 

평균은이어야 시간 가중치가 적용되므로 그룹의 모든 값의 표준 평균이 아닙니다.

예를 들어, 그룹 2의 시간 가중 평균은 72.785가 아니며 모든 4 값의 정규 평균입니다. 또한 이상적으로, 15 분 매개 변수화

(5 minutes/15 minutes) * 17.33 = 5.776667  ==> The 5 minutes is taken from the difference between this timestamp and the previous timestamp 
+(5 minutes/15 minutes) * 23.40 = 7.8 
+(3.75 minutes/15 minutes) * 150.12 = 37.53 
+(1.25 minutes/15 minutes) * 100.29 = 8.3575 

= **59.46417** 

이 60 분 (시간당)에 향후 변경 될 수 있습니다로,하지만 난이 여기에 문제가 있다고 생각하지 않습니다 오히려해야합니다.

또한 성능이 매우 중요합니다. 내 데이터 세트가 약 10k 행을 가지므로 각 레코드를 하나씩 반복하는 것은 매우 느립니다.

팬더의 df.rolling() 함수를 살펴 보았지만 특정 시나리오에 직접 적용하는 방법을 알 수 없었습니다.

도움을 주셔서 감사합니다.

UPDATE 1 :

시몬의 확실한 해결책 다음은, 내가 그것을 조금 수정했습니다.

def func(df): 
    if df.size == 0: return 
    timestep = 15*60 
    indexes = df.index - (df.index[-1] - pd.Timedelta(seconds=timestep)) 
    seconds = indexes.seconds 
    weight = [seconds[n]/timestep if n == 0 else (seconds[n] - seconds[n - 1])/timestep 
      for n, k in enumerate(seconds)] 
    return np.sum(weight*df.values) 

이합니다 (DB 행없는) 비어로 15 분 간격으로

답변

3

이 하나 있었다 대처하는 것입니다

나는 나의 특정한 경우에 적응하는 데에 몇 개조하면 되겠했다 교활한. 나는 이것을하기에 더 좋은 방법이 있다는 직감이 있기 때문에 다른 주석 작성자가보다 효율적으로 이것을하는 것을보고 싶다.

또한 15 분 값을 매개 변수화하는 한 부분을 건너 뛰었지만 주석에서 어떻게 할 수 있는지 설명했습니다. 이것은 독자의 연습 과제로 남겨 두었습니다 : D 그것은 매개 변수화되어야합니다. 그곳에는 무작위의 '* 15'와 '* 60'값들이 많이 있습니다.

나는 또한 피곤하고 내 아내는 영화를보고 싶어하므로 코드를 정리하지 않았습니다. 좀 지저분하고 더 깨끗하게 쓰여 져야합니다. 다른 사람이 6 줄의 코드로이 모든 것을 다시 할 수 있는지에 따라 달라질 수 있습니다. 내일 아침에 아직도 답이 없다면 나는 다시 돌아가서 이것을 잘 할 것이다.

def func(df): 
    timestep = 15*60 
    seconds = (df.index.minute*60+df.index.second)-timestep 
    weight = [k/timestep if n == 0 else (seconds[n] - seconds[n - 1])/timestep 
       for n, k in enumerate(seconds)] 
    return np.sum(weight*df.values) 

df.resample('15min', closed='right').apply(func) 
+0

이 영리 더 나은 솔루션을 업데이트! 대단히 고마워,이게 내가 필요한거야! Resample() 대신 GroupBy()를 사용할 수 있습니까? 이유는 그룹화하려는 다른 열이 있는데, 단순화를 위해 원래의 질문에 포함시키지 않았습니다. 나는 테이블을 사용하는 것 같습니다 : df.groupby ([pd.TimeGrouper (freq = '15Min')]) 그러나 오른쪽과 함께 그룹을 닫는 방법은없는 것 같습니다. resample() 함수에 있습니다. –

+0

그래서 기본적으로 내 테이블에 다음과 같은 4 열이 : "| ZONE | PRICE1 | TIME PRICE2" 을 그리고 난 내가 한 각각의 가격 –

+0

에 대한 시간 가중 영역 당 평균 15 분 간격 당을 갖고 싶어 더 많은 데이터와 모든 것을 테스트하는 것이 더 빠릅니다. 파이썬의 속도에 익숙하지 않은 것 같습니다. 1.6 백만 행을 처리하기 위해 (각각 ~ 3 행의 530k 그룹에서) 약 10 분이 걸렸습니다. 나는 C# 프로그램에서 (코드가 훨씬 길어서 각 행을 수동으로 반복해야했기 때문에) 동일한 작업을 수행했으며 10 초도 채 걸리지 않았습니다. –