data frames
data comparison
pandas
python
data analysis

Find difference between two data frames

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Finding the difference between two pandas DataFrames can mean several different things: checking whether they are exactly equal, locating changed cell values, or identifying rows that exist in one table but not the other. The right method depends on which kind of difference you care about, so the first step is to define the comparison precisely.

Exact Equality Is the Simplest Check

If you only need to know whether two DataFrames are identical in values, index, and column order, use equals().

python
1import pandas as pd
2
3df1 = pd.DataFrame({"id": [1, 2], "value": [10, 20]})
4df2 = pd.DataFrame({"id": [1, 2], "value": [10, 20]})
5
6print(df1.equals(df2))

This returns one boolean, which is useful for quick assertions but not for understanding where the data differs.

Use compare() for Cell-Level Differences

If the DataFrames have the same index and columns and you want to see changed cells, compare() is the most direct tool.

python
1import pandas as pd
2
3df1 = pd.DataFrame({"id": [1, 2], "value": [10, 20]})
4df2 = pd.DataFrame({"id": [1, 2], "value": [10, 25]})
5
6print(df1.compare(df2))

The output highlights the old and new values side by side. This is ideal when both tables represent the same shape and identity, and only the contents may have changed.

Align First if Shape or Ordering Differs

Many comparison bugs come from comparing frames that are logically the same table but are ordered differently. Before comparing, sort or align them on stable keys.

python
1import pandas as pd
2
3df1 = pd.DataFrame({"id": [2, 1], "value": [20, 10]}).sort_values("id").reset_index(drop=True)
4df2 = pd.DataFrame({"id": [1, 2], "value": [10, 25]}).sort_values("id").reset_index(drop=True)
5
6print(df1.compare(df2))

Without alignment, you may report differences that are really just row-order differences.

Find Added or Removed Rows With merge

If you want to know which rows appear in one DataFrame but not the other, use an outer merge with the indicator column.

python
1import pandas as pd
2
3left = pd.DataFrame({"id": [1, 2, 3], "value": [10, 20, 30]})
4right = pd.DataFrame({"id": [2, 3, 4], "value": [20, 35, 40]})
5
6merged = left.merge(right, how="outer", indicator=True)
7print(merged)

The _merge column tells you whether each row came from:

  • 'left_only'
  • 'right_only'
  • 'both'

This is often the right answer when the task is really about row presence rather than cell-by-cell changes.

Compare Specific Columns or Keys When Full Equality Is Too Strict

Sometimes only a subset of columns matters. In that case, reduce the DataFrames before comparison.

python
important1 = df1[["id", "value"]]
important2 = df2[["id", "value"]]
print(important1.compare(important2))

This keeps the comparison tied to the business rule instead of accidentally treating metadata columns as important changes.

Missing Values Need Intentional Handling

NaN handling can affect the result. Depending on the method and the shape of the inputs, missing values may be treated as equal in some contexts and as differences in others.

If missing values have a business meaning, normalize them before comparison.

python
df1 = df1.fillna("MISSING")
df2 = df2.fillna("MISSING")

Do not let null semantics remain implicit if the comparison result will drive data validation or alerts.

Common Pitfalls

The most common mistake is comparing two DataFrames without first aligning them by key and order.

Another mistake is using equals() when the real requirement is to identify which cells or rows changed.

A third issue is comparing whole tables when only a subset of columns matters to the business logic.

Finally, missing values, duplicate keys, and row-order differences can all make a naive comparison look more dramatic than the actual data change.

Summary

  • Use equals() for a strict yes-or-no equality check.
  • Use compare() when the shape matches and you want changed cell values.
  • Align or sort by stable keys before comparing.
  • Use outer merge(..., indicator=True) to find added or removed rows.
  • Limit the comparison to relevant columns when full-table equality is too strict.
  • Define how missing values should be treated before trusting the diff.

Course illustration
Course illustration

All Rights Reserved.