merge() matches rows between two DataFrames based on the on column(s), or on left_on/right_on if the key columns have different names in each DataFrame, and the how parameter controls which rows survive when a key doesn't match on both sides: 'inner', the default, keeps only rows with a match in both, 'left'/'right' keep all rows from one side and fill unmatched columns from the other with NaN, and 'outer' keeps every row from both sides. Choosing the wrong how is one of the most common sources of unexpectedly missing or duplicated rows in real-world pandas code.
1Understanding pd.merge()
merge() matches rows between two DataFrames based on the on column(s), or on left_on/right_on if the key columns have different names in each DataFrame, and the how parameter controls which rows survive when a key doesn't match on both sides: 'inner', the default, keeps only rows with a match in both, 'left'/'right' keep all rows from one side and fill unmatched columns from the other with NaN, and 'outer' keeps every row from both sides. Choosing the wrong how is one of the most common sources of unexpectedly missing or duplicated rows in real-world pandas code.
Always double-check row counts before and after a merge() — an unexpected row-count increase usually means the key column has duplicate values on one side, causing each match to produce multiple output rows, a many-to-many join, which is a very common, easy-to-miss bug.
import pandas as pd
customers = pd.DataFrame({"id": [1, 2], "name": ["Alice", "Bob"]})
orders = pd.DataFrame({"customer_id": [1, 1, 2], "total": [50, 30, 20]})
merged = pd.merge(customers, orders, left_on="id", right_on="customer_id")
print(merged)2Practical Example
Here is a real-world application of pd.merge() showing how it is used in production Pandas code.
import pandas as pd
a = pd.DataFrame({"id": [1, 2, 3], "val": ["a", "b", "c"]})
b = pd.DataFrame({"id": [2, 3, 4], "val2": ["x", "y", "z"]})
print(pd.merge(a, b, on="id", how="outer"))3Best Practices
Follow these guidelines when working with pd.merge():
1. Choose how deliberately based on what should happen to unmatched keys, rather than relying on the default 'inner' without thinking it through
2. Check the row count before and after a merge, since an unexpected increase usually signals duplicate keys causing a many-to-many join
3. Use left_on/right_on when the key columns have different names in each DataFrame, instead of renaming a column just to make on work
Tip: Always double-check row counts before and after a merge() — an unexpected row-count increase usually means the key column has duplicate values on one side, causing each match to produce multiple output rows, a many-to-many join, which is a very common, easy-to-miss bug.
import pandas as pd
customers = pd.DataFrame({"id": [1, 2], "name": ["Alice", "Bob"]})
orders = pd.DataFrame({"customer_id": [1, 1, 2], "total": [50, 30, 20]})
merged = pd.merge(customers, orders, left_on="id", right_on="customer_id")
print(merged)