Короткий ответ
Полное совпадение всех столбцов строки — более строгое условие, чем совпадение бизнес-ключа (например, order_id); если в таблице несколько версий одного заказа с разными статусами, проверка полных дубликатов их не найдёт, и в итоге дашборд, считающий по order_id, и источник, считающий по строкам, дадут разные числа.
Как это работает подробнее
df.duplicated() без параметров сравнивает все столбцы, а df.duplicated(subset=['order_id']) — только указанный ключ; если каждая версия заказа отличается хотя бы одним полем (например, временной меткой обновления), полные дубликаты не обнаруживаются, хотя по бизнес-смыслу должна быть одна запись на заказ.
Пример кода
question-133.py
import pandas as pd
df = pd.DataFrame({
'order_id': [1, 1, 2],
'status': ['created', 'paid', 'paid'],
'amount': [100, 100, 50]
})
print(len(df), df['order_id'].nunique())
dedup = df.drop_duplicates(subset=['order_id'], keep='last')
print(dedup['amount'].sum())Что использовать на практике
- Практика. при расхождении дашборда и источника стоит первым шагом сравнить df['order_id'].nunique() с len(df) — если они не равны, источник содержит несколько строк на один бизнес-объект, и нужно явно решить, какую версию считать "актуальной" (например, keep='last' по дате обновления) до агрегации.
- Проверка. len(df) равен 3, а nunique() по order_id — 2; после дедупликации по бизнес-ключу сумма amount равна 150 (100 + 50), а не 250, как если бы считали по всем строкам.
Подводные камни
- Частая ошибка. считают общее количество строк "количеством заказов", не проверив уникальность бизнес-ключа, из-за чего дашборд, который правильно дедуплицирует по order_id, показывает меньшее число, которое ошибочно интерпретируют как "дашборд врёт"; дедуплицируют без сортировки по времени обновления, оставляя случайную, а не актуальную версию записи.