Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pandas Time Series Holiday Rule Offset

Tags:

python

pandas

Trying to define a set of rules using pandas.tseries.holidays class but can't figure out how to just create a rule based on another rule. I have the below rule but then want to just create another rule that offsets original rule by one business day:

Thanksgiving:

Holiday("Thanksgiving Day", month=11, day=1, offset=pd.DateOffset(weekday=TH(4))),

Black Friday:

Holiday("Thanksgiving Day", month=11, day=1, 
        offset=pd.DateOffset(weekday=TH(4))) + pd.DateOffset(1),

Similarly trying to create rule for Cyber Monday which would just be the Monday following Thanksgiving. Tried the below but this returns 11-2

Holiday("Thanksgiving Day", month=11, day=1,
        offset=pd.DateOffset(weekday=TH(4)), observance=next_monday)

But above won't work returning

TypeError: unsupported type for add operation

like image 826
horatio1701d Avatar asked May 27 '15 14:05

horatio1701d


3 Answers

I don't believe you can specify holidays relative other holidays. However, in your case, we can define holidays that match your requirement. Given that the Thanksgiving is the fourth Thursday, then BlackFriday is the fourth Friday, and CyberMonday is the fourth Saturday (observed on the following Monday). The latest date possible for Thanksgiving is Nov. 28, so that Saturday would be Nov. 30 and the 'holiday' would be observed on Dec. 2.

from pandas.tseries.holiday import Holiday, TH, FR, SA, next_monday

Holiday("Black Friday", month=11, day=1, offset=pd.DateOffset(weekday=FR(4)))
Holiday("CyberMonday", month=11, day=1, offset=pd.DateOffset(weekday=SA(4)), 
        observance=next_monday)
like image 169
Alexander Avatar answered Sep 20 '22 00:09

Alexander


Nowadays, it's not possible define both offset and observance parameters in the same holiday rule.

I found this issue with the Boxing holiday day in England. The Boxing Day is the next workday after Christmas day.

I coded the solution using the observance parameter pointing to the appropriate rule, in this case: after_nearest_workday

    Holiday('Christmas', month=12, day=25, observance=nearest_workday),
    Holiday('Boxing Day', month=12, day=25, observance=after_nearest_workday)

after_nearest_workday is a function. If you need another observance rule, you can create your own function like the following original Pandas observance functions:

def nearest_workday(dt):
    """
    If holiday falls on Saturday, use day before (Friday) instead;
    if holiday falls on Sunday, use day thereafter (Monday) instead.
    """
    if dt.weekday() == 5:
        return dt - timedelta(1)
    elif dt.weekday() == 6:
        return dt + timedelta(1)
    return dt

def after_nearest_workday(dt):
    """
    returns next workday after nearest workday
    needed for Boxing day or multiple holidays in a series
    """
    return next_workday(nearest_workday(dt))
like image 38
J. Mulet Avatar answered Sep 18 '22 00:09

J. Mulet


With the latest pandas 0.23.4, it's pretty easy to do this now.

import pandas as pd
from pandas.tseries.offsets import Day
from dateutil.relativedelta import TH

BlackFriday = Holiday("Black Friday", month=11, day=1, 
        offset=[pd.DateOffset(weekday=TH(4)), Day(1)])
like image 20
WillZ Avatar answered Sep 22 '22 00:09

WillZ