如何在熊猫历时计算中排除周末和节假日

时间:2018-09-12 09:19:28

标签: python pandas dataframe timestamp

这是我的数据集,为确保您知道数据格式,在此之前

df['Datetime_Start'] =  df['Start'].dt.strftime('%D')
df['Datetime_Finish'] =  df['Finish'].dt.strftime('%D')

选定的有趣列

No  Datetime_Start    Datetime_Finish
1   13/08/18          31/08/18
1   14/08/18          25/08/18

我期望的输出

No  Datetime_Start    Datetime_Finish    Duration
1   13/08/18          31/08/18           12 Days
1   14/08/18          24/08/18           6 Days

这是因为2018年8月18日,19日,25日和26日是星期六和星期日,而17日和22日是公众假期(在印度尼西亚)

这是印度尼西亚https://publicholidays.co.id/2018-dates/公众假期的链接,但是如果您仅包括2018年8月17日至22日来回答问题,那是可以的,但是请使其可配置,以便我可以手动添加

1 个答案:

答案 0 :(得分:3)

这可能是一种方式。基本思想是,我将范围扩展到(pd.date_range之间的所有日期,然后使用不同的条件来筛选不应计数的日期:

import pandas as pd

import requests

from icalendar import Calendar

ics_url = 'https://www.calendarlabs.com/ical-calendar/ics/50/Indonesia_Holidays.ics'

df = {'Datetime_Start': pd.to_datetime(['2018-08-13', '2018-08-14']),
      'Datetime_End': pd.to_datetime(['2018-08-31', '2018-08-25'])}
df = pd.DataFrame(df)

df['days_in_range'] = df.apply(
    lambda x: pd.date_range(x['Datetime_Start'], x['Datetime_End']),
    axis=1)

# remove weekends
df['days_in_range'] = df['days_in_range'].apply(lambda x: x[x.dayofweek <= 4])

# remove holidays
calendar = Calendar.from_ical(requests.get(ics_url).content)
holidays = [pd.to_datetime(x['DTSTART'].dt).date()
            for x in calendar.walk('VEVENT')]

df['days_in_range'] = df['days_in_range'].apply(
    lambda x: [y for y in x if y.date() not in holidays])

df['Duration'] = df['days_in_range'].apply(lambda x: len(x) - 1)

肯定有机会加快这一步,还有一些隐藏的假设:

  • 范围始终包含至少一天的可计算结果。极端情况不予处理。
  • 假定ical文件不重复使用。