2013-03-14 3 views
9

불규칙한 (반) 기간으로 DataFrame을 리샘플링하는 '요리 책'방법이 있습니까?사용자 지정 기간을 사용하여 리샘플링

나는 일일 간격으로 데이터 세트를 가지고 있으며 때로는 (과학 서적에서) dekad라는 이름으로 리샘플링하기를 원합니다. 나는 그것을 위해 적절한 영어 용어가 있다고 생각하지 않는다. 그러나 기본적으로 3 ~ 10 일간의 파트에서 한 달을 자르고, 세 번째 파트는 8 일에서 11 일 사이의 나머지 부분이다.

필자는 두 가지 해결책, 즉이 경우에 대한 구체적인 해결책과 불규칙한 기간에 대한 더 일반적인 해결책을 생각해 냈습니다. 그러나 둘 다 정말 좋아 보이지 않으므로 다른 사람들이 이런 유형의 상황을 어떻게 처리하는지 잘 알고 있습니다.

는 일부 샘플 데이터를 만들기 시작하자 :

import pandas as pd 

begin = pd.datetime(2013,1,1) 
end = pd.datetime(2013,2,20) 

dtrange = pd.date_range(begin, end) 

p1 = np.random.rand(len(dtrange)) + 5 
p2 = np.random.rand(len(dtrange)) + 10 

df = pd.DataFrame({'p1': p1, 'p2': p2}, index=dtrange) 

내가 수동으로 공격 태도를 보여준 후 개별 달 (YYYYMM)에 의해 그룹화되어 해낸 가장 먼저하는 일. 마찬가지로 :

def to_dec1(data, func): 

    # create the indexes, start of the ~10day period 
    idx1 = pd.datetime(data.index[0].year, data.index[0].month, 1) 
    idx2 = idx1 + datetime.timedelta(days=10) 
    idx3 = idx2 + datetime.timedelta(days=10) 

    # slice the period and perform function 
    oneday = datetime.timedelta(days=1) 
    fir = func(data.ix[:idx2 - oneday].values, axis=0) 
    sec = func(data.ix[idx2:idx3 - oneday].values, axis=0) 
    thi = func(data.ix[idx3:].values, axis=0) 

    return pd.DataFrame([fir,sec,thi], index=[idx1,idx2,idx3], columns=data.columns) 

dfmean = df.groupby(lambda x: x.strftime('%Y%m'), group_keys=False).apply(to_dec1, np.mean) 
결과

: 필요한 경우

print dfmean 

        p1   p2 
2013-01-01 5.436778 10.409845 
2013-01-11 5.534509 10.482231 
2013-01-21 5.449058 10.454777 
2013-02-01 5.685700 10.422697 
2013-02-11 5.578137 10.532180 
2013-02-21  NaN  NaN 

당신은 항상 대가로 'dekads'의 전체 달을 얻을 주, 그 문제가되지 않습니다 쉽게 제거 할 수 있습니다.

다른 해결책은 DataFrame을 잘라서 각 세그먼트에서 기능을 수행하는 일정 범위의 날짜를 제공하여 작동합니다. 당신이 원하는 기간의 측면에서 더 유연합니다. 약간의 시간을 자신을 '구축'을 저장하는 날짜 범위와 이전 결과의 인덱스를 사용하여 메신저

def to_dec2(data, dts, func): 

    chucks = [] 
    for n,start in enumerate(dts[:-1]): 

     end = dts[n+1] - datetime.timedelta(days=1) 
     chucks.append(func(data.ix[start:end].values, axis=0)) 

    return pd.DataFrame(chucks, index=dts[:-1], columns=data.columns) 

dfmean2 = to_dec2(df, dfmean.index, np.mean) 

참고.

이러한 사례를 처리하는 가장 좋은 방법은 무엇입니까? 판다 스에서 좀 더 빌드 - 인 방법이 있습니까?

d = df.index.day - np.clip((df.index.day-1) // 10, 0, 2)*10 - 1 
date = df.index.values - np.array(d, dtype="timedelta64[D]") 
df.groupby(date).mean() 

:

import pandas as pd 
import numpy as np 

begin = pd.datetime(2013,1,1) 
end = pd.datetime(2013,2,20) 

dtrange = pd.date_range(begin, end) 

p1 = np.random.rand(len(dtrange)) + 5 
p2 = np.random.rand(len(dtrange)) + 10 

df = pd.DataFrame({'p1': p1, 'p2': p2}, index=dtrange) 

이 dekad의 날짜를 계산 :

샘플 데이터를 생성 : 당신이 NumPy와 1.7을 사용하는 경우

+0

위에, 당신은 (당신이 그들을 원하는 목적지 루틴 쉽게 이러한 그룹을 채울 수), [날짜, NUM_OF_DAYS]의 다중 색인에 GROUPBY 수 정상처럼 GROUPBY. 모든 이벤트에서 TimeGrouper를 사용하여이 작업을 수행하는 더 효율적인 방법이 있습니다 (단, 생각해야합니다). – Jeff

답변

7

, 당신은 계산을 할 datetime64 & timedelta64 배열을 사용할 수 있습니다 출력은 다음과 같습니다.

    p1   p2 
2013-01-01 5.413795 10.445640 
2013-01-11 5.516063 10.491339 
2013-01-21 5.539676 10.528745 
2013-02-01 5.783467 10.478001 
2013-02-11 5.358787 10.579149 
변수의 계산에 HYRY 데이터 및 용액 최대 사용 51,515,
+0

감사합니다. 매력과 같습니다. –

2

, 또한 할 수있다 (상관없이 NumPy와 버전) 이상 0.11 데브 팬더에서 다음 :

In [18]: from datetime import timedelta 

In [23]: pd.Series([ timedelta(int(i)) for i in d ]) 
Out[23]: 
0    00:00:00 
1  1 days, 00:00:00 
2  2 days, 00:00:00 
3  3 days, 00:00:00 
4  4 days, 00:00:00 
5  5 days, 00:00:00 
6  6 days, 00:00:00 
7  7 days, 00:00:00 
8  8 days, 00:00:00 
9  9 days, 00:00:00 
10   00:00:00 

47 6 days, 00:00:00 
48 7 days, 00:00:00 
49 8 days, 00:00:00 
50 9 days, 00:00:00 
Length: 51, dtype: timedelta64[ns] 

날짜에 similary 구성되고 더 일반적인 경우에 대한

date = pd.Series(df.index) - pd.Series([ timedelta(int(i)) for i in d ]) 
df.groupby(date.values).mean() 
+0

그것은 10.1에서 나던, dev 버전을 실행하지 않습니다.미래에 대해 잘 알고 있습니다. 감사합니다. –

관련 문제