Iterative Workloads
Reminder
In the Record Linkage tutorial you found out that Liken creates a canonical_id. By default this canonical_id is an autoincrementing numeric identifier starting from zero.
In this chapter we explore the configuring needed to canonicalize a dataset iteratively. By iteratively we mean appending to the same dataset — for example a dataset of customers that is appended to with new customers in a given time interval.
!!! note Here we explore the implications for batch workloads, especially for datasets that tend to append data
Canonical IDs
A new canonical ID every time we instantiate a Dedupe class isn't going to be practical for our use case. In fact, given our use case, we're likely to already have a canonical ID (literally an Liken canonical_id, or another). So we should use that instead and pass it in as a string identifier to the id argument of the canonicalize function. See the tutorial for a recap.
The Problem
Preparing an existing canonical_id column for an append is your job, not Liken's: new records need identifiers that continue the existing numbering before they are stacked onto the canonicalized dataset. Liken provides the preprocessors and dedupers; the identifier bookkeeping below is the part you carry out yourself. The suggested steps to take are:
- Add a column,
canonical_id, to the append dataset that continues the existing numbering: if the existing dataset holdsNrows (ids0toN-1), thenappended rows get idsNtoN + n - 1. - Append ("stack") your datasets.
- Instantiate
Dedupeand passid="canonical_id"to the canonicalizer.
!!! warning This process is going to be a lot easier with numeric ids. It's possible to use string identifiers but it makes the process of incrementing on append datasets much harder to manage and reason about
The Append Flow, Worked
Say your canonicalized customers currently hold ids 0 and 1, and an append batch carries two new records with pre-assigned ids 2 and 3 — one of which is a case-variant of an existing customer:
| canonical_id | name |
|---|---|
| 0 | Alice Wong |
| 1 | Bob Lane |
| 2 | alice wong |
| 3 | Carol Fox |
Existing records (ids 0–1) stacked with the append batch (ids 2–3).
Canonicalize the stacked frame with id="canonical_id":
import liken as lk
pipeline = lk.pipeline().step(
lk.col("name", preprocessors=[lk.preprocessors.lower()]).fuzzy(threshold=0.7)
)
df = lk.dedupe(stacked).apply(pipeline).canonicalize(id="canonical_id", keep="first")
| canonical_id | name |
|---|---|
| 0 | Alice Wong |
| 1 | Bob Lane |
| 0 | alice wong |
| 3 | Carol Fox |
The new duplicate inherited the existing id 0 — the group keeps its established identity.
Because keep="first" picks the earliest record of the group, the new record joins the existing id rather than the other way around. Later appends that duplicate other members of the group likewise collapse onto id 0. The dataset keeps one continuous identifier space across runs.
Decision Tree
flowchart TD
df{{"`DataFrame already has a **canonical_id**?`"}}
id1{{"`**id** defined in canonicalize()?`"}}
id2{{"`DataFrame carries an **id** column to use?`"}}
idiscanonical{{"`**id** is the same as **canonical_id**?`"}}
autoincrement("`Create a new autoincrementing **canonical_id**`")
copy("`Copy **id** to create **canonical_id**`")
overwrite("`Copy **id** to overwrite **canonical_id**`")
existing("`Use existing **canonical_id**`")
df-- yes -->id1
df-- no -->id2
id1-- no -->existing
id1-- yes -->idiscanonical
idiscanonical-- yes -->existing
idiscanonical-- no -->overwrite
id2-- no -->autoincrement
id2-- yes -->copy