pandas: типы столбцов и очистка по правилу

Дубли: duplicated и drop_duplicates по ключевым столбцам

Содержание курса

Параметр keep: управление тем, что считается дублем

Когда duplicated() находит группу строк с одинаковыми значениями по subset, она должна решить: какую из них считать «оригиналом», а какие — дублями. Этим управляет параметр keep.

По умолчанию keep='first': первое вхождение получает False (не дубль), все последующие — True. При keep='last' логика зеркальная: последнее вхождение считается «оригиналом», все предыдущие помечаются True.

import pandas as pd

df = pd.DataFrame({
    'user_id': [1, 2, 1, 3, 2],
    'action':  ['login', 'buy', 'login', 'view', 'buy'],
    'amount':  [0, 100, 0, 50, 200]
})

key_cols = ['user_id', 'action']

print(df.duplicated(subset=key_cols, keep='first').tolist())
# [False, False, True, False, True]

print(df.duplicated(subset=key_cols, keep='last').tolist())
# [True, True, False, False, False]

Здесь строки 0 и 2 — это пара (1, 'login'). При keep='first' дублем считается строка 2; при keep='last' — строка 0. Строки 1 и 4 — пара (2, 'buy'): аналогично меняется, кто из них получает True.

Третье значение — keep=False — отличается принципиально: дублями помечаются все строки группы, включая первое вхождение.

print(df.duplicated(subset=key_cols, keep=False).tolist())
# [True, True, True, False, True]

Это удобно для диагностики: чтобы увидеть все строки, участвующие в дублировании, достаточно отфильтровать по этой маске:

print(df[df.duplicated(subset=key_cols, keep=False)])
#    user_id action  amount
# 0        1  login       0
# 1        2    buy     100
# 2        1  login       0
# 4        2    buy     200

Один из важных практических нюансов: если передать keep=False не в duplicated(), а в drop_duplicates(), результат будет удалять все строки с дублями — включая «оригиналы». То есть из таблицы исчезнут все четыре строки выше, а не только «лишние» копии. Для большинства задач это не то, что нужно.

Правило простое: keep=False — инструмент диагностики, чтобы посмотреть на проблему. Для реального удаления используй keep='first' или keep='last', явно выбирая, какую запись из группы сохранить.