pbPassingBI
/
Wrangling & cleaning beginner 5 min

Removing duplicates

Finding duplicate rows, choosing which to keep, and deduplicating on a key.

What you'll be able to do
  • Detect duplicates
  • Deduplicate on specific columns
  • Keep the right row when duplicates differ

Finding them

df.duplicated().sum()                      # fully identical rows
df[df.duplicated(keep=False)]              # show every copy, not just repeats
df.duplicated(subset=['email']).sum()      # duplicate on a key column

keep=False marks all copies rather than only the second onwards, which is what you want when inspecting.

Removing them

df = df.drop_duplicates()
df = df.drop_duplicates(subset=['email'])
df = df.drop_duplicates(subset=['email'], keep='last')

keep accepts 'first' (the default), 'last', or False to drop every copy.

Keeping the right one

When duplicates differ — an old and a new record for the same customer — sort first so the row you want is the one kept:

df = (df.sort_values('updated_at')
        .drop_duplicates(subset=['email'], keep='last'))

This is the pandas equivalent of ROW_NUMBER() OVER (PARTITION BY email ORDER BY updated_at DESC) in SQL. Without the sort, which row survives depends on file order — reproducible today, different tomorrow.

Duplicates that are not identical

df['email'] = df['email'].str.strip().str.lower()

[email protected] and [email protected] are different strings but the same customer. Normalise before deduplicating, or the duplicates stay.

Key points
  • keep=False marks every copy, which is what you want for inspection
  • Sort before drop_duplicates so the row you keep is deliberate
  • Normalise case and whitespace before deduplicating on text
Check yourself