CodeRigor

LESSON

Merge with cardinality checks and unmatched evidence

Reject duplicate/missing keys before a many-to-one left merge and retain an explicit match indicator.

A join can multiply rows when the right key is not unique. That can inflate totals even if the final chart looks reasonable. Validate the expected many-to-one relationship before treating the joined result as an enriched report.

Our left sales table keeps unmatched customers and records _match. Missing join keys are rejected on both sides because Pandas can match nulls to nulls, unlike the usual SQL null comparison. The application’s policy must be explicit at this boundary.

Merge with cardinality checks and unmatched evidence
start / 3
Reject duplicate/missing keys before a many-to-one left merge and retain an explicit match indicator.
Merge with cardinality checks and unmatched evidence
Reject duplicate/missing keys before a many-to-one left merge and retain an explicit match indicator.

A left merge preserves every input observation, while an inner merge would discard unmatched customers. validate=many_to_one checks right-key uniqueness; indicator records whether each row matched. Neither setting replaces key validation or the report’s separate first-valid duplicate policy.

The general merge helper rejects duplicate right keys. The capstone first applies its established customer deduplication policy, then supplies a unique lookup to this helper. That sequence avoids silently choosing an arbitrary duplicate during enrichment.

Python
import pandas as pd
left=pd.DataFrame({"id":["001","missing"]})
right=pd.DataFrame({"id":["001"],"name":["NA"]})
joined=left.merge(right,on="id",how="left",validate="many_to_one",indicator=True)
print(joined["_merge"].astype(str).tolist())
print(joined["name"].isna().tolist())

The _match indicator is evidence, not a replacement for the actual customer name. A name literally equal to NA is valid text, so default missing-token inference would corrupt the lookup. Actual pd.NA marks an unmatched result here.

The tests use a nondefault left index and repeated left customer keys. The output must preserve left row order and count while allowing many sales to share one unique customer. A duplicate right key is refused before it can inflate revenue.

Keep the interpretation visible
start / 3
Column representation, accepted business policy and independent report checks are separate decisions.
Keep the interpretation visible
Column representation, accepted business policy and independent report checks are separate decisions.
Python
import pandas as pd
left=pd.DataFrame({"key":[None]})
right=pd.DataFrame({"key":[None],"value":[7]})
print(len(left.merge(right,on="key")))
print("this application rejects missing keys before merging")

Implement the many-to-one left merge and inspect unmatched rows. Reject null and duplicate keys explicitly. Next reconcile the complete DataFrame audit against the existing records algorithm.

Actual Pandas 2.3.3 · Independent records comparison

Follow the same observations through each operation.

These tables were computed from the supplied fixture. Choose a step to inspect actual values and row counts. Full report parity includes accepted rows, rejection reasons, unmatched source positions and every summary field.

11source records
5accepted rows
6rejected rows
1unmatched accepted
Raw CSV · 11 rows

Eleven raw records retain text IDs, literal NA and empty amounts before business validation.

Raw CSV · actual fixture values; null is labelled missing and empty text stays distinct
sale_idcustomer_iddateamount
s0010012025-01-01$0.29
s0020022025-01-02$0
s003missing2025-01-03-$1.25
s0010012025-01-01$0.29
s0010012025-01-01$0.30
s004"" · empty text2025-01-04$4
s005NA2025-01-05$2
s0060012025-02-30$1
s0070012025-01-07$1,234.50
s0080012025-01-08bad
s0090012025-01-09"" · empty text
Accepted lesson-frame dtypessale_id · stringcustomer_id · stringdate · stringcents · Int64
Download the data, independent baseline, Pandas implementation and checks →

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →