【问题标题】:Pandas Python: calculating financial week numberPandas Python:计算金融周数
【发布时间】:2020-10-22 22:07:27
【问题描述】:

我有五年的金融相关数据。财政年度从 7 月 1 日开始,到 6 月 30 日结束。我想计算每个财政年度的财政周。我想在数据框的日期列上应用一些操作,这样当我写df['date].dt.week 之类的东西时,它应该返回财务周数而不是日历周数。所以我使用以下代码来执行所需的输出:

df['date'] = df['date'].apply(pd.Period,freq='W')
df['date'].dt.week

但它没有产生预期的结果。谁能指导我哪里出错了?

【问题讨论】:

    标签: python python-3.x pandas datetime


    【解决方案1】:

    我认为你不能用pandas 做到这一点。但是,您可以使用我在下面创建的名为 business_week 的矢量化函数(当我使用它时,我还为 business day 创建了一个)。这些函数说明闰年。此功能从您过去的月份/日期的第一天开始计算,而不是一周中的特定日期。请注意,一年有 52 个整周,并且根据闰年的不同,还有 1 或 2 天,因此 6 月 30 日将显示为周53,6 月 29 日也将显示为闰年。如果您希望它是 52,您可以简单地将 53 替换为 52。您必须传递以下参数:

    1. 要以日期时间格式导出工作日的列
    2. 开始月份
    3. 开始日

    例如:df['week'] = business_week(df['date'], 7, 1) 和下面的最小可重现示例:

    df = pd.DataFrame({'date': 
    {0: pd.Timestamp('2019-01-01 00:00:00'),
    1: pd.Timestamp('2019-06-28 00:00:00'),
    2: pd.Timestamp('2019-06-29 00:00:00'),
    3: pd.Timestamp('2019-06-30 00:00:00'),
    4: pd.Timestamp('2019-07-01 00:00:00'),
    5: pd.Timestamp('2019-07-07 00:00:00'),
    6: pd.Timestamp('2019-07-08 00:00:00'),
    7: pd.Timestamp('2020-01-01 00:00:00'),
    8: pd.Timestamp('2020-06-28 00:00:00'),
    9: pd.Timestamp('2020-06-29 00:00:00'),
    10: pd.Timestamp('2020-06-30 00:00:00'),
    11: pd.Timestamp('2020-07-01 00:00:00'),
    12: pd.Timestamp('2020-07-07 00:00:00'),
    13: pd.Timestamp('2020-07-08 00:00:00')}})
    
    def business_week(d, start_month, start_day):
        from datetime import datetime, timedelta
        y_int = d.dt.year
        y_str = y_int.astype(str)
        start_md = (datetime(2020, start_month, start_day) - timedelta(days=1)).strftime('%m-%d')
        start_ymd = pd.to_datetime(y_str + '-' + start_md)
        s = d.dt.dayofyear - start_ymd.dt.dayofyear
        m1 = s.mask(s < 1, 365 - abs(s))
        m2 = m1.mask((y_int % 4 == 0) & (d > start_ymd), m1 - 1)
        return np.where(y_int % 4 != 0, (m2 + 6) / 7, (m2 + 7) / 7).astype(int)
    
    
    df['week'] = business_week(df['date'], 7, 1)
    df
    Out[1]: 
             date  week
    0  2019-01-01    27
    1  2019-06-28    52
    2  2019-06-29    52
    3  2019-06-30    53
    4  2019-07-01     1
    5  2019-07-07     1
    6  2019-07-08     2
    7  2020-01-01    27
    8  2020-06-28    52
    9  2020-06-29    53
    10 2020-06-30    53
    11 2020-07-01     1
    12 2020-07-07     1
    13 2020-07-08     2
    

    另外,如果你想要它,你可以使用类似的方法返回business_day

    def business_day(d, start_month, start_day):
        from datetime import datetime, timedelta
        y_int = d.dt.year
        y_str = y_int.astype(str)
        start_md = (datetime(2020, start_month, start_day) - timedelta(days=1)).strftime('%m-%d')
        start_ymd = pd.to_datetime(y_str + '-' + start_md)
        s = d.dt.dayofyear - start_ymd.dt.dayofyear
        m1 = s.mask(s < 1, 365 - abs(s))
        m2 = m1.mask((y_int % 4 == 0) & (d <= start_ymd), m1 + 1)
        return m2
    
    
    df['day'] = business_day(df['date'], 7, 1)
    df
    Out[1]: 
             date  day
    0  2019-01-01  185
    1  2019-06-28  363
    2  2019-06-29  364
    3  2019-06-30  365
    4  2019-07-01    1
    5  2019-07-07    7
    6  2019-07-08    8
    7  2020-01-01  185
    8  2020-06-28  364
    9  2020-06-29  365
    10 2020-06-30  366
    11 2020-07-01    1
    12 2020-07-07    7
    13 2020-07-08    8
    

    【讨论】:

      【解决方案2】:

      Series.dt.week id 已弃用。我还没有遇到过财政年度周。也许将周数设置为从某个日期开始。

      一年中的正常周数我会在将日期强制为日期时间后尝试以下操作

      df.date.apply(lambda x: pd.Period(x,freq='D').week)
      

      df['date'].dt.strftime("%W").astype(int)
      

      【讨论】:

      猜你喜欢
      • 2017-07-16
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      • 2018-05-05
      • 1970-01-01
      • 1970-01-01
      • 2021-02-05
      • 2011-01-16
      相关资源
      最近更新 更多