Flag questionable cross-year person links for review
flag_links.RdScores every multi-record person cluster produced by link_panel() on how
consistent its member records are from year to year, and sorts each flagged
cluster into one primary explanation. The intent is triage: separate the small
set of genuinely questionable links (same surname, materially different given
name, or a near-miss surname that may be two different people) from the large
set whose apparent disagreement has a benign, mechanical cause (a nickname, a
maiden/compound surname, a field-order swap, or an upstream parser artifact).
Usage
flag_links(
df,
emp_id = "EMP_ID",
org_id = "ein",
org_name = "org.name",
year = "taxyr",
raw_name = "name.raw",
first = "first_name",
last = "last_name",
divergence_lv = 0.15,
divergence_jw = 0.15,
last_sim_floor = 0.85,
first_sim_floor = 0.85,
hon = honorific_tokens(),
cred = credential_tokens()
)Arguments
- df
A linked panel: the output of
link_panel()(or any frame carrying the person id, org, year, raw name, and parsed given/surname columns).- emp_id, org_id, org_name, year
Column names for the cross-year person id, organization id, organization name, and tax year.
- raw_name, first, last
Column names for the raw (pre-parse) name string and the parsed given and surname components.
- divergence_lv, divergence_jw
Raw-name divergence thresholds above which a cluster is flagged (normalised Levenshtein and Jaro-Winkler distance).
- last_sim_floor, first_sim_floor
Similarity floors (via compare_last_names/compare_first_names) at or above which surnames or given names are treated as agreeing when assigning a category.
- hon, cred
Token sets for honorific-glue and credential detection; see
honorific_tokens()andcredential_tokens().
Value
A data frame with one row per multi-record person, class
"synthid_link_flags", ordered with the review queue first. Key columns:
category, review_flag, review_score, the per-criterion flags
(flag_first_disagree, flag_last_disagree, flag_name_divergence), the
agreement metrics (last_sim, first_sim, name_lv_norm, name_jw), and
the distinct values seen (names_seen, first_seen, last_seen). A summary
(thresholds, person and flag counts, category tally) is attached as the
"synthid_flags" attribute.
Details
A cluster is flagged when any of three criteria trip: the parsed first names
disagree, the parsed last names disagree, or the raw name strings diverge
beyond divergence_lv (normalised Levenshtein) or divergence_jw
(Jaro-Winkler). Every flagged cluster is then assigned, in priority order, to
the first matching category:
order_swaptwo raw names share the same tokens in different order (e.g.
"SMITH BRAD"vs"BRAD SMITH") – a correct link.parser_honorific_gluea honorific is fused onto the given name (
"MRWILLIAM") or a single letter onto the surname ("WSMITH") – a correct link exposing an upstream parser defect (seeparse_fail_log()).surname_credentialpost-nominal credentials leaked into the surname (
"MCNEIL"vs"RM RDMS RVT CRA MCNEIL") – also a parser defect.surname_compoundthe surnames reconcile as a maiden/hyphenated or reordered compound (
compare_last_names\(\ge\)last_sim_floor).nickname_or_spellingsurnames agree and the given names agree as a nickname, initial, or minor spelling variant (compare_first_names \(\ge\)
first_sim_floor) – a correct link.reviewresidual: nothing benign explains the divergence. This is the human queue; see
link_review_queue().
See also
link_review_queue() for the residual queue, parse_fail_log() for
the parser-defect handoff.
Examples
if (FALSE) { # \dontrun{
linked <- link_panel(panel)
flags <- flag_links(linked)
table(flags$category)
review <- link_review_queue(flags)
} # }