简体   繁体   中英

Pandas Time Series Holiday Rule Offset

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

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))

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)

For anyone else who encounters this. Got this help after submitting issue with Pandas which solved my issue. https://github.com/pydata/pandas/issues/10217#issuecomment-106040041

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)])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM