2014-11-21 11 views
11

का योग मान लें मैं डेटा फ्रेम नीचे हैपांडा रोलिंग पिछले पांच मिनट

Date, A 
2014-11-21 11:00:00, 1 
2014-11-21 11:03:00, 4 
2014-11-21 11:04:00, 1 
2014-11-21 11:05:00, 2 
2014-11-21 11:07:00, 4 
2014-11-21 11:08:00, 1 
2014-11-21 11:12:00, 1 
2014-11-21 11:13:00, 2 

पहला कॉलम datetime वस्तु है और दूसरे स्तंभ एक पूर्णांक है। मैं चाहता हूं कि प्रत्येक पंक्ति के लिए पिछले पांच मिनट के लिए कॉलम 'ए' के ​​योग की गणना करना है।

पंक्ति 2014-11-21 11:12:00, 1 के लिए एक उदाहरण के रूप में, स्तंभ 'ए' का योग होगा 2 (1 + 1) और पंक्ति 2014-11-21 11:05:00, 2 के लिए स्तंभ 'ए' का योग 7 (2 + 1 + 4) होगा। महत्वपूर्ण बात यह है कि समय खिड़की (5 मिनट) के लिए पिछले पंक्तियों की संख्या प्रत्येक पंक्ति के लिए समान नहीं है (क्योंकि समय श्रृंखला अनियमित है) है।

मैं कैसे 'ए' पांडा में rolling_sum पद्धति का उपयोग करके स्तंभ के लिए पिछले पांच मिनट का योग मिल सकता है? अग्रिम में धन्यवाद।

उत्तर

13

सामान्य में, अगर दिनांकों पूर्णतः ऐच्छिक हैं, मुझे लगता है कि आप पंक्तियों या use df.apply, पर एक अजगर for-loop उपयोग करने के लिए मजबूर किया जाएगा (जो हुड के नीचे, यह भी एक अजगर पाश का उपयोग करता है।)

हालांकि, अपनी तिथियाँ समान फ्रीक्वेंसी साझा करते हैं, मामले से ऊपर है, तो वहाँ एक चाल है जो df.apply का उपयोग करने से बहुत जल्दी होना चाहिए: आम आवृत्ति के अनुसार timeseries विस्तार - इस मामले में, 1 मिनट - Nans में भरने शून्य के साथ, और फिर rolling_sum पर कॉल करें:

In [279]: pd.rolling_sum(df.set_index(['Date']).asfreq('1T').fillna(0), window=5, min_periods=1).reindex(df['Date']) 
Out[279]: 
         A 
Date     
2014-11-21 11:00:00 1 
2014-11-21 11:03:00 5 
2014-11-21 11:04:00 6 
2014-11-21 11:05:00 7 
2014-11-21 11:07:00 11 
2014-11-21 11:08:00 8 
2014-11-21 11:12:00 2 
2014-11-21 11:13:00 3 

बेशक, यदि आप एक छोटे पर्याप्त विवरण के स्तर को स्वीकार करने को तैयार हैं किसी भी समय श्रृंखला के लिए समान फ्रीक्वेंसी है, लेकिन df.asfreq(...) के लिए आवश्यक आकार इस चाल अव्यावहारिक बना सकते हैं।


df.apply का उपयोग करके अधिक सामान्य दृष्टिकोण का एक उदाहरण यहां दिया गया है। ध्यान दें कि बुला searchsorteddf['Date'] क्रमबद्ध क्रम में किया जा रहा है पर निर्भर करता है।

import numpy as np 
import pandas as pd 
df = pd.read_csv('data', parse_dates=[0], sep=',\s*') 
start_dates = df['Date'] - pd.Timedelta(minutes=5) 
df['start_index'] = df['Date'].values.searchsorted(start_dates, side='right') 
df['end_index'] = np.arange(len(df)) 

def sum_window(row): 
    return df['A'].iloc[row['start_index']:row['end_index']+1].sum() 
df['rolling_sum'] = df.apply(sum_window, axis=1) 

print(df[['Date', 'A', 'rolling_sum']]) 

पैदावार

    Date A rolling_sum 
0 2014-11-21 11:00:00 1   1 
1 2014-11-21 11:03:00 4   5 
2 2014-11-21 11:04:00 1   6 
3 2014-11-21 11:05:00 2   7 
4 2014-11-21 11:07:00 4   11 
5 2014-11-21 11:08:00 1   8 
6 2014-11-21 11:12:00 1   2 
7 2014-11-21 11:13:00 2   3 

यहाँ एक बेंचमार्क df.apply बुला बनाम df.asfreq चाल की तुलना है:

import numpy as np 
import pandas as pd 
df = pd.read_csv('data', parse_dates=[0], sep=',\s*') 

def big_df(df): 
    df = df.copy() 
    for i in range(7): 
     dates = df['Date'] + pd.Timedelta(df.iloc[-1]['Date']-df.iloc[0]['Date']) + pd.Timedelta('1 minute') 
     df2 = pd.DataFrame({'Date': dates, 'A': df['A']}) 
     df = pd.concat([df, df2]) 
    df = df.reset_index(drop=True) 
    return df 

def using_apply(): 
    start_dates = df['Date'] - pd.Timedelta(minutes=5) 
    df['start_index'] = df['Date'].values.searchsorted(start_dates, side='right') 
    df['end_index'] = np.arange(len(df)) 

    def sum_window(row): 
     return df['A'].iloc[row['start_index']:row['end_index']+1].sum() 

    df['rolling_sum'] = df.apply(sum_window, axis=1) 
    return df[['Date', 'rolling_sum']] 

def using_asfreq(): 
    result = (pd.rolling_sum(
     df.set_index(['Date']).asfreq('1T').fillna(0), 
     window=5, min_periods=1).reindex(df['Date'])) 
    return result 

In [364]: df = big_df(df) 

In [367]: %timeit using_asfreq() 
1000 loops, best of 3: 1.21 ms per loop 

In [368]: %timeit using_apply() 
1 loops, best of 3: 208 ms per loop 
+0

त्वरित उत्तर के लिए बहुत बहुत धन्यवाद। मैं df.asfreq उपयोग कर सकते हैं नहीं (...) मेरे डाटासेट में सबसे छोटी के विवरण का स्तर के बाद से विधि सेकंड है और मैं पंक्तियों के लाखों लोगों की है। लेकिन df.apply विधि चाल करता है। –

+0

सामान्य दृष्टिकोण काम करता है, अगर इसे लंबे कोड में उपयोग किया जा रहा है, तो केवल एक चीज को ध्यान में रखा जाना चाहिए: फ़ंक्शन 'sum_window' स्पष्ट रूप से इनपुट 'df' का उपयोग नहीं करता है इसलिए सावधान रहना आवश्यक है। – nilesh

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