Пусть это будет следующий Python Panda DataFrame:
| ID | date | direction | country_ID |
|-----------|-------------------------|---------------|------------|
| 0 | 2022-04-01 10:00:01 | IN | UK |
| unknown | 2022-04-01 10:00:03 | IN | UK |
| 0 | 2022-04-01 12:00:01 | OUT | UK |
| 0 | 2022-04-01 12:30:11 | IN | GER |
| 1 | 2022-04-01 10:00:00 | IN | GER |
| 1 | 2022-04-01 08:04:03 | OUT | GER |
| unknown | 2022-04-01 10:20:02 | OUT | USA |
| unknown | 2022-04-01 09:59:58 | IN | GER |
| unknown | 2022-04-01 05:04:03 | OUT | ITL |
| unknown | 2022-04-01 05:04:01 | OUT | ITL |
| 2 | 2022-04-01 05:03:59 | OUT | ITL |
Мне нужно создать DataFrame, содержащий строки с неизвестным значением идентификатора, которые имеют совпадающую запись со значениями направления и страны_ID с интервалом в 2 секунды (его можно изменить), но идентификатор строки, которой он соответствует, отличается от неизвестного.
Все строки неизвестны:
| ID | date | direction | country_ID |
|-----------|-------------------------|---------------|------------|
| unknown | 2022-04-01 10:00:03 | IN | UK |
| unknown | 2022-04-01 10:20:02 | OUT | USA |
| unknown | 2022-04-01 09:59:58 | IN | GER |
| unknown | 2022-04-01 05:04:03 | OUT | ITL |
| unknown | 2022-04-01 05:04:01 | OUT | ITL |
Примеры соответствия для каждой строки, указанной выше:
| ID | date | direction | country_ID |
|-----------|-------------------------|---------------|------------|
| unknown | 2022-04-01 10:00:03 | IN | UK |
| 0 | 2022-04-01 10:00:01 | IN | UK |
| ID | date | direction | country_ID |
|-----------|-------------------------|---------------|------------|
| unknown | 2022-04-01 10:20:02 | OUT | USA |
| ID | date | direction | country_ID |
|-----------|-------------------------|---------------|------------|
| unknown | 2022-04-01 09:59:59 | IN | GER |
| 1 | 2022-04-01 10:00:00 | IN | GER |
| ID | date | direction | country_ID |
|-----------|-------------------------|---------------|------------|
| unknown | 2022-04-01 05:04:03 | OUT | ITL |
| ID | date | direction | country_ID |
|-----------|-------------------------|---------------|------------|
| unknown | 2022-04-01 05:04:01 | OUT | ITL |
| 2 | 2022-04-01 05:03:59 | OUT | ITL |
Удаляем те, у которых нет совпадений. Получаем результирующий DataFrame:
| ID | date | direction | country_ID | date_match | ID_match |
|-----------|-------------------------|---------------|------------|----------------------|---------------|
| unknown | 2022-04-01 10:00:03 | IN | UK | 2022-04-01 10:00:01 | 0 |
| unknown | 2022-04-01 09:59:58 | IN | GER | 2022-04-01 10:00:00 | 1 |
| unknown | 2022-04-01 05:04:01 | OUT | ITL | 2022-04-01 05:03:59 | 2 |
Спасибо заранее за вашу помощь.
Вы можете использовать маску, чтобы разделить фрейм данных на две части, и pandas.merge_asof
, чтобы найти совпадения по группам и в течение 2 секунд:
df['date'] = pd.to_datetime(df['date'])
mask = df['ID'].eq('unknown')
idx = (pd
.merge_asof(df[mask].sort_values(by='date').reset_index(),
df[~mask].sort_values(by='date'),
by=['direction', 'country_ID'],
on='date',
direction='nearest', tolerance=pd.Timedelta('2s'),
)
.loc[lambda d: d['ID_y'].notna(), 'index']
)
df.loc[sorted(idx)]
выход:
ID date direction country_ID
1 unknown 2022-04-01 10:00:03 IN UK
7 unknown 2022-04-01 09:59:58 IN GER
9 unknown 2022-04-01 05:04:01 OUT ITL
df2 = (pd
.merge_asof(df[mask].sort_values(by='date').reset_index(),
df[~mask].sort_values(by='date').rename(columns = {'date': 'date_match'}),
by=['direction', 'country_ID'],
left_on='date', right_on='date_match',
direction='nearest', tolerance=pd.Timedelta('2s'),
suffixes=('', '_match')
)
.loc[lambda d: d['ID_match'].notna()]
.set_index('index').sort_index()
)
выход:
ID date direction country_ID ID_match date_match
index
1 unknown 2022-04-01 10:00:03 IN UK 0 2022-04-01 10:00:01
7 unknown 2022-04-01 09:59:58 IN GER 1 2022-04-01 10:00:00
9 unknown 2022-04-01 05:04:01 OUT ITL 2 2022-04-01 05:03:59
см. обновление для данных матча
Как я могу добавить указанную выше информацию о совпадении в полученный DataFrame? Извините, я редактировал пост как раз в тот момент, когда вы ответили :(