Создание 53-й и 1-й недели в ту же неделю, начиная с воскресенья - PullRequest
0 голосов
/ 03 мая 2020

Привет, у меня есть следующие данные: указатель, день недели, неделя нет, феча

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 как полную неделю из 7 дней, то есть 29, 30 и 31 декабря, чтобы также получить неделю № 1. - чтобы это работало также, когда у меня много лет в этом наборе данных.

В этом конкретном году это означает изменение всех 53 на 1, но я думаю, что могут быть и другие годы, когда это не сработает. Таким образом, чтобы получить общее правило, я понял, что если первое января выпадает на воскресенье, мне не нужно ничего менять, поэтому я решил сначала проверить это на каждый год, и если первое января не выпадает на воскресенье, изменить все номера недели между предыдущим воскресеньем и этим воскресеньем на 1. Другой вариант, о котором я подумал, - это узнать, какой недели нет в предыдущем воскресенье, а затем изменить все номера недели этого года с тем же номером, что и в предыдущее воскресенье, 1. Для обоих я должен был бы выполнить условие внутри df, чтобы отфильтровывать только определенные строки, но как мне это сделать, когда я хочу отобразить только один столбец этого df? Смысл, если бы я сделал:

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

тогда это будет показывать все столбцы в итоговых значениях, в то время как я хотел бы и эти условия и видеть только столбец «День недели».

Так как бы мне это сделать, а также, все это звучит очень сложно для меня. Есть ли более простой / эффективный способ, который я упустил?

Спасибо!

Ответы [ 4 ]

0 голосов
/ 03 мая 2020

Итак, это то, что я придумал в конце. Как это производительность мудро?

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']])
0 голосов
/ 03 мая 2020

Используйте пакет datetime, как описано в этом ответе StackOverflow: Как найти номера недель с неделями, начинающимися в воскресенье, в Python?

0 голосов
/ 03 мая 2020

Похоже, вам нужен собственный настраиваемый бизнес-календарь, мы можем использовать небольшую функцию для его создания.

Если вы создаете календарь, начинающийся в первый календарный день каждого календарного года, тогда это будет работать .

Одно замечание: я не писал этого несколько лет, оставлю это на ваше усмотрение :)

Использование

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
0 голосов
/ 03 мая 2020

Вы можете использовать оператор mod. Это даст вам остаток после деления на данное число. Для этого 52 % 52 = 0 и 0 % 52 = 0. Мод действительно работает, только когда вы начинаете считать с 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
...