Пользовательская логика для удаления дубликатов

У меня есть следующий набор данных, к которому я надеюсь применить некоторую пользовательскую логику:

data = pd.DataFrame({'ID': ['A','B','B','C','C','D','D'], 
'Date': ['2018-07-02T02:21:12.000+0000','2018-07-02T02:28:29.000+0000','2018-07-02T02:28:31.000+0000','2018-07-02T02:30:58.000+0000','2018-07-02T02:31:01.000+0000','2018-07-02T02:42:46.000+0000','2018-07-02T02:41:47.000+0000'],
'Action': ['Start','Start','Start','Stop','Stop','Start','Start'],
'Group': [5,13,13,19,19,2,2],
'Value': [100,110,110,95,95,280,280]
})

Строки 1:2, 3:4 и 5:6 идентичны, за исключением значений в столбце «Дата», которые отличаются на несколько секунд. Есть ли способ удалить дубликаты, если 1) временная дельта «даты» между похожими строками меньше 1 минуты и 2) вся остальная информация идентична?

Результат должен выглядеть следующим образом:

result = pd.DataFrame({
'ID': ['A','B','C','D'], 
'Date': ['2018-07-02T02:21:12.000+0000','2018-07-02T02:28:29.000+0000','2018-07-02T02:30:58.000+0000','2018-07-02T02:42:46.000+0000'],
'Action': ['Start','Start','Stop','Start'],
'Group': [5,13,19,2],
'Value': [100,110,95,280]
})

person Dfeld    schedule 19.07.2018    source источник
comment
Это может быть двусмысленно. Скажем, у вас есть несколько строк в течение 2 минут. Какой 1-минутный слот вы выбираете для группировки?   -  person jpp    schedule 19.07.2018
comment
jpp делает очень хорошее замечание. Решение, которое я предоставил, является каскадным, а это означает, что если бы у вас было 10 измерений с интервалом в 59 секунд, вы все равно сохранили бы только первое измерение и рассмотрели бы остальные 9 дубликатов. Возможно, это то, что вам нужно, но если нет, вам нужно будет выполнить какой-то другой тип группировки. Если у вас есть только 2 даты для каждой группы, это не будет проблемой.   -  person ALollz    schedule 19.07.2018


Ответы (1)


Кажется, что желаемая логика может быть реализована с помощью самослияния с использованием pd.merge_asof, что позволяет сочетать сопоставление точных ключей и nearest ключей.

Вы исключите точные совпадения и будете использовать направление по умолчанию backward, что означает, что вы всегда будете сохранять только самую раннюю запись времени в случае, если две (или более) записи происходят в указанном временном окне.

import pandas as pd

data['Date'] = pd.to_datetime(data.Date)
data = data.sort_values('Date')

merged = pd.merge_asof(
              data, 
              data.rename(columns={'Date': 'Date2'}), 
              by=[x for x in data.columns if x != 'Date'], 
              left_on='Date', right_on='Date2',
              direction='backward',
              allow_exact_matches=False)

# Remove duplicates within 1 minute
merged[((merged.Date - merged.Date2) > pd.Timedelta(minutes=1)) | (merged.Date2.isnull())].drop(columns='Date2')

Выходы:

  ID                Date Action  Group  Value
0  A 2018-07-02 02:21:12  Start      5    100
1  B 2018-07-02 02:28:29  Start     13    110
3  C 2018-07-02 02:30:58   Stop     19     95
5  D 2018-07-02 02:41:47  Start      2    280
person ALollz    schedule 19.07.2018