将工作日添加到带有日期的 pandas 数据框中并跳过假期 python

dav*_*p13 7 dataframe pandas python-holidays

我有一个包含日期的数据框,如下表所示。第一个块是它应该的样子,第二个块是我在添加 BDays 时得到的。这是完成后的样子的示例。我想使用第一列并向日期添加 5 个工作日,但如果 5 个生日与假期重叠(例如 21 年 2 月 15 日),那么我需要再添加一天。使用 添加 5Bday 相当简单 pandas.tseries.offsets import BDay,但我在使用数据框时不能跳过假期。

我尝试过使用pandas.tseries.holiday import USFederalHolidayCalendar、workdays 和 workalendar 模块,但无法弄清楚。任何人都知道我能做什么。

正确的例子

日期 退出日期+5
2021/02/09 2021/02/17
2021/02/10 2021/02/18

错误的例子

日期 退出日期+5
2021/02/09 2021/02/16
2021/02/10 2021/02/17

以下是我尝试过的一些代码示例:

import pandas as pd
from workdays import workday
...
df['DATE'] = workday(df['EXIT DATE +5'], days=5, holidays=holidays)
Run Code Online (Sandbox Code Playgroud)

下一个例子:

import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
bday_us = pd.offsets.CustomBusinessDay(calendar=USFederalHolidayCalendar())
dt = df['DATE']
df['EXIT DATE +5'] = dt + bday_us
Run Code Online (Sandbox Code Playgroud)

===========================================

最终代码:

下面是我最终确定的代码。由于纽约证券交易所实际交易的日期,我必须手动定义假期。比如布什总统安息的那天。

import datetime as dt
import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import BDay

from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, nearest_workday, \
    USMartinLutherKingJr, USPresidentsDay, GoodFriday, USMemorialDay, \
    USLaborDay, USThanksgivingDay

class USTradingCalendar(AbstractHolidayCalendar):
    rules = [
        Holiday('NewYearsDay', month=1, day=1, observance=nearest_workday),
        USMartinLutherKingJr,
        USPresidentsDay,
        GoodFriday,
        USMemorialDay,
        Holiday('USIndependenceDay', month=7, day=4, observance=nearest_workday),
        Holiday('BushDay', year=2018, month=12, day=5),
        USLaborDay,
        USThanksgivingDay,
        Holiday('Christmas', month=12, day=25, observance=nearest_workday)
    ]

offset = 5

df = pd.DataFrame(['2019-10-11', '2019-10-14', '2017-04-13', '2018-11-28', '2021-07-02'], columns=['DATE'])
df['DATE'] = pd.to_datetime(df['DATE'])

def offset_date(start, offset):
  return start + pd.offsets.CustomBusinessDay(n=offset, calendar=USTradingCalendar())

df['END'] = df.apply(lambda x: offset_date(x['DATE'], offset), axis=1)
print(df)
Run Code Online (Sandbox Code Playgroud)

xic*_*aio 8

输入数据

df = pd.DataFrame(['2021-02-09', '2021-02-10', '2021-06-28', '2021-06-29', '2021-07-02'], columns=['DATE'])
df['DATE'] = pd.to_datetime(df['DATE'])
Run Code Online (Sandbox Code Playgroud)

使用 apply 的建议解决方案

from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import BDay

def offset_date(start, offset):
  return start + pd.offsets.CustomBusinessDay(n=offset, calendar=USFederalHolidayCalendar())

offset = 5
df['END'] = df.apply(lambda x: offset_date(x['DATE'], offset), axis=1)

    DATE        END
    2021-02-09  2021-02-17
    2021-02-10  2021-02-18
    2021-06-28  2021-07-06
    2021-06-29  2021-07-07
    2021-07-02  2021-07-12
Run Code Online (Sandbox Code Playgroud)

PS:如果您想使用特定日历(例如 NYSE)而不是默认日历,我建议您按照此答案中有关创建自定义日历的USFederalHolidayCalendar说明进行操作。

我不推荐的替代解决方案

目前,据我所知,pandas 不支持矢量化方法来解决您的问题。但如果您想遵循与您提到的类似的方法,那么您应该这样做。

首先,您必须定义一个任意遥远的end日期,其中包括您可能需要的所有时段,并使用它来创建假期列表。

holidays = USFederalHolidayCalendar().holidays(start='2021-02-09', end='2030-02-09')
Run Code Online (Sandbox Code Playgroud)

然后,您通过参数而不是将该holidays列表传递给 CustomBusinessDay以生成所需的偏移量。holidayscalendar

offset = 5
bday_us = pd.offsets.CustomBusinessDay(n=offset, holidays=holidays)
df['END'] = df['DATE'] + bday_us
Run Code Online (Sandbox Code Playgroud)

然而,这种类型的方法并不是真正的矢量化解决方案,尽管看起来很像。请参阅以下SO 答案以获取进一步说明。在幕后,这种方法可能会进行效率不高的转换。这就是为什么它会产生以下警告。

性能警告:非向量化 DateOffset 应用于 Series 或 DatetimeIndex


归档时间:

查看次数:

8589 次

最近记录:

4 年,4 月 前