2013-10-11 8 views
48

मेरे डेटा में किसी निश्चित तिथि पर एक से अधिक घटनाओं को डेट पर कोई ईवेंट नहीं है सकते हैं। मैं इन घटनाओं को लेता हूं, तिथि से गिनती करता हूं और उन्हें साजिश देता हूं। हालांकि, जब मैं उन्हें साजिश करता हूं, तो मेरी दो श्रृंखला हमेशा मेल नहीं खाती हैं।जोड़ें लापता दिनांकों dataframe

idx = pd.date_range(df['simpleDate'].min(), df['simpleDate'].max()) 
s = df.groupby(['simpleDate']).size() 

ऊपर कोड IDX में 30 दिनांकों कहना की एक श्रृंखला बन जाता है। क्योंकि कोई घटनाओं किसी निश्चित तिथि के लिए हुआ 2013/09/01 2013/09/30 के लिए हालांकि एस केवल 25 या 26 दिन हो सकता है। मैं तो एक AssertionError मिल के रूप में आकार न मैच जब मैं साजिश करने का प्रयास करें:

fig, ax = plt.subplots()  
ax.bar(idx.to_pydatetime(), s, color='green') 

इस से निपटने के लिए उचित तरीका क्या है? मैं IDX या (जो मैं नहीं बल्कि करना चाहते हैं) की ओर से कोई मूल्यों के साथ दिनांक निकालना चाहते श्रृंखला के लिए 0 मूल्यों के साथ 0. की गणना के साथ लापता तिथि जोड़ते है मैं नहीं बल्कि 30 दिनों की एक पूरी ग्राफ होगा है । यदि यह दृष्टिकोण सही है, तो कैसे शुरू किया जाए इस पर कोई सुझाव? क्या मुझे कुछ प्रकार की गतिशील reindex फ़ंक्शन चाहिए?

यहाँ एस (df.groupby(['simpleDate']).size()) का एक टुकड़ा है, 04 के लिए कोई प्रविष्टि नहीं नोटिस और 05.

09-02-2013  2 
09-03-2013 10 
09-06-2013  5 
09-07-2013  1 

उत्तर

115

आप Series.reindex इस्तेमाल कर सकते हैं:

import pandas as pd 

idx = pd.date_range('09-01-2013', '09-30-2013') 

s = pd.Series({'09-02-2013': 2, 
       '09-03-2013': 10, 
       '09-06-2013': 5, 
       '09-07-2013': 1}) 
s.index = pd.DatetimeIndex(s.index) 

s = s.reindex(idx, fill_value=0) 
print(s) 

पैदावार

2013-09-01  0 
2013-09-02  2 
2013-09-03 10 
2013-09-04  0 
2013-09-05  0 
2013-09-06  5 
2013-09-07  1 
2013-09-08  0 
... 
+2

वाह धन्यवाद! मैं पूरी तरह से समझ नहीं पाया कि रीइंडेक्स कितनी अच्छी तरह से काम करता है। – KHibma

+12

'रीइन्डेक्स' एक अद्भुत कार्य है। यह (1) लेबल के नए सेट से मेल खाने के लिए मौजूदा डेटा को पुन: व्यवस्थित कर सकता है, (2) नई पंक्तियां डालें जहां पहले कोई लेबल मौजूद नहीं था, (3) गायब लेबल के लिए डेटा भरें, (आगे/पीछे भरने सहित) (4) पंक्तियों का चयन करें लेबल द्वारा! – unutbu

+0

@unutbu यह एक प्रश्न का हिस्सा है जो मैंने भी किया था, धन्यवाद! लेकिन यह सोच रहा था कि क्या आपको पता था कि घटनाओं के साथ तारीखों की सूची कैसे गतिशील रूप से बनाई जाए? –

2

लापता तिथियों को भरने के लिए यहां एक अच्छी विधि है एक dataframe, fill_value, days_back की अपनी पसंद के साथ भरें, और आदेश (date_order) है जिसके द्वारा dataframe सॉर्ट करने के लिए सुलझाने के लिए:

def fill_in_missing_dates(df, date_col_name = 'date',date_order = 'asc', fill_value = 0, days_back = 30): 

    df.set_index(date_col_name,drop=True,inplace=True) 
    df.index = pd.DatetimeIndex(df.index) 
    d = datetime.now().date() 
    d2 = d - timedelta(days = days_back) 
    idx = pd.date_range(d2, d, freq = "D") 
    df = df.reindex(idx,fill_value=fill_value) 
    df[date_col_name] = pd.DatetimeIndex(df.index) 

    return df 
11

एक मुद्दा अगर वहाँ डुप्लिकेट मानों हैं कि reindex असफल हो जायेगी है। हम टाइमस्टैंप डेटा है, जो हम तारीख से अनुक्रमित करना चाहते हैं के साथ काम कर रहे हैं कहते हैं:

df = pd.DataFrame({ 
    'timestamps': pd.to_datetime(
     ['2016-11-15 1:00','2016-11-16 2:00','2016-11-16 3:00','2016-11-18 4:00']), 
    'values':['a','b','c','d']}) 
df.index = pd.DatetimeIndex(df['timestamps']).floor('D') 
df 

पैदावार

  timestamps    values 
2016-11-15 "2016-11-15 01:00:00" a 
2016-11-16 "2016-11-16 02:00:00" b 
2016-11-16 "2016-11-16 03:00:00" c 
2016-11-18 "2016-11-18 04:00:00" d 

डुप्लिकेट 2016-11-16 तारीख के कारण, एक प्रयास पुन: अनुक्रमणिका के लिए:

all_days = pd.date_range(df.index.min(), df.index.max(), freq='D') 
df.reindex(all_days) 

के साथ विफल रहता है:

... 
ValueError: cannot reindex from a duplicate axis 

(इस से इसका मतलब है कि सूचकांक डुप्लिकेट है, नहीं है कि यह अपने आप में एक dup है)

इसके बजाय, हम .loc उपयोग कर सकते हैं रेंज में सभी तिथियों के लिए प्रविष्टियां देखने के लिए:

df.loc[all_days] 

पैदावार

  timestamps    values 
2016-11-15 "2016-11-15 01:00:00" a 
2016-11-16 "2016-11-16 02:00:00" b 
2016-11-16 "2016-11-16 03:00:00" c 
2016-11-17 NaN     NaN 
2016-11-18 "2016-11-18 04:00:00" d 

fillna यदि आवश्यक हो तो रिक्त स्थान भरने के लिए कॉलम श्रृंखला पर उपयोग किया जा सकता है।

6

asfreq() का उपयोग करने के लिए एक त्वरित कार्यवाही है। एक नए सूचकांक की इस रचना की आवश्यकता नहीं है उपयोगकर्ता द्वारा reindex() भीतर कॉल करने के लिए। *

dates = pd.Index([pd.Timestamp('2012-05-01'), 
        pd.Timestamp('2012-05-04'), 
        pd.Timestamp('2012-05-06')]) 
s = pd.Series([1, 2, 3], dates) 

print(s.asfreq('D')) 
2012-05-01 1.0 
2012-05-02 NaN 
2012-05-03 NaN 
2012-05-04 2.0 
2012-05-05 NaN 
2012-05-06 3.0 
Freq: D, dtype: float64 

* कम से कम नहीं। हुड के नीचे बहुत अच्छी तरह से बुलाया जा सकता है।

2

कई मामलों में, resample(see documentation here) एक सामान्य समाधान प्रदान करता है जो लापता और डुप्लिकेट तिथियों दोनों को संभाल सकता है। उदाहरण के लिए:

df.resample('D').mean() 

resample एक आस्थगित आपरेशन की तरह groupby तो आप एक और ऑपरेशन के साथ पालन करने की आवश्यकता है। आदि इस मामले mean अच्छी तरह से काम करता है, लेकिन आप यह भी max, sum की तरह वहाँ कई मानक पांडा विधि का उपयोग कर सकते हैं,

यहाँ में मूल डेटा है, लेकिन '2013-09-03' के लिए एक अतिरिक्त प्रवेश के साथ:

   val 
date    
2013-09-02 2.0 
2013-09-03 15.0 <- mean of original values for 2013-09-03 
2013-09-04 NaN <- NaN b/c date not present in orig 
2013-09-05 NaN <- NaN b/c date not present in orig 
2013-09-06 5.0 
2013-09-07 1.0 

ध्यान दें कि यह तुम्हारे जाने के बाद fillna या interpolate तरह के तरीकों का उपयोग कर सकते के रूप में वांछित लापता मूल्यों को भरने के लिए:

  val 
date   
2013-09-02 2 
2013-09-03 10 
2013-09-03 20 
2013-09-06 5 
2013-09-07 1 

और यहाँ के परिणाम हैं।