Python 从周日开始将第53周和第1周改为同一周

Python 从周日开始将第53周和第1周改为同一周,python,pandas,conditional-statements,week-number,Python,Pandas,Conditional Statements,Week Number,嗨,我有以下数据: 索引,星期几,星期号,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

嗨,我有以下数据:
索引,星期几,星期号,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周
-从周日开始工作周
-将第一周定为7天的完整一周,即12月29日、30日和31日也将定为第一周。
-当我在这个数据集中有很多年的时间时,也要让它起作用。

在这一年里,这意味着将所有的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)]
然后,这将显示总计中的所有列,而我需要和这些条件,并且只看到“周日”列。

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


谢谢大家!

您可以使用
mod
操作符。这将给出除以给定数字后的余数。因此,
52%52=0
0%52=0
。Mod仅在从0开始计数时才起作用,因此必须先减去1,请参见以下内容:

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

使用此StackOverflow中描述的
datetime
包回答:

似乎您需要自己的自定义业务日历,我们可以使用一个小功能创建一个

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

需要注意的是,我已经多年没有写过这篇文章了,我将把它留给你:)

用法
功能。
这就是我最后想到的。这种性能如何

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

这回答了你的问题吗?我一直在使用这个软件包,这就是为什么我得到了当前的“不周”专栏,但正如你所看到的,它与我需要的有点不同。如果你知道一个函数,它可以将一周中的所有天数变为1(甚至是12月份的天数),我很想听听这个。谢谢非常感谢。这不就是把所有53个换成1个吗?我不确定这是否有效,因为如果有一年,二月有29天,一月一日是星期六,也就是说一月二日是星期天,第二周是星期天,那么那一年将有54周没有,所以53岁的人需要保持原样,只有54岁的人变为1岁。令人困惑在这种情况下,您必须使用
最大周数-1
的mod。因此,一旦你完成了周数的计算,回顾一年中的最后一周,这也行不通,因为如果1月1日是星期日,你会希望将12月的所有日期都保留为一年中的最后一周。
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
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']])