2013-03-14 20 views
9

Bir DataFrame'i (yarı) düzensiz dönemlerle yeniden örneklemek için bir 'yemek kitabı' yolu var mı?Özel dönemlerle yeniden örnekleme

Günlük aralıklarla veri kümem var ve bazen (bilimsel literatürde) dekad'ın isminin ne olduğunu yeniden örneklendirmesini istiyorum. Bunun için uygun bir ingilizce terim olduğunu düşünmüyorum, ancak üçüncüsünün on üç gün içinde bir ayını kesiyor ve üçüncüsü 8 ile 11 gün arasında kalan bir şey.

Kendim için iki çözüm buldum, bu dava için belirli bir tane ve herhangi bir düzensiz dönem için daha genel bir tane. Ama her ikisi de çok iyi, bu yüzden başkalarının bu tür durumlarla nasıl başa çıktıklarını anlamak istiyorum.

bazı örnek verileri oluşturmaya başlayalım:

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) 

i elle dilimleme sonra bireysel ay (YYYYAA) göre gruplama ve ile gelen ilk şey. Gibi:

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) 
sonuçlanır

: Gerekirse

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 

her zaman karşılığında 'dekads' tam bir ay olsun Not, onun değil bir sorun ve kolay çıkarmak için.

Diğer çözüm, DataFrame'i kestiğiniz ve her segmentte bir işlev gerçekleştirebileceğiniz bir tarih aralığı sağlayarak çalışır. İstediğiniz dönemler bakımından daha esnek.

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) 

Bir önceki zamanın indeksini, bir süre 'oluşturmak' için zaman aralığı olarak kullanıyorum.

Bu vakaları ele almanın en iyi yolu ne olurdu? Pandalarda belki de biraz daha inşa yöntemi var mı?

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 tarihini hesaplamak:

örnek verileri oluşturmak: Eğer numpy 1.7 kullanıyorsanız

+0

yukarıda, daha sonra, (senin onları istediğiniz yerde rutin kolayca bu grupları doldurmak olabilir), [tarih, NUM_OF_DAYS] bir çok endeksi GroupBy olabilir normal gibi GroupBy. Her durumda TimeGrouper ile bunu yapmak için daha verimli bir yol var (ama bunu düşünmek zorundayım) – Jeff

cevap

7

, sen hesaplama yapmak datetime64 & timedelta64 diziler kullanabilirsiniz Çıktı:

    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 
değişkenin hesaplanması için HYRY verilerini ve çözüm yukarı kullanma
+0

Teşekkürler, bir çekicilik gibi çalışır. –

2

, biz de yapabiliriz (bakılmaksızın numpy versiyonu) sonra 0.11-dev veya pandalar aşağıdaki:

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] 

tarih için similary inşa edilmiştir daha genel durum için

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

10.1'de değil, dev sürümlerini çalıştırmıyorum.Gelecek için iyi bilmek, teşekkürler! –

İlgili konular