পান্ডাস ডেটা ফ্রেমে হারিয়ে যাওয়া তারিখগুলি যুক্ত করুন


127

আমার ডেটাতে একটি নির্দিষ্ট তারিখে একাধিক ইভেন্ট বা কোনও তারিখে কোনও ইভেন্ট থাকতে পারে। আমি এই ইভেন্টগুলি গ্রহণ করি, তারিখ অনুসারে একটি গণনা পাই এবং সেগুলি প্লট করি। যাইহোক, আমি যখন তাদের পরিকল্পনা করি, আমার দুটি সিরিজ সবসময় মেলে না।

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

উপরের কোডে আইডিএক্স 30 তারিখের একটি ব্যাপ্তিতে পরিণত হয়। 09-01-2013 থেকে 09-30-2013 তবে এস এর কেবল 25 বা 26 দিন থাকতে পারে কারণ একটি নির্দিষ্ট তারিখের জন্য কোনও ইভেন্ট ঘটেনি। আমি যখন প্লট করার চেষ্টা করি তখন আকারগুলি মেলে না এমন হিসাবে আমি একটি AssertionError পাই:

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

এটি মোকাবেলার সঠিক উপায় কী? আমি কি আইডিএক্স থেকে মান না দিয়ে তারিখগুলি মুছে ফেলতে চাইছি বা (যা পরিবর্তে করবো) সিরিজের সাথে একটি মিস করার তারিখটি 0 গণনা সহ যুক্ত করা হবে rather পরিবর্তে 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একটি আশ্চর্যজনক ফাংশন। এটি (1) নতুন লেবেলের সাথে সেট করার সাথে বিদ্যমান ডেটাটিকে পুনঃক্রম করতে পারে, (২) নতুন সারি সন্নিবেশ করানো হবে যেখানে কোনও লেবেল আগে নেই, (3) নিখোঁজ লেবেলের জন্য ডেটা পূরণ করুন (সামনের / পিছিয়ে থাকা সহ) (4) সারি নির্বাচন করুন লেবেল দ্বারা!
unutbu

@ ইউন্টবু আমার এই প্রশ্নের একটি উত্তর দেয়, ধন্যবাদ! তবে আপনি ভাবছিলেন যে আপনি কীভাবে ঘটনার তারিখগুলির সাথে একটি তালিকা গতিশীলভাবে তৈরি করতে জানেন?
নিক ডডি

2
যদিও রিইনডেক্সের সাথে একটি সমস্যা (বা বাগ) রয়েছে: এটি 1/1/1970 এর আগে তারিখগুলি নিয়ে কাজ করে না, তাই এই ক্ষেত্রে df.resample () পুরোপুরি কাজ করে।
সের্গেই গুলবিন

1
: আপনি শুরু লিখে লাফালাফি এবং ম্যানুয়ালি তারিখ শেষ করতে idx জন্য এর পরিবর্তে এটি ব্যবহার করতে পারেidx = pd.date_range(df.index.min(), df.index.max())
নিদ্রাভঙ্গের জন্য সঙ্কেত

আপনাকে অনুসন্ধানটি বাঁচাতে এখানে ডকুমেন্টেশনের লিঙ্কটি ফেলে দেওয়া হচ্ছে: pandas.pydata.org/pandas-docs/stable/references/api/…
Harm te

40

একটি দ্রুত workaround ব্যবহার করা হয় .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করতে এড়াচ্ছেন কারণ এটি প্রথম এবং শেষ সূচকটি শুরু এবং শেষ হিসাবে স্পষ্টভাবে ব্যবহার করে (যা আপনি প্রায় সর্বদা চাইতেন)।
মাইকেল হেজে

খুব পরিষ্কার এবং পেশাদার পদ্ধতি। ইন্টারপোলেট পরে পাশাপাশি ব্যবহার করে ভাল কাজ করে।
মিসরাফজাদেঃ

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 বা []] কোনও নিখোঁত লেবেলের সাথে তালিকা-পছন্দগুলি পাস করা ভবিষ্যতে কী-এরর উত্থাপন করবে, আপনি বিকল্প হিসাবে .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

নিখোঁজ তারিখগুলি একটি ডেটাফ্রেমে পূরণ করার জন্য আপনার পছন্দ অনুসারে fill_value, days_backপূরণ করার জন্য এবং ক্রম ( date_order) দিয়ে ডেটাফ্রেমকে বাছাই করার জন্য একটি দুর্দান্ত পদ্ধতি:

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.