#python #pandas #dataframe #datetime #timestamp
#python #pandas #фрейм данных #дата и время #временная метка
Вопрос:
В настоящее время я успешно закодировал программу, которая позволяет мне находить полные или частичные временные перекрытия (см. ‘group_overl’ с тем же номером).
Возникают два случая:
- Если у меня полное перекрытие, я должен удалить тот или тех, кто включен в первый.
- Если у меня частичное перекрытие, я должен начать второе и пересчитать продолжительность.
Для лучшего понимания, вот пример:
Мой df:
alias begin end duration group_overl
0 M4 2019-10-21 07:39:26.356716 2019-10-21 07:42:02.574268 156.218 1
1 M4 2019-10-21 07:40:03.235327 2019-10-21 07:42:02.222821 118.987 1
2 M4 2019-10-21 07:42:52.299657 2019-10-21 07:43:19.834114 27.534 2
3 M4 2019-10-21 07:44:09.936458 2019-10-21 07:44:37.143862 27.207 3
4 M4 2019-10-21 07:45:27.488518 2019-10-21 07:45:54.122312 26.634 4
5 M4 2019-10-21 07:57:27.564887 2019-10-21 08:26:00.413448 1712.849 11
6 M4 2019-10-21 07:58:06.209659 2019-10-21 08:27:00.413448 1734.204 11
Ожидаемый результат:
alias begin end duration
0 M4 2019-10-21 07:39:26.356716 2019-10-21 07:42:02.574268 156.218
2 M4 2019-10-21 07:42:52.299657 2019-10-21 07:43:19.834114 27.534
3 M4 2019-10-21 07:44:09.936458 2019-10-21 07:44:37.143862 27.207
4 M4 2019-10-21 07:45:27.488518 2019-10-21 07:45:54.122312 26.634
5 M4 2019-10-21 07:57:27.564887 2019-10-21 08:26:00.413448 1712.849
6 M4 2019-10-21 08:26:00.413448 2019-10-21 08:27:00.413448 60
- Как вы можете видеть, строка 1 исчезла, потому что она полностью соответствует времени строки 0. строка 1 была удалена.
- Строка 6 частично находится в строке 5. Итак, реальное начало 6 — это конец 5. Итак, мы делаем новое различие между началом и концом строки 6, чтобы иметь новую продолжительность (здесь 60 секунд).
Я пробовал несколько методов лечения, но не могу этого сделать, спасибо за ваше время!
Комментарии:
1. Есть ли несколько
alias
значений, которые вам нужно сгруппировать, ИЛИ это все столбцыM4
?2. в этом случае все столбцы имеют значение ‘M4’, потому что я уже разложил df. Но в другом проекте, по сути, приветствуется groupby.
3. Ожидаете ли вы более 2 строк в
group_overl
группе?4. @QuangHoang да, это возможно
Ответ №1:
Поскольку мы используем shift()
этот метод, предполагается, что вы отсортировали фрейм данных по begin
столбцу, как показано в вашем примере. Похоже, вам не нужно группировать alias
:
Создайте два условия, о которых вы упомянули, используя shift
. Для первого условия отфильтруйте результаты. Для второго используйте where()
.
df['begin'] = pd.to_datetime(df['begin'])
df['end'] = pd.to_datetime(df['end'])
c1 = (df['begin'].between(df['begin'].shift(), df['end'].shift())
amp; df['end'].between(df['begin'].shift(), df['end'].shift()))
c2 = (df['begin'].between(df['begin'].shift(), df['end'].shift())
amp; df['end'].gt(df['end'].shift()))
df = df[~c1]
df['duration'] = df['duration'].where(~c2, (df['end'] - df['end'].shift()).dt.seconds)
df
Out[1]:
alias begin end duration
0 M4 2019-10-21 07:39:26.356716 2019-10-21 07:42:02.574268 156.218
2 M4 2019-10-21 07:42:52.299657 2019-10-21 07:43:19.834114 27.534
3 M4 2019-10-21 07:44:09.936458 2019-10-21 07:44:37.143862 27.207
4 M4 2019-10-21 07:45:27.488518 2019-10-21 07:45:54.122312 26.634
5 M4 2019-10-21 07:57:27.564887 2019-10-21 08:26:00.413448 1712.849
6 M4 2019-10-21 07:58:06.209659 2019-10-21 08:27:00.413448 60.000
group_overl
0 1
2 2
3 3
4 4
5 11
6 11
Если вы хотите убедиться, что эти условия выполняются группой, тогда вы можете создать третье условие, чтобы они были в одной группе. Убедитесь, что вы
df = df.sort_values(['alias','begin','end])
и тогда:
df['begin'] = pd.to_datetime(df['begin'])
df['end'] = pd.to_datetime(df['end'])
c1 = (df['begin'].between(df['begin'].shift(), df['end'].shift())
amp; df['end'].between(df['begin'].shift(), df['end'].shift()))
c2 = (df['begin'].between(df['begin'].shift(), df['end'].shift())
amp; df['end'].gt(df['end'].shift()))
c3 = df['alias'] == df['alias'].shift()
df = df[~(c1 amp; c3)]
df['duration'] = df['duration'].where(~(c2 amp; c3), (df['end'] - df['end'].shift()).dt.seconds)
df
Out[2]:
alias begin end duration
0 M4 2019-10-21 07:39:26.356716 2019-10-21 07:42:02.574268 156.218
2 M4 2019-10-21 07:42:52.299657 2019-10-21 07:43:19.834114 27.534
3 M4 2019-10-21 07:44:09.936458 2019-10-21 07:44:37.143862 27.207
4 M4 2019-10-21 07:45:27.488518 2019-10-21 07:45:54.122312 26.634
5 M4 2019-10-21 07:57:27.564887 2019-10-21 08:26:00.413448 1712.849
6 M4 2019-10-21 07:58:06.209659 2019-10-21 08:27:00.413448 60.000
group_overl
0 1
2 2
3 3
4 4
5 11
6 11
Комментарии:
1. Большое спасибо! И если мне нужно использовать
groupby
по каким-то причинам, например, несколько псевдонимов (по случайности)?2. Если у меня есть другой столбец для
groupby
. С вашим кодом мне просто нужно добавить его вsort_values
c4 = df[‘priority’] == df[‘priority’].shift() df=df[~(c1 amp; c3 amp; c4)] и изменить условие вwhere
?3. @ThonyNadir точно. У вас получилось! Если бы вы могли любезно принять в качестве решения / проголосовать за ответ, я был бы очень признателен. Спасибо!
4. условие where равно c2 amp; c3 amp; c4 ?