2015-07-03 11 views
7

मुझे डेटाटाइम इंडेक्स के साथ एक बड़ा डेटाफ्रेम मिला है और डेटा को बिल्कुल 10 समान आकार की अवधि में दोहराने की आवश्यकता है।डेटाटाइम इंडेक्स के साथ एक डीएफ को वास्तव में समान रूप से समान अवधि के लिए कैसे दोहराना है?

अभी तक, मैंने डेटा में दिनों की कुल संख्या निर्धारित करने के लिए पहली और आखिरी तिथियों को खोजने का प्रयास किया है, प्रत्येक अवधि के आकार को निर्धारित करने के लिए 10 तक विभाजित करें, फिर उस संख्या का उपयोग करके पुन: नमूना लें। उदाहरण के लिए:

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

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

यह resampling के बाद से periodsize एक पूर्णांक पूर्णांक है के बाद df में ठीक 10 अवधियों की गारंटी नहीं है। एक फ्लोट का उपयोग resampling में काम नहीं करता है। ऐसा लगता है कि या तो कुछ आसान है कि मैं यहां याद कर रहा हूं, या मैं समस्या को सभी गलत पर हमला कर रहा हूं।

उत्तर

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 

पैदावार से

     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 

मूल्यों 0 में देता है निर्दिष्ट कर सकते हैं -कॉलम समेकित पंक्तियों की संख्या इंगित करता है, क्योंकि मूल डेटाफ्रेम 1 के मानों से भरा था। 4 और 3 का पैटर्न लगभग उतना ही है जितना आप प्राप्त कर सकते हैं क्योंकि 33 पंक्तियों को समान रूप से 10 समूहों में समूहीकृत नहीं किया जा सकता है।


स्पष्टीकरण: इस सरल DataFrame पर विचार करें:

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') का प्रयोग समूहों की सही संख्या देता समूहों

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

df.resample('3D', how='sum') का उपयोग करते हुए की गलत संख्या देता है, लेकिन दूसरा समूह 2000-01-04 पर शुरू होता है जो ev नहीं है enly DataFrame विभाजित दो समान रूप से स्थान दिया गया समूहों में:

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

बेहतर करने के लिए, हम दिन की तुलना में एक बेहतर समय संकल्प पर काम करने की जरूरत है। चूंकि Timedelta के पास total_seconds विधि है, चलिए सेकंड में काम करते हैं।ऊपर के उदाहरण के लिए तो, इच्छित आवृत्ति स्ट्रिंग होगा

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

के बाद से वहाँ 5 दिनों में 216000 * 2 सेकंड हैं:

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

ठीक है, तो अब हम सभी की जरूरत है इस सामान्यीकरण करने के लिए एक रास्ता है । हम सूचकांक में न्यूनतम और अधिकतम तिथियां चाहते हैं:

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

हम एक अतिरिक्त दिन जोड़ते हैं क्योंकि इससे दिन में अंतर ठीक हो जाता है। में उपरोक्त उदाहरण, वहाँ 2000/01/05 और 2000/01/01 के लिए मुहर के बीच केवल 4 दिन,

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

लेकिन जैसा कि हम काम उदाहरण में देख सकते, DataFrame 5 पंक्तियां हैं कर रहे हैं 5 दिनों का प्रतिनिधित्व करता है। तो यह समझ में आता है कि हमें एक अतिरिक्त दिन जोड़ने की जरूरत है।

अब हम साथ प्रत्येक समान रूप से स्थान दिया गया समूह में सेकंड की सही संख्या की गणना कर सकते हैं:

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

यह काफी आसान लगता है। मैं भी अतिरिक्त स्पष्टीकरण की सराहना करता हूं। धन्यवाद! –

1

यहाँ एक तरह से यह सुनिश्चित करने के बराबर आकार के उप अवधि pd.Timedelta पर np.linspace() का उपयोग कर और फिर pd.cut का उपयोग कर विभिन्न डिब्बे में प्रत्येक ओ बीएस वर्गीकृत है।

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 

ऐसा करने का एक और संभावित छोटा तरीका है समय सारिणी के रूप में अपने नमूना freq निर्दिष्ट करना। लेकिन नीचे दिखाए गए समस्या यह है कि यह 10 के बजाय 11 उप-नमूने प्रदान करता है। मेरा मानना ​​है कि resampleleft-inclusive/right-exclusive (or left-exclusive/right-inclusive) उप-नमूना योजना लागू करता है ताकि '02-02-03 00' : 00: 00 'को एक अलग समूह के रूप में माना जाता है। अगर हम pd.cut का उपयोग यह करने के लिए ourself ऐसा करने के लिए, हम include_lowest=True इतना है कि यह हमें ठीक 10 उप नमूने नहीं बल्कि 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

यह दिलचस्प है, धन्यवाद! मुझे लगता है कि @HappyLeapSecond का जवाब मेरी ज़रूरतों के लिए थोड़ा आसान है, हालांकि। –

संबंधित मुद्दे