Pandas посчитать сумму часов за месяц
Есть задача, в которой суть заключается в выводе суммы часов за месяц, данные берутся из датафрейма, который берется из дб, данные в дб поступают из телеграмм бота:
| Name | date_reg | time_reg | date_start_job | time_start_job | time_end_job |
|---|---|---|---|---|---|
| @test1 | 21-05-2021 | 11:18 | 22-05-2021 | 10:00 | 19:07 |
| @test2 | 21-05-2021 | 12:13 | 22-05-2021 | 9:58 | 20:04 |
Пробовал сравнивать дату(год и месяц) в столбце с датой и дату(год и месяц) на текущий момент, с помощью datetime, но данный способ не универсален:
month = dt.datetime.today()
date = month.strftime("%Y-%m")
tetsd = df['date_start_job'] == date
Сумму получаю по всем месяцам, но по отдельным месяцам вычленить ее не получается:
datedf = df.groupby(['name', 'date_start_job']).first()
kek = datedf.groupby('name').sum()
На выходе должен получиться фрейм с указанием "name", месяцем и суммой часов за этот месяц:
| name | month | summ |
|---|---|---|
| @test1 | 05 | 09:07 |
| @test2 | 05 | 10:46 |
В моем же случае сейчас считается вся сумма часов без оглядки на месяц.
Буду признателен за помощь, или в каком направлении копать.
Ответы (2 шт):
Проще всего создать ещё одну колонку, в которой будет записано время работы за сессию. Затем просто применить к столбцу с датой (в пандасовском формате, конечно) метод resamlpe. Что-то вроде этого должно работать:
df['summ'] = df[time_end_job] - df[time_start_job]
print(df.query('name == "test1"').resample('1M', on='date_start_job'))
Тогда в последней колонке будет суммарное время за месяц.
Моя попытка решения вашей задачи
Исходные данные:
Name date_reg time_reg date_start_job time_start_job time_end_job
@test1 21-05-2021 11:18 21-05-2021 10:00 19:07
@test2 21-05-2021 12:13 21-05-2021 9:58 20:00
@test1 21-05-2021 12:13 21-05-2021 9:24 20:04
@test2 21-05-2021 12:13 22-05-2021 9:58 19:04
@test1 21-05-2021 12:13 21-04-2021 9:34 20:04
@test2 21-05-2021 12:13 21-02-2021 9:58 20:10
@test1 21-05-2021 12:13 21-04-2021 9:58 20:04
@test2 21-05-2021 12:13 21-02-2021 9:15 20:04
@test1 21-05-2021 12:13 21-03-2021 9:58 21:00
@test2 21-05-2021 12:13 21-02-2021 5:16 20:04
Типы данных:
Name object
date_reg object
time_reg object
date_start_job object
time_start_job object
time_end_job object
dtype: objectэ
Решение:
(df
# Конвертируем строки в дату и время
.assign(time_start_job=pd.to_datetime(df.time_start_job))
.assign(time_end_job=pd.to_datetime(df.time_end_job))
# Считаем разницу между начальным и конечным временем
.assign(time_spent=lambda x: (x.time_end_job - x.time_start_job))
# Группируем датафрейм по имени и году-месяцу
.groupby(['Name', pd.to_datetime(df.date_start_job).dt.strftime('%Y-%m')])
# Считаем сумму потраченного времени для каждой группы
['time_spent'].sum()
# Можно получить сумму в секундах, чтобы потом пересчитать как хочется
#['time_spent'].sum().dt.total_seconds()
.reset_index(name='time_spent_sum')
)
Результат:
Name date_start_job time_spent_sum
0 @test1 2021-03 0 days 11:02:00
1 @test1 2021-04 0 days 20:36:00
2 @test1 2021-05 0 days 19:47:00
3 @test2 2021-02 1 days 11:49:00
4 @test2 2021-05 0 days 19:08:00
Для ваших данных результат такой:
name date_start_job time_spent_sum
0 AndryshchenkoSergey 2021-05 1 days 21:57:00
1 AndryshchenkoSergey 2021-06 0 days 17:21:00
2 wt4565 2021-05 0 days 02:18:00
3 z6_1_02 2021-05 0 days 08:03:00