2015-07-03 17 views
7

Veri günlüğü endeksli büyük bir veri karegim var ve veriyi 10 eşit büyüklükteki periyodlara yeniden örneklememiz gerekiyor.Bir df datetime endeksiyle tam olarak n eşit büyüklükteki dönemlere nasıl yeniden örneklenir?

Şimdiye kadar, verilerdeki toplam gün sayısını belirlemek için ilk ve son tarihleri ​​bulmayı denedim, her bir dönemin boyutunu belirlemek için 10'a bölerek o gün sayısını kullanarak yeniden örnekleme yaptım. örneğin:

first = df.reset_index().timesubmit.min() 
last = df.reset_index().timesubmit.max() 
periodsize = str((last-first).days/10) + 'D' 

df.resample(periodsize,how='sum') 

Bu periodsize aşağı yuvarlanır int olduğundan yeniden örnekleme sonra df içinde tam olarak 10 dönemleri garanti etmez. Bir yüzdürme kullanarak yeniden örnekleme çalışmıyor. Ya burada eksik olan basit bir şey var gibi görünüyor ya da problemi tamamen yanlışlara saldırıyorum.

cevap

1
import numpy as np 
import pandas as pd 

n = 10 
nrows = 33 
index = pd.date_range('2000-1-1', periods=nrows, freq='D') 
df = pd.DataFrame(np.ones(nrows), index=index) 
print(df) 
#    0 
# 2000-01-01 1 
# 2000-01-02 1 
# ... 
# 2000-02-01 1 
# 2000-02-02 1 

first = df.index.min() 
last = df.index.max() + pd.Timedelta('1D') 
secs = int((last-first).total_seconds()//n) 
periodsize = '{:d}S'.format(secs) 

result = df.resample(periodsize, how='sum') 
print('\n{}'.format(result)) 
assert len(result) == n 

verim ziyade bize

     0 
2000-01-01 00:00:00 4 
2000-01-04 07:12:00 3 
2000-01-07 14:24:00 3 
2000-01-10 21:36:00 4 
2000-01-14 04:48:00 3 
2000-01-17 12:00:00 3 
2000-01-20 19:12:00 4 
2000-01-24 02:24:00 3 
2000-01-27 09:36:00 3 
2000-01-30 16:48:00 3 

değerleri tam olarak 10 alt örneklerini verir, böylece biz include_lowest=True belirtebilirsiniz -column, orijinal DataFrame 1 değerleri ile doldurulduğundan, toplanan satırların sayısını gösterir. 4 satır ve 3'ün kalıbı, yaklaşık 33 satır, 10 gruba eşit olarak gruplandırılamadığından, alabileceğiniz kadardır.


Açıklama: Bu basit DataFrame düşünün:

n = 2 
nrows = 5 
index = pd.date_range('2000-1-1', periods=nrows, freq='D') 
df = pd.DataFrame(np.ones(nrows), index=index) 
#    0 
# 2000-01-01 1 
# 2000-01-02 1 
# 2000-01-03 1 
# 2000-01-04 1 
# 2000-01-05 1 

df.resample('2D', how='sum') kullanma grupların doğru sayıda df.resample('3D', how='sum') kullanma gruplar

In [366]: df.resample('2D', how='sum') 
Out[366]: 
      0 
2000-01-01 2 
2000-01-03 2 
2000-01-05 1 

sayısı yanlış verir verir ama ikinci grup, ev olmayan 2000-01-04'dan başlar. enly iki eşit aralıklı gruba DataFrame bölmek:

In [367]: df.resample('3D', how='sum') 
Out[367]: 
      0 
2000-01-01 3 
2000-01-04 2 

daha iyi yapmak için, gün içinde daha ince zaman çözünürlükte çalışmak gerekir. Timedelta s bir total_seconds yöntemine sahip olduğundan, saniye olarak çalışalım.

In [373]: (pd.Timedelta(days=5)/pd.Timedelta('1S'))/2 
Out[373]: 216000.0 

Tamam, şimdi tek ihtiyacımız bu genelleme için bir yoldur: Yukarıdaki örneğin Böylece istenen frekans dize 5 günde 216.000 * 2 saniye olmadığından

In [374]: df.resample('216000S', how='sum') 
Out[374]: 
        0 
2000-01-01 00:00:00 3 
2000-01-03 12:00:00 2 

olurdu . bunun doğru çıkıp günlerde fark yaratıyor çünkü

first = df.index.min() 
last = df.index.max() + pd.Timedelta('1D') 

Biz fazladan bir gün ekleyin: Biz endeksinde minimum ve maksimum tarihleri ​​isteyeceksiniz. yılında Yukarıdaki örnek, 2000/01/05 ve 2000-01-01 için zaman damgaları arasındaki tek 4 gün,

In [377]: (pd.Timestamp('2000-01-05')-pd.Timestamp('2000-01-01')).days 
Out[378]: 4 

Ama işlenmiş örnekte de görebileceğiniz gibi, DataFrame 5 satır var var 5 gününü temsil eder. Bu yüzden fazladan bir gün eklememiz gerektiği mantıklı.

Şimdi her eşit aralıklı gruptaki saniye sayısını doğru hesaplayabiliriz:

ilginç
secs = int((last-first).total_seconds()//n) 
+0

Bu yeterince basit görünüyor. Ekstra açıklamayı da takdir ediyorum. Teşekkürler! –

1

üzerinde np.linspace() kullanarak ve pd.cut kullanarak her bir engeli farklı kutulara sınıflandırarak eşit boyutlu alt dönemleri sağlamanın bir yolu.

import pandas as pd 
import numpy as np 

# generate artificial data 
np.random.seed(0) 
df = pd.DataFrame(np.random.randn(100, 2), columns=['A', 'B'], index=pd.date_range('2015-01-01 00:00:00', periods=100, freq='8H')) 

Out[87]: 
          A  B 
2015-01-01 00:00:00 1.7641 0.4002 
2015-01-01 08:00:00 0.9787 2.2409 
2015-01-01 16:00:00 1.8676 -0.9773 
2015-01-02 00:00:00 0.9501 -0.1514 
2015-01-02 08:00:00 -0.1032 0.4106 
2015-01-02 16:00:00 0.1440 1.4543 
2015-01-03 00:00:00 0.7610 0.1217 
2015-01-03 08:00:00 0.4439 0.3337 
2015-01-03 16:00:00 1.4941 -0.2052 
2015-01-04 00:00:00 0.3131 -0.8541 
2015-01-04 08:00:00 -2.5530 0.6536 
2015-01-04 16:00:00 0.8644 -0.7422 
2015-01-05 00:00:00 2.2698 -1.4544 
2015-01-05 08:00:00 0.0458 -0.1872 
2015-01-05 16:00:00 1.5328 1.4694 
...      ...  ... 
2015-01-29 08:00:00 0.9209 0.3187 
2015-01-29 16:00:00 0.8568 -0.6510 
2015-01-30 00:00:00 -1.0342 0.6816 
2015-01-30 08:00:00 -0.8034 -0.6895 
2015-01-30 16:00:00 -0.4555 0.0175 
2015-01-31 00:00:00 -0.3540 -1.3750 
2015-01-31 08:00:00 -0.6436 -2.2234 
2015-01-31 16:00:00 0.6252 -1.6021 
2015-02-01 00:00:00 -1.1044 0.0522 
2015-02-01 08:00:00 -0.7396 1.5430 
2015-02-01 16:00:00 -1.2929 0.2671 
2015-02-02 00:00:00 -0.0393 -1.1681 
2015-02-02 08:00:00 0.5233 -0.1715 
2015-02-02 16:00:00 0.7718 0.8235 
2015-02-03 00:00:00 2.1632 1.3365 

[100 rows x 2 columns] 


# cutoff points, 10 equal-size group requires 11 points 
# measured by timedelta 1 hour 
time_delta_in_hours = (df.index - df.index[0])/pd.Timedelta('1h') 
n = 10 
ts_cutoff = np.linspace(0, time_delta_in_hours[-1], n+1) 
# labels, time index 
time_index = df.index[0] + np.array([pd.Timedelta(str(time_delta)+'h') for time_delta in ts_cutoff]) 

# create a categorical reference variables 
df['start_time_index'] = pd.cut(time_delta_in_hours, bins=10, labels=time_index[:-1]) 
# for clarity, reassign labels using end-period index 
df['end_time_index'] = pd.cut(time_delta_in_hours, bins=10, labels=time_index[1:]) 

Out[89]: 
          A  B start_time_index  end_time_index 
2015-01-01 00:00:00 1.7641 0.4002 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-01 08:00:00 0.9787 2.2409 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-01 16:00:00 1.8676 -0.9773 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-02 00:00:00 0.9501 -0.1514 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-02 08:00:00 -0.1032 0.4106 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-02 16:00:00 0.1440 1.4543 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-03 00:00:00 0.7610 0.1217 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-03 08:00:00 0.4439 0.3337 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-03 16:00:00 1.4941 -0.2052 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-04 00:00:00 0.3131 -0.8541 2015-01-01 00:00:00 2015-01-04 07:12:00 
2015-01-04 08:00:00 -2.5530 0.6536 2015-01-04 07:12:00 2015-01-07 14:24:00 
2015-01-04 16:00:00 0.8644 -0.7422 2015-01-04 07:12:00 2015-01-07 14:24:00 
2015-01-05 00:00:00 2.2698 -1.4544 2015-01-04 07:12:00 2015-01-07 14:24:00 
2015-01-05 08:00:00 0.0458 -0.1872 2015-01-04 07:12:00 2015-01-07 14:24:00 
2015-01-05 16:00:00 1.5328 1.4694 2015-01-04 07:12:00 2015-01-07 14:24:00 
...      ...  ...     ...     ... 
2015-01-29 08:00:00 0.9209 0.3187 2015-01-27 09:36:00 2015-01-30 16:48:00 
2015-01-29 16:00:00 0.8568 -0.6510 2015-01-27 09:36:00 2015-01-30 16:48:00 
2015-01-30 00:00:00 -1.0342 0.6816 2015-01-27 09:36:00 2015-01-30 16:48:00 
2015-01-30 08:00:00 -0.8034 -0.6895 2015-01-27 09:36:00 2015-01-30 16:48:00 
2015-01-30 16:00:00 -0.4555 0.0175 2015-01-27 09:36:00 2015-01-30 16:48:00 
2015-01-31 00:00:00 -0.3540 -1.3750 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-01-31 08:00:00 -0.6436 -2.2234 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-01-31 16:00:00 0.6252 -1.6021 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-02-01 00:00:00 -1.1044 0.0522 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-02-01 08:00:00 -0.7396 1.5430 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-02-01 16:00:00 -1.2929 0.2671 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-02-02 00:00:00 -0.0393 -1.1681 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-02-02 08:00:00 0.5233 -0.1715 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-02-02 16:00:00 0.7718 0.8235 2015-01-30 16:48:00 2015-02-03 00:00:00 
2015-02-03 00:00:00 2.1632 1.3365 2015-01-30 16:48:00 2015-02-03 00:00:00 

[100 rows x 4 columns] 

df.groupby('start_time_index').agg('sum') 

Out[90]: 
          A  B 
start_time_index     
2015-01-01 00:00:00 8.6133 2.7734 
2015-01-04 07:12:00 1.9220 -0.8069 
2015-01-07 14:24:00 -8.1334 0.2318 
2015-01-10 21:36:00 -2.7572 -4.2862 
2015-01-14 04:48:00 1.1957 7.2285 
2015-01-17 12:00:00 3.2485 6.6841 
2015-01-20 19:12:00 -0.8903 2.2802 
2015-01-24 02:24:00 -2.1025 1.3800 
2015-01-27 09:36:00 -1.1017 1.3108 
2015-01-30 16:48:00 -0.0902 -2.5178 

bunu yapmak için diğer potansiyel kısa bir yol süresi delta olarak örnekleme frek belirtmektir. Fakat problem, aşağıda gösterildiği gibi, 10 yerine 11 alt-örnek sunmasıdır. Bunun sebebi, resample'un left-inclusive/right-exclusive (or left-exclusive/right-inclusive) alt-örnekleme şemasını uygulayabilmesidir. Bu nedenle, en son 2015-02-03 00 : 00: 00 'ayrı bir grup olarak kabul edilir. biz kendimiz yapmak zorunda pd.cut kullanırsanız o 0 içinde 11.

n = 10 
time_delta_str = str((df.index[-1] - df.index[0])/(pd.Timedelta('1s') * n)) + 's' 
df.resample(pd.Timedelta(time_delta_str), how='sum') 

Out[114]: 
          A  B 
2015-01-01 00:00:00 8.6133 2.7734 
2015-01-04 07:12:00 1.9220 -0.8069 
2015-01-07 14:24:00 -8.1334 0.2318 
2015-01-10 21:36:00 -2.7572 -4.2862 
2015-01-14 04:48:00 1.1957 7.2285 
2015-01-17 12:00:00 3.2485 6.6841 
2015-01-20 19:12:00 -0.8903 2.2802 
2015-01-24 02:24:00 -2.1025 1.3800 
2015-01-27 09:36:00 -1.1017 1.3108 
2015-01-30 16:48:00 -2.2534 -3.8543 
2015-02-03 00:00:00 2.1632 1.3365 
+0

, teşekkürler! Bence @HappyLeapSecond 'un cevabı, ihtiyaçlarim için biraz daha basit. –

İlgili konular