सामान्य में, अगर दिनांकों पूर्णतः ऐच्छिक हैं, मुझे लगता है कि आप पंक्तियों या 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
का उपयोग करके अधिक सामान्य दृष्टिकोण का एक उदाहरण यहां दिया गया है। ध्यान दें कि बुला searchsorted
df['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
त्वरित उत्तर के लिए बहुत बहुत धन्यवाद। मैं df.asfreq उपयोग कर सकते हैं नहीं (...) मेरे डाटासेट में सबसे छोटी के विवरण का स्तर के बाद से विधि सेकंड है और मैं पंक्तियों के लाखों लोगों की है। लेकिन df.apply विधि चाल करता है। –
सामान्य दृष्टिकोण काम करता है, अगर इसे लंबे कोड में उपयोग किया जा रहा है, तो केवल एक चीज को ध्यान में रखा जाना चाहिए: फ़ंक्शन 'sum_window' स्पष्ट रूप से इनपुट 'df' का उपयोग नहीं करता है इसलिए सावधान रहना आवश्यक है। – nilesh