【问题标题】:Making the 53th and 1th week into the same week starting on Sunday从星期日开始将第 53 周和第 1 周设为同一周
【发布时间】:2020-05-03 10:45:18
【问题描述】:

您好,我有以下数据:
索引、星期几、星期编号、Fecha

360      Friday       52 2019-12-27
361    Saturday       52 2019-12-28
362      Sunday       53 2019-12-29
363      Monday       53 2019-12-30
364     Tuesday       53 2019-12-31
365   Wednesday        1 2020-01-01
366    Thursday        1 2020-01-02
367      Friday        1 2020-01-03
368    Saturday        1 2020-01-04
369      Sunday        2 2020-01-05
370      Monday        2 2020-01-06

我想要:
- 包含 1 月 1 日的那一周是第 1 周
- 星期天开始
- 将第 1 周作为 7 天的整周,这意味着 12 月 29 日、30 日和 31 日也将获得第 1 周。
- 当我在这个数据集中有很多年的时间时,也可以让它工作。

在这个特定的年份,这意味着将所有 53 都更改为 1,但我认为其他年份这可能行不通。所以为了得到一个一般规则,我意识到如果 1 月 1 日是星期天,我不需要改变任何东西,所以我想首先检查每年的情况,如果 1 月 1 日不是星期天将前一个星期日和那个星期天之间的所有周数更改为 1。我想到的另一个选择是找出前一个星期日的第几周没有,然后将那一年的所有周数更改为与前一个星期日相同的数字,为 1。 对于这两种情况,我都需要在 df 中执行一个条件以仅过滤掉某些行,但是当我只想显示该 df 的一列时,我该怎么做?意思是如果我会这样做:

totals[(totals['Fecha'].dt.month==1) & (totals['Fecha'].dt.day==1) & (totals['Fecha'].dt.year==i)]

然后这将显示所有列的总数,而我想要这些条件并且只看到“工作日”列。

那么我该怎么做呢,而且,这对我来说听起来超级复杂。有没有我忽略的更简单/更有效的方法?

谢谢!

【问题讨论】:

标签: python pandas conditional-statements week-number


【解决方案1】:

所以这就是我最终想出的。这种性能表现如何?

totals['Fecha']=pd.to_datetime(totals['Fecha'], format='%d/%m/%Y') #change type to datetime
totals['Day of week']=totals['Fecha'].dt.weekday_name   #create day of week 'Sunday, Monday, etc'
totals['Week no']=totals['Fecha'].dt.strftime('%U').astype(int)+1 #create week no's with Sunday as first day of week

for i in set(totals['Fecha'].dt.year):
    if i!=2019: #because for the first year we don't have a previous end of year
        first_day_of_year=str(i)+'-01-01' 
        # if there are any rows where the day of the week of the first day of the year equals 'Sunday'
        if any(totals['Day of week'].where(totals['Fecha']==first_day_of_year)!='Sunday'):

        # then for the year before, change all the last week no's to one
            last_week=max(totals['Week no'].where(totals['Fecha'].dt.year==i-1))
            totals.loc[(totals['Week no']==last_week)&(totals['Fecha'].dt.year==i-1), 'Week no']=1

print(totals[['Day of week', 'Week no', 'Fecha']])

【讨论】:

    【解决方案2】:

    您可以使用mod 运算符。这将为您提供除以给定数字后的余数。因此,52 % 52 = 00 % 52 = 0。 Mod 仅在您从 0 开始计数时才真正起作用,因此您必须先减一,见下文:

    my_week = 53
    my_bounded_week = ((my_week - 1) % 52) + 1
    # First minus one to make the series start at 0.
    # Then add one after the mod to make the series start at 1
    
    print(my_bounded_week)
    # prints 1
    

    【讨论】:

    • 谢谢。这不等于将所有 53 替换为 1 吗?我不确定这是否可行,因为如果有一年 2 月有 29 天并且 1 月 1 日是星期六,这意味着 1 月 2 日是星期日和第 2 周,那么那一年将有 54 周不,所以 53 需要保持原样,只有 54 更改为 1。令人困惑!
    • 在这种情况下,您将不得不使用 maximum number of weeks - 1 的 mod。因此,一旦您计算完周数,就可以在最后一周的模型中倒退一年
    • 这也行不通,因为如果 1 月 1 日是星期日,您可能希望将 12 月的所有日期保留为一年中的最后一周。
    【解决方案3】:

    使用此 StackOverflow 答案中所述的 datetime 包:How can I find week numbers with weeks starting on Sunday in Python?

    【讨论】:

    • 我一直在使用这个包,这就是我获得当前“无周”列的方式,但正如您所见,它与我需要的有点不同。如果你知道一个函数可以将那一周的所有天数变为 1(甚至是 12 月的天数),我很想听听这个。谢谢!
    【解决方案4】:

    看来您需要自己的自定义业务日历,我们可以使用一个小函数来创建一个。

    假设您从每个日历年的第一个日历日开始创建日历,那么这将起作用。

    需要注意的是,我已经很多年没有写这个了,我会留给你的:)

    用法

    df = business_cal('01-01-2019','01-01-2020')
    
    print(df.head(5))
    
            date  weeks  dayofmonth  dayofweek daynameofweek
    0 2018-12-30      1          30          6        Sunday
    1 2018-12-31      1          31          0        Monday
    2 2019-01-01      1           1          1       Tuesday
    3 2019-01-02      1           2          2     Wednesday
    4 2019-01-03      1           3          3      Thursday
    

    功能。

    def business_cal(start,end):
        """
        Function that returns a calendar year given a start and end date.
        Constrains - week must start on Sunday if 01/01/2020 is not Sunday,
        we take the last Sunday of the previous year.
        """
        start_date = pd.to_datetime(start)
        
        if start_date.weekday() != 6:
            start_date = start_date - pd.DateOffset(days=(start_date.weekday() + 1))
        else:
            start_date
    
    
        dates = pd.date_range(start_date,end,freq='7D')
        
        df = pd.DataFrame(dates,columns=['date'])
        # grab week numbers.
        df['weeks'] = df.index + 1 
        df1 = df.set_index('date').resample('D').ffill().reset_index()
        
        df1['dayofmonth'] = df1['date'].dt.day
        df1['dayofweek'] = df1['date'].dt.dayofweek
        df1['daynameofweek'] = df1['date'].dt.day_name()
        return df1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-25
      • 2016-10-07
      • 1970-01-01
      • 2021-08-21
      • 2012-11-27
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      相关资源
      最近更新 更多