Собесов

Сценарий: дедупликация строк с правилом приоритета

PythonОчистка данныхЛёгкаяJunior

Условие

В таблице contacts(email, name, source, updated_at) для одного email бывает несколько строк из разных источников. Нужно оставить одну строку на email — самую свежую по updated_at, а при равенстве — из источника crm (приоритет над web).

Решение

Подход

sort_values по нескольким ключам в нужном порядке + drop_duplicates(keep='first').

Реализация

priority = {'crm': 0, 'web': 1, 'mobile': 2, 'csv_import': 3}
contacts['source_rank'] = contacts['source'].map(priority).fillna(99)
 
dedup = (
    contacts
    .sort_values(
        ['email', 'updated_at', 'source_rank'],
        ascending=[True, False, True],   # email any, свежие сверху, приоритетные сверху
    )
    .drop_duplicates(subset='email', keep='first')
    .drop(columns='source_rank')
)

Альтернатива через groupby

dedup = (
    contacts
    .assign(source_rank=contacts['source'].map(priority).fillna(99))
    .sort_values(['updated_at', 'source_rank'], ascending=[False, True])
    .groupby('email', as_index=False)
    .first()
)

Подводные камни

  1. drop_duplicates(keep='first') зависит от порядка строк — без sort_values результат недетерминирован.
  2. NaN в updated_at сортируются в конец независимо от ascending (опция na_position='last').
  3. Если email в разном регистре (A@x.com vs a@x.com) — это разные строки. Сначала email.str.lower().str.strip().
  4. groupby(...).first() берёт первое не-NaN значение по каждой колонке — это часто не то же, что «первая строка целиком». Будьте аккуратны.
  5. Невидимые пробелы в email — , табы — str.strip() их не убирает. Используйте str.replace(r'\s+', '', regex=True).

Эталонный ответ

sort_values([...]).drop_duplicates(subset='email', keep='first') после нормализации регистра и пробелов.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти