पांडा डेटाफ़्रेम में अनुपलब्ध तिथियाँ जोड़ें


127

मेरे डेटा में किसी दिनांक पर कई ईवेंट हो सकते हैं या किसी दिनांक पर NO ईवेंट हो सकते हैं। मैं इन घटनाओं को लेता हूं, तारीख तक एक गिनती प्राप्त करता हूं और उन्हें प्लॉट करता हूं। हालाँकि, जब मैं उन्हें प्लॉट करता हूं, तो मेरी दो श्रृंखला हमेशा मेल नहीं खाती हैं।

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

उपर्युक्त कोड में idx 30 तिथियों की श्रेणी बन जाता है। 09-01-2013 से 09-30-2013 हालांकि एस में केवल 25 या 26 दिन हो सकते हैं क्योंकि किसी भी तारीख को कोई घटना नहीं हुई है। जब मैं प्लॉट करने की कोशिश करता हूं तो मुझे एक जोर मिलता है क्योंकि साइज मैच नहीं करते हैं:

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

जवाबों:


254

आप उपयोग कर सकते हैं 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
...

23
reindexएक अद्भुत समारोह है। यह मौजूदा डेटा को लेबल के एक नए सेट से मिलान करने के लिए मौजूदा डेटा को पुन: व्यवस्थित कर सकता है, (2) नई पंक्तियाँ डालें जहाँ पहले से मौजूद कोई लेबल नहीं है, (3) लापता लेबल के लिए डेटा भरें, (फॉरवर्ड / बैकवर्ड फिलिंग सहित) (4) पंक्तियों का चयन करें लेबल द्वारा!
अनटुब

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

2
एक समस्या (या बग) है, जो रेनडेक्स के साथ है: यह 1/1/1970 से पहले की तारीखों के साथ काम नहीं करता है, इसलिए इस मामले में df.resample () पूरी तरह से काम करता है।
सर्गेई गुलबीन

1
आप इसके बजाय idx को प्रारंभ और समाप्ति तिथियों को मैन्युअल रूप से छोड़ने के लिए उपयोग कर सकते हैं:idx = pd.date_range(df.index.min(), df.index.max())
Reveille

आपको खोज को बचाने के लिए दस्तावेज़ के लिंक को यहाँ छोड़ना
हरम ते

40

एक तेज़ वर्कअराउंड का उपयोग करना है .asfreq() । इसके भीतर कॉल करने के लिए नए इंडेक्स के निर्माण की आवश्यकता नहीं होती है .reindex()

# "broken" (staggered) dates
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

1
मैं वास्तव में इस पद्धति को पसंद करता हूं; आप कॉल करने से बचें date_rangeक्योंकि यह आरंभ और अंत के रूप में पहले और अंतिम सूचकांक का उपयोग करता है (जो कि आप लगभग हमेशा चाहते हैं)।
माइकल

बहुत साफ और पेशेवर विधि। इंटरपोलेट का उपयोग करने के साथ-साथ बाद में भी काम करता है।
msarafzadeh

26

एक समस्या यह है कि 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

(इसके द्वारा इसका मतलब है कि इंडेक्स में डुप्लिकेट है, ऐसा नहीं है कि यह स्वयं एक डुबकी है)

इसके बजाय, हम .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 यदि आवश्यक हो तो रिक्त भरने के लिए कॉलम श्रृंखला पर उपयोग किया जा सकता है।


यदि दिनांक कॉलम में है Blanksया क्या करना है इस पर कोई विचार NULLS? df.loc[all_days]उस मामले में काम नहीं करेगा।
फुरकान हाशिम

1
किसी भी गुम लेबल के साथ .loc या [] पासिंग सूची-पसंद भविष्य में KeyError को बढ़ाएगा, आप एक विकल्प के रूप में .reindex () का उपयोग कर सकते हैं। यहाँ प्रलेखन देखें: pandas.pydata.org/pandas-docs/stable/…
दिमित्री

19

एक वैकल्पिक दृष्टिकोण है resample, जो लापता तिथियों के अलावा डुप्लिकेट तिथियों को संभाल सकता है। उदाहरण के लिए:

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

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

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

             val
date           
2013-09-02     2
2013-09-03    10
2013-09-03    20    <- duplicate date added to OP's data
2013-09-06     5
2013-09-07     1

और यहाँ परिणाम हैं:

             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

मैंने अनुपस्थित तारीखों को NaNs के रूप में छोड़ दिया ताकि यह स्पष्ट हो सके कि यह कैसे काम करता है, लेकिन आप fillna(0)NaN को शून्य के साथ बदलने के लिए जोड़ सकते हैं जैसा कि ओपी द्वारा अनुरोध किया गया है या वैकल्पिक रूप interpolate()से पड़ोसी पंक्तियों के आधार पर गैर-शून्य मानों को भरने के लिए कुछ का उपयोग करना चाहते हैं।


6

यहाँ एक अच्छा विधि एक 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.