как справиться с временным перекрытием и определить продолжительность? Pandas Python

#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 ?