اذهب إلى المحتوى

السؤال

نشر (معدل)

لدي بيانات على شكل dataframe بحيث تحتوى على تواريخ، وكل تاريخ مربوط به حدث أو أكثر أو ليس به أحداث إطلاقا، التواريخ من المفترض أنها لشهر كامل، الا انني عندما أقوم بعمل groupby لجمع عدد الأحداث سوياً في كل تاريخ تابعه لها، يكون عدد التواريخ أقل من 30، وذلك لأن هناك بعض الأيام ليس بها أحداث فيتم إزالتها مباشرة كالتالي:

df.groupby(['simpleDate']).size()

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

لاحظ أن هناك تواريخ في المنتصف تم ازالتها لانها لا تحتوى على أحداث.

أريد طباعة تلك التواريخ أيضا بحيث يكون عدد الأحداث بها 0 ولا يتم تجاهلها، كيف يمكنني فعل هذا؟

تم التعديل في بواسطة Mohamed Elnemr

Recommended Posts

  • 0
نشر

يمكنك استخدام Series.reindex لضمان عدم تجاهل التواريخ التى عدد الأحداث بها 0 حيث أن groupby تقوم فقط بالاحتفاظ بالقيم التى عددها 1 أو أكثر ، أنظر الكود التالي:

import pandas as pd

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

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

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

وتكون النتيجة كالتالي:

2021-09-01     0
2021-09-02     2
2021-09-03    10
2021-09-04     0
2021-09-05     0
2021-09-06     5
...

لاحظ أن القيم التى = 0 لم يتم إلغاؤها.

  • 0
نشر

الحل الأسرع هو استخدام .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

 

 

  • 0
نشر

يمكن استخدام حل أسرع وهو الدالة asfreq حيث أنها لاتتطلب إعادة إنشاء index على عكس reindex:

dates = pd.Index([pd.Timestamp('2022-07-01'), 
                  pd.Timestamp('2022-07-04'), 
                  pd.Timestamp('2022-07-06')])

s = pd.Series([1, 2, 3], dates)

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

كما أن reindex تفشل في حال وجود قيم مكررة duplicate values.

كما يمكن استخدام timestamps بتطبيق الدالة DatetimeIndex:

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
yields

            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

وحل آخر باستخدام resample التي تحل مشكلة duplicate values:

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

 

  • 0
نشر

من خلال resample يمكننا القيام بماتطلبه:

import pandas as pd
df = pd.DataFrame({
    'date': pd.to_datetime(
        ['2016-11-15','2016-11-16','2016-11-18']),
    'values':['a','b','c']})
df
"""
    date 	values
0 	2016-11-15 	a
1 	2016-11-16 	b
2 	2016-11-18 	c
"""
#resample استخدام 
df.set_index(df.date, inplace=True)
df.resample('D').sum().fillna(0)
"""
        values
date 	
2016-11-15 	a
2016-11-16 	b
2016-11-17 	0
2016-11-18 	c
"""

ولتسهيل العملية يمكنك استخدام التابع التالي. حيث نمرر له ال dataframe والعمود الخاص بالتاريخ والطريقة التي نريد فرز العمود على أساسها والقيمة المراد وضعها للتواريخ المفقودة وهي تعتمد على دالة ال  reindex التي سبق ذكرها في الإجابات السابقة:

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

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...