Python Dataframe: получить альтернативные дни в зависимости от месяца? - PullRequest
5 голосов
/ 28 мая 2020

У меня есть df со столбцом salary_day

            salary_day
    0       thursday
    1       friday

Я пытаюсь получить альтернативные даты для каждого дня.

Для May 2020:

четверг в мае: 7,14,21,28, пятница в мае: 1,8,15,22,29

Ожидаемый результат для альтернативных четверга и пятницы в месяце May:

df

salary_day        req_dates
thursday           7,21 
friday           1,15,29

Для June 2020:

Четверг июня: 4,11,18,25 Пятница в июне: 5,12,19,26

Поскольку в мае 5 пятниц, первая пятница июня не является альтернативным днем и должны быть исключены, а 12,26 следует рассматривать

ожидаемый результат для альтернативных четверга и пятницы для месяца June:

df

salary_day        req_dates
thursday           4,18
friday             12,26



Edit1: На все дни недели

На май месяц

      salary_day        req_dates
0     Monday            4,18
1     Tuesday           5,19
2     Wednesday         6,20
3     Thursday          7,21
4     Friday           1,15,29 
5     Saturday         2,16,30 
6     Sunday           3,17,31

Ответы [ 2 ]

3 голосов
/ 28 мая 2020

Я думаю, что наиболее простой и общий способ сделать это - создать справочную таблицу со всеми днями указанного года. И создайте дополнительные столбцы: month, day_name, day.

Затем, чтобы проверить, какие day_names находятся в df['salary_day] `.

После этого мы проверяем, не четно ли day, по: day % 2 > 0.

Наконец, мы GroupBy.agg и присоединяем day как строку ,:

# create salary days to get altnerative days
days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
df = pd.DataFrame({'salary_day': days})

START_MONTH = 5
YEAR = 2020

def create_dates(y, month_start):
    dates = pd.date_range(f'{y}-{str(month_start).zfill(2)}-01', f'{y}-12-31')
    dates = pd.DataFrame({'dates': dates})
    dates['month'] = dates['dates'].dt.month
    dates['day_name'] = dates['dates'].dt.day_name().str.lower()
    dates['day'] = dates['dates'].dt.day
    return dates


def get_alternative_dates(salary_days, y, month_start):
    df_dates = create_dates(y, month_start)

    m = df_dates['day_name'].isin(salary_days)

    months = df_dates[m].copy()
    months['day'] = months['day'].astype(str)
    months['rank_days'] = months.groupby('day_name')['day'].cumcount().add(1)

    months = months[months['rank_days'].mod(2).ne(0)]
    df_final = months.groupby(['month', 'day_name'])['day'].agg(','.join).reset_index()

    return df_final

get_alternative_dates(df['salary_day'], YEAR, START_MONTH)

Вывод

    month  day_name      day
0       5    friday  1,15,29
1       5  thursday     7,21
2       6    friday    12,26
3       6  thursday     4,18
4       7    friday    10,24
5       7  thursday  2,16,30
6       8    friday     7,21
7       8  thursday    13,27
8       9    friday     4,18
9       9  thursday    10,24
10     10    friday  2,16,30
11     10  thursday     8,22
12     11    friday    13,27
13     11  thursday     5,19
14     12    friday    11,25
15     12  thursday  3,17,31
0 голосов
/ 28 мая 2020

Это сработало для меня:

# for read_clipboard()
'''
salary_day
thursday
friday
'''

import pandas as pd
df = pd.read_clipboard()
print(df)

.

  salary_day
0   thursday
1     friday

.

import calendar

c = calendar.Calendar(firstweekday=calendar.SUNDAY)

year = 2020; month = 5

monthcal = c.monthdatescalendar(year,month)
fridays = [(str(day)[-2:]) for week in monthcal for day in week if \
                day.weekday() == calendar.FRIDAY and \
                day.month == month]
thursdays = [(str(day)[-2:]) for week in monthcal for day in week if \
                day.weekday() == calendar.THURSDAY and \
                day.month == month]

# Friday will be the first salary day of the month only if it occours on 1st
if int(thursdays[0]) < int(fridays[0]):
   fridays = fridays[1:] 


df['req_dates'] = ''

print(df)

df.loc[df['salary_day'] == 'thursday', 'req_dates'] = ','.join(thursdays[::2])
df.loc[df['salary_day'] == 'friday', 'req_dates'] = ','.join(fridays[::2])

Вывод:

  salary_day req_dates
0   thursday     07,21
1     friday  01,15,29

На июнь месяц:

year = 2020; month = 6

Вывод:

  salary_day req_dates
0   thursday     04,18
1     friday     12,26
...