Мой набор данных выглядит так:
main_id time_stamp
aaa 2019-05-29 08:16:05+05
aaa 2019-05-30 00:11:05+05
aaa 2020-05-30 09:15:07+05
bbb 2019-05-29 09:11:05+05
Для каждого main_id
я хочу:
а) отсортировать time_stamps в порядке возрастания
б) Я хочу создать новый столбец day
, который использует time_stamp для получения числа, описывающего рабочий день.
Рабочие дни определяются следующим образом:
Понедельник 05:00 - Вторник 01:00 (1 рабочий день, т.е. понедельник)
вторник 05:00 - среда 01:00 => (1 рабочий день, т.е. вторник)
и так далее...
Первая и вторая строки со значком main_id = aaa
относятся к одному и тому же рабочему дню, поскольку вторая строка показывает время до 1:00 следующего дня. Итак, это самый первый рабочий день, и в столбце day
будет 1
.
Однако в третьей строке отметка времени относится к другому рабочему дню, поэтому мы добавляем 2
вместо day
.
Конечный результат может выглядеть примерно так:
main_id time_stamp day
aaa 2019-05-29 08:16:05+05 1
aaa 2019-05-30 00:11:05+05 1
aaa 2020-05-30 09:15:07+05 2
bbb 2019-05-29 09:11:05+05 1
День 1 будет где-то между 5:00 утра и 1:00 следующего дня. В то время как днем 2 будет следующий возможный рабочий день (следующие 5:00 - 1:00)
Как я могу этого добиться?
df = df.sort_values('vehicle_id')
ничего. Я предполагаю, что между этими временными интервалами нет данных @mozway
Тогда должно сработать простое вычитание, см. мой ответ
#Let's say the dataframe is df
df['time_stamp'] = pd.to_datetime(df['time_stamp'])
df.sort_values(by='time_stamp')
day1= #add the end of the first businesss date, like: 2019-05-30 01:00
df['day']=1
for i in df.index:
df['day'].iloc[i]+=ceil(df['day'].iloc[i] - day1)
При сортировке по отметкам времени я также хочу убедиться, что группировка main_id остается неизменной.
Кроме того, я не знаю, чем закончился первый рабочий день. придется извлечь его из df
Простым методом было бы вычесть 5 часов, а затем сгруппировать по отсортированным датам, чтобы получить номер группы:
df['time_stamp'] = pd.to_datetime(df['time_stamp'])
s = df['time_stamp'].sub(pd.Timedelta('5h'))
df['day'] = df.groupby(s.dt.date).ngroup().add(1)
NB. на самом деле вам не нужно сортировать значения, groupby
сортирует значение по умолчанию.
Вариант для применения на «main_id»:
df['day'] = (df.groupby('main_id')
.apply(lambda d: d.groupby(s.dt.date).ngroup().add(1)).droplevel(0)
)
Выход:
main_id time_stamp day
0 aaa 2019-05-29 08:16:05+05:00 1
1 aaa 2019-05-30 00:11:05+05:00 1
2 aaa 2020-05-30 09:15:07+05:00 2
3 bbb 2019-05-29 09:11:05+05:00 1
не могли бы вы немного объяснить свой код? почему ты вычитаешь 5?
Чтобы привести свой рабочий день в соответствие с обычным днем, начав на 5 часов раньше: 5->1 становится 0->20 (здесь вы можете вычесть только 1 час).
Было бы здорово, если бы вы могли объяснить немного больше... также часть ngroup(). ТАКЖЕ, с текущим кодом временные метки не сортируются в порядке возрастания. Как я могу достичь этого? Таким образом, элементы по-прежнему сгруппированы по main_id
во всех aaa
вместе, а затем все bbb
вместе. Я уже отсортировал main_ids перед вашим фрагментом кода, как показано в qs
Сейчас отключаюсь, уточню позже
Чтобы отсортировать даты, просто используйте df = df.sort_values(by=['main_id','time_stamp'])
не могли бы вы объяснить эту часть немного больше? df.groupby(s.dt.date).ngroup().add(1)
Конечно, для каждой группы (здесь каждая дата) получите номер группы (от 0 до n-1) и добавьте 1, так как вы хотите, чтобы ваш счет начинался с 1.
Что должно происходить между 1 и 5 часами ночи?