【问题标题】:Get business days between start and end date using pandas使用 pandas 获取开始日期和结束日期之间的工作日
【发布时间】:2012-10-22 20:56:13
【问题描述】:

我正在使用 pandas,我想知道使用 pandas 获取开始日期和结束日期之间的工作日的最简单方法是什么?

有很多关于在 Python 中执行此操作的帖子(example),但我有兴趣直接使用 pandas,因为我认为 pandas 可能很容易处理这个问题。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您也可以为此使用date_range

    In [3]: pd.date_range('2011-01-05', '2011-01-09', freq=BDay())
    
    Out[3]: DatetimeIndex(['2011-01-05', '2011-01-06', '2011-01-07'], dtype='datetime64[ns]', freq='B', tz=None)
    

    编辑

    甚至更简单

    In [7]: pd.bdate_range('2011-01-05', '2011-01-09')
    
    Out[7]: DatetimeIndex(['2011-01-05', '2011-01-06', '2011-01-07'], dtype='datetime64[ns]', freq='B', tz=None)
    

    请注意,开始日期和结束日期都包含在内。 来源:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.bdate_range.html

    【讨论】:

      【解决方案2】:

      从 v0.14 开始,您可以使用假日日历。

      从 pandas.tseries.holiday 导入 USFederalHolidayCalendar 从 pandas.tseries.offsets 导入 CustomBusinessDay us_bd = CustomBusinessDay(日历=USFederalHolidayCalendar()) 打印 pd.DatetimeIndex(start='2010-01-01',end='2010-01-15', freq=us_bd)

      返回:

      DatetimeIndex(['2010-01-04', '2010-01-05', '2010-01-06', '2010-01-07', '2010-01-08', '2010-01-11', '2010-01-12', '2010-01-13', '2010-01-14', '2010-01-15'], dtype='datetime64[ns]',频率='C')

      【讨论】:

      • 如果你想要日期范围之间的天数,你可以得到这个pd.DatetimeIndex(start='2010-01-01',end='2010-01-15',freq=us_bd).shape[0]
      • DatetimeIndex 中的 "start" 和 "end" 参数已被弃用,但您可以使用 len(pd.date_range(start='2010-01-01',end='2010-01-15',freq=us_bd)) pandas.pydata.org/docs/reference/api/pandas.date_range.html
      【解决方案3】:

      在使用 bdate_range 或 BDay() 时要小心 - 名称可能会误导您认为它是一个工作日范围,而实际上它只是日历日,去掉了周末(即不放假)考虑)。

      【讨论】:

      • 尽管这并不是对 Q 的完整回答......这是一个非常重要的评论,属于已接受的答案 - 名称 BDay 具有误导性。圣诞节是工作日吗?如果不是在周末,则根据 BDay。
      【解决方案4】:

      使用BDay() 获取范围内的工作日。

      from pandas.tseries.offsets import *
      
      In [185]: s
      Out[185]: 
      2011-01-01   -0.011629
      2011-01-02   -0.089666
      2011-01-03   -1.314430
      2011-01-04   -1.867307
      2011-01-05    0.779609
      2011-01-06    0.588950
      2011-01-07   -2.505803
      2011-01-08    0.800262
      2011-01-09    0.376406
      2011-01-10   -0.469988
      Freq: D
      
      In [186]: s.asfreq(BDay())
      Out[186]: 
      2011-01-03   -1.314430
      2011-01-04   -1.867307
      2011-01-05    0.779609
      2011-01-06    0.588950
      2011-01-07   -2.505803
      2011-01-10   -0.469988
      Freq: B
      

      切片:

      In [187]: x=datetime(2011, 1, 5)
      
      In [188]: y=datetime(2011, 1, 9)
      
      In [189]: s.ix[x:y]
      Out[189]: 
      2011-01-05    0.779609
      2011-01-06    0.588950
      2011-01-07   -2.505803
      2011-01-08    0.800262
      2011-01-09    0.376406
      Freq: D
      
      In [190]: s.ix[x:y].asfreq(BDay())
      Out[190]: 
      2011-01-05    0.779609
      2011-01-06    0.588950
      2011-01-07   -2.505803
      Freq: B
      

      count()

      In [191]: s.ix[x:y].asfreq(BDay()).count()
      Out[191]: 3
      

      【讨论】:

      • 当我的数据具有小时粒度时,是否可以使用相同的技术?所以我想抽出工作日的所有时间。我知道如何在这之后只抽出一天的工作时间
      • 我发现你可以使用这个 .asfreq(freq='BH')
      • 什么是s?请举一个完整的例子。
      • @root 我认为这个答案,作为公认的答案,应该包括@Lars 评论。这个名字具有误导性,人们可能会发现自己陷入困境。 BDay 这个名字具有误导性。圣诞节是工作日吗?如果不是周末,则根据 BDay。在大多数业务逻辑应用程序中,BDay 确实代表“工作日”而不是“工作日”。
      【解决方案5】:

      this answerxone 之上,我们可以编写一个短函数来返回trading days of US exchange

      from xone import calendar
      
      def business_dates(start, end):
          us_cal = calendar.USTradingCalendar()
          kw = dict(start=start, end=end)
          return pd.bdate_range(**kw).drop(us_cal.holidays(**kw))
      
      In [1]: business_dates(start='2018-12-20', end='2018-12-31')
      Out[1]: DatetimeIndex(['2018-12-20', '2018-12-21', '2018-12-24', '2018-12-26',
                             '2018-12-27', '2018-12-28', '2018-12-31'],
                            dtype='datetime64[ns]', freq=None)
      

      2019 年 3 月编辑:

      DatetimeIndex 替换为bdate_rangepandas 0.24.0 update

      • 不推荐通过传递范围参数 start、end 和 period 创建 TimedeltaIndex、DatetimeIndex 或 PeriodIndex,取而代之的是 timedelta_range()、date_range() 或 period_range()

      【讨论】:

      • 这是个坏蛋。
      • 我可能会用 len 函数包装 pd.bdate_range 以获取天数,但这更美观。
      【解决方案6】:

      我们可以使用pd.bdate_range

      例子:

      In [1]: pd.bdate_range("2020-01-01", "2020-01-06")
      Out[1]: DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-06'], dtype='datetime64[ns]', freq='B')
      

      【讨论】:

        【解决方案7】:

        如果您也在周六工作或有不寻常的工作周,您还希望排除您所在国家/地区的公共假期。

        import pandas as pd  
        from datetime import datetime
        
        weekmask = 'Sun Mon Tue Wed Thu'
        exclude = [pd.datetime(2020, 5, 1),
                   pd.datetime(2020, 5, 2),
                   pd.datetime(2020, 5, 3)]
        
        pd.bdate_range('2020/4/30','2020/5/26',
                       freq='C',
                       weekmask = weekmask,
                       holidays=exclude )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多