Data AnalyticsData Cleaningbeginner
Updated:

Removing Duplicate Records in Pandas

4 min read

Duplicate rows silently inflate every count and total. Learn to detect them with duplicated() and remove them with drop_duplicates(), including subset and keep.

TL;DR – Quick Answer

Removing duplicate records means finding rows that repeat and keeping only one copy so counts and totals are correct. In pandas you detect duplicates with duplicated() and remove them with drop_duplicates(). Use the subset argument to define duplicates by specific key columns, and the keep argument to choose which copy survives.

On This Page

Duplicate records are one of the most damaging data defects precisely because they are invisible. A duplicated customer row does not throw an error; it just quietly doubles that customer's revenue in every total. Removing duplicates means finding rows that repeat and keeping only the copy you want, so counts, sums and averages reflect reality. In pandas the two tools are duplicated() to detect and drop_duplicates() to remove, but the real skill is deciding what counts as a duplicate.

This topic pairs closely with inconsistent category labels, because near-duplicates often hide behind small text differences, and it builds on the overview in what is data cleaning.

What "duplicate" actually means

There are two kinds. An exact duplicate is a row identical to another across every column — usually a data-entry or import glitch. A key duplicate is a row that repeats a business key, like the same email or customer_id, even though other columns differ. Which one you care about depends on the grain of the table: what a single row is supposed to represent. If each row should be one unique customer, two rows with the same email are duplicates even if their spend differs. If each row is one purchase, the same customer appearing twice is perfectly correct.

Getting this right is the whole game. Blindly deleting repeated customers when rows are meant to be purchases destroys real data.

Detecting duplicates

Start by looking, never by deleting. Here is an illustrative messy sample.

import pandas as pd

df = pd.DataFrame({
    "customer_id": [1, 2, 2, 3, 3, 4],
    "email":       ["a@x.com", "b@x.com", "b@x.com", "c@x.com", "c@x.com", "d@x.com"],
    "order":       ["A100", "A101", "A101", "A102", "A103", "A104"],
    "amount":      [1200, 980, 980, 550, 600, 760],
})

print("exact dup rows:", df.duplicated().sum())
print(df[df.duplicated(keep=False)])          # show every row involved

Expected output:

exact dup rows: 1
   customer_id    email order  amount
1            2  b@x.com  A101     980
2            2  b@x.com  A101     980

duplicated() flags the second identical row for customer 2. Notice customer 3 appears twice too, but those rows are not exact duplicates — different orders and amounts — so they are not flagged. Whether they are a problem depends entirely on the table's grain.

Removing exact duplicates

For true identical repeats, drop_duplicates() keeps one copy:

clean = df.drop_duplicates()
print(clean)
   customer_id    email order  amount
0            1  a@x.com  A100    1200
1            2  b@x.com  A101     980
3            3  c@x.com  A102     550
4            3  c@x.com  A103     600
5            4  d@x.com  A104     760

The duplicate A101 row is gone; customer 3's two distinct orders correctly remain. drop_duplicates() defaults to keep='first', retaining the earliest copy. Use keep='last' to keep the most recent, or keep=False to drop every copy of anything duplicated (useful when you want to isolate and inspect them rather than trust either version).

Deduplicating by a business key

When rows should be unique by an id or email but other fields drift, dedupe on a subset:

# keep only one row per customer_id, preferring the last (most recent) record
one_per_customer = df.drop_duplicates(subset=["customer_id"], keep="last")
print(one_per_customer[["customer_id", "email", "order", "amount"]])
   customer_id    email order  amount
0            1  a@x.com  A100    1200
2            2  b@x.com  A101     980
4            3  c@x.com  A103     600
5            4  d@x.com  A104     760

Now there is exactly one row per customer. keep='last' kept customer 3's second order — the choice of first versus last should match which record you trust, for example the most recent update.

A frequent real-world need is to keep the most complete or most recent record per key rather than an arbitrary first or last. The pattern is to sort first, then dedupe: sort by an update timestamp descending, then drop_duplicates(subset=[key], keep='first') retains the newest row per key. Sorting before deduping turns keep from a blind choice into a deliberate rule, and is how analysts collapse a change-log of updates down to one current record per entity.

How analysts use it

The professional routine: first establish the grain ("one row = one what?"), then check exact duplicates with duplicated().sum(), then check key duplicates with duplicated(subset=[key]). Inspect the flagged rows before deleting, because a "duplicate" is sometimes two legitimate events or two conflicting records that need reconciling, not deleting. When deduping by key, decide deliberately whether the first or last record wins. Finally, re-check your headline totals before and after — a big drop in a sum after dedup is a signal that duplicates were meaningfully inflating your numbers.

Common mistakes

  • Deleting without inspecting. Running drop_duplicates() blind can remove legitimate rows. Always view df[df.duplicated(keep=False)] first.
  • Confusing grain. Treating repeated customers as duplicates when each row is meant to be a purchase deletes real transactions. Define the grain before deduping.
  • Ignoring near-duplicates. " b@x.com " with a trailing space, or "B@X.com" in different case, will not match as duplicates until the text is standardized. Clean text first (see inconsistent category labels).
  • Defaulting to keep='first' without thinking. If the latest record is the corrected one, keeping the first retains stale data. Match keep to which copy you trust.

In interviews

Expect "How would you find and remove duplicate rows?" and follow-ups about deduping by key columns. Strong answers name duplicated() and drop_duplicates(), explain the subset and keep arguments, and — most importantly — raise the grain question: you cannot decide what a duplicate is without knowing what one row represents. Mentioning that text inconsistencies hide duplicates, and that you inspect before deleting, shows maturity beyond memorized syntax.

Where this fits in your learning path

Removing duplicates is a core early skill in the data cleaning cluster, right alongside missing-value handling. It follows naturally from what is data cleaning and connects to inconsistent category labels, since standardizing text is what makes hidden duplicates visible. Reliable deduplication is a fundamental part of the data analyst roadmap.

Frequently Asked Questions

How do I find duplicate rows in pandas?
Use df.duplicated(), which returns a boolean series marking each row that is a repeat of an earlier one. df.duplicated().sum() counts them, and df[df.duplicated(keep=False)] shows every row involved in any duplication so you can inspect them before deleting.
What does the keep argument do in drop_duplicates?
keep controls which copy is retained. keep='first' (the default) keeps the first occurrence, keep='last' keeps the last, and keep=False removes all copies of any duplicated row entirely. Choose based on whether the earliest or latest record is the one you trust.
How do I remove duplicates based on only some columns?
Pass subset with the key columns, for example df.drop_duplicates(subset=['email']). This treats rows as duplicates when those columns match, even if other columns differ. It is how you deduplicate by a business key like customer id or email rather than requiring the whole row to be identical.
Why are duplicates dangerous in analysis?
Duplicates silently inflate counts, sums and averages. A customer counted twice doubles their revenue contribution and can skew every metric built on that data. Because the query still runs and the chart still renders, the error is invisible until someone checks the totals against a trusted source.
Should I always remove duplicates?
No. Some repetition is legitimate, such as a customer making two separate purchases, which are correctly two rows. Only remove records that are truly unintended copies. Deciding this requires knowing what a single row is supposed to represent, called the grain of the table.

Want to Build Your Career in Data Analytics with AI?

Join CodeBegun and train with working industry engineers — Explore the Data Analytics program

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 16 July 2026 LinkedIn
Chat with us