Skip to contents

End-to-end stage-1 + stage-2 cross-org linkage over a panel that already carries within-org EMP_IDs (link_panel()): build one profile per person, generate candidate pairs by hash blocking, score them from the variant sets, link pairs at or above threshold, and resolve the accepted edges into cross-organization person clusters (XORG_ID) under the one-person-per-org invariant.

Usage

link_cross_org(
  df,
  cols = synthid_cols(),
  state = NULL,
  ntee = NULL,
  passes = names(blocking_passes()),
  weights = default_weights(),
  threshold = 7,
  max_block_size = 5000L,
  verbose = FALSE
)

Arguments

df

A linked panel (output of link_panel()).

cols

Column mapping; see synthid_cols().

state, ntee

Optional organization geography / NTEE columns for the tighter blocking passes (join from the BMF beforehand). NULL -> those passes emit nothing and linkage falls back to the surname pass.

passes

Blocking passes to run; see blocking_passes().

weights

Base match weights; see default_weights().

threshold

Minimum score to accept a cross-org edge (default 7, the within-org default; needs its own tuning – the score scale differs, as title/salutation are dropped and surname rarity is population-based).

max_block_size

Oversize-bucket guard for candidate_pairs().

verbose

Print stage sizes.

Value

A list: profiles and assignment both carry the cross-org rollups XORG_ID, XORG_N_ORGS, XORG_N_TITLES, XORG_N_YEARS (distinct calendar years), XORG_N_RECORDS (total filing rows); edges (all scored candidate pairs); and report (counts, including edges rejected by the org guard). Stamp the assignment back onto the panel with stamp_xorg() to recover each person's full title history.

Examples

if (FALSE) { # \dontrun{
linked <- link_panel(panel)
xo <- link_cross_org(linked, state = "state", ntee = "ntee", threshold = 8)
subset(xo$profiles, XORG_N_ORGS > 1)          # people who interlock
subset(xo$edges, score >= 8 & is_board_a & is_board_b)  # board-board interlocks
} # }