Skip to contents

Collapses every record of a within-organization person (all rows sharing an EMP_ID, as stamped by link_panel()) into one structured profile row for cross-organization linkage. Deliberately does not flatten the cluster to a single canonical name string: the variant sets are what carry a person from one organization's filing to another's (a maiden/married surname, an OCR variant, a nickname), so each name field keeps both a deterministic canonical value (for display and as a primary blocking key) and the full set of observed variants (for blocking recall and pairwise scoring).

Usage

build_person_profile(
  df,
  cols = synthid_cols(),
  emp_id = "EMP_ID",
  title = "title.standard",
  state = NULL,
  ntee = NULL,
  overrides = NULL
)

Arguments

df

A linked panel: the output of link_panel() (or any frame carrying EMP_ID plus parsed name components). Multiple rows per EMP_ID.

cols

Column mapping; see synthid_cols(). Uses org_id, year, name, and the name-component features (first_name, middle_name, last_name, suffix, gender).

emp_id

Name of the person-cluster id column (default "EMP_ID").

title

Name of the standardized-title column, classified into a coarse role via classify_title_role() (default "title.standard"; skipped if absent).

state, ntee

Optional column names for organization geography and NTEE industry. When present they are carried into the profile as variant sets and are available as relaxable blocking dimensions; when NULL or absent they are skipped (join them from the BMF beforehand if you want them).

overrides

Passed to classify_title_role() for title tail cases.

Value

A data frame, one row per EMP_ID, with scalar summary columns and list-columns for the variant sets:

EMP_ID, n_records, n_orgs, n_years, first_year, last_year

Cluster size and span.

last_name, last_name_variants, last_name_keys

Modal surname; the distinct surnames observed; their phonetic (Soundex) blocking keys.

first_name, first_name_variants, first_name_roots, first_initial

Most-complete formal given name; distinct given names; their canonical nickname roots (first_name_roots()); leading initial.

middle_initials, suffixes, gender

Union of middle initials and suffixes; modal gender (NA on tie/unknown).

name_variants

Distinct full-name strings seen for the person.

primary_role, roles, is_board

Modal coarse role; the role set; whether the person ever held a BOARD seat.

titles, orgs, years

Distinct standardized titles, organization ids, and tax years for the person.

states, ntee

Present only when state/ntee are supplied.

List-columns hold one character vector per person; unnest last_name_keys (with EMP_ID) to get the long key table for the stage-1 hash join.

Details

The profile is the unit compared in the cross-org stage. Stage 1 (candidate generation) is a hash/inverted-index lookup on blocking keys rather than a materialized within-block cross product: a profile emits one key per surname variant (last_name_keys, phonetic), lands in every matching bucket, and only profiles sharing a bucket are scored – so maiden/married/OCR variants are not silently dropped, and a common surname never materializes an all-pairs block.

Examples

if (FALSE) { # \dontrun{
linked <- link_panel(panel)
profiles <- build_person_profile(linked)
# long blocking-key table for the cross-org hash join:
keys <- do.call(rbind, Map(function(id, k) data.frame(EMP_ID = id, key = k),
                           profiles$EMP_ID, profiles$last_name_keys))
} # }