Skip to contents

The pipeline is driven by two kinds of reference data: crosswalks (curated lookup tables shipped as package data) and word lists (character vectors shipped as package data used by the regex-based cleaning steps).

Crosswalks

The four crosswalks are package data (title.xwalk, title.patterns, title.taxonomy, status.codes). Their source is the CSV tables in data-raw/crosswalks/ of the source repository: edit a table, then run data-raw/crosswalks/build-crosswalks.R to rebuild the package data. (Until October 2026 the crosswalks were kept in a Google Sheet; it is retired, and an export of every tab is archived in data-raw/crosswalks/archive/.)

Title standardization (get_title_xwalk())

Maps every observed title variant to a canonical title.standard, plus a strata / strata.label for board sub-roles. Used in step 07, standardize_titles().

xwalk <- get_title_xwalk()
dim(xwalk)
#> [1] 9181    4
head(xwalk, 8)
#>                title.variant title.standard strata strata.label
#> 1                                  NO TITLE                    
#> 2               AAA DIRECTOR       DIRECTOR                    
#> 3 AAC ATHLETE REPRESENTATIVE   BOARD MEMBER                    
#> 4              AAFP DELEGATE   BOARD MEMBER                    
#> 5               AAJ DELEGATE   BOARD MEMBER                    
#> 6               AAJ GOVERNOR   BOARD MEMBER                    
#> 7              AAJ PRESIDENT   BOARD MEMBER                    
#> 8            AAMD LEADERSHIP   BOARD MEMBER

Title patterns (get_title_patterns())

Head rules for titles the standardization crosswalk does not list: a title whose longest known prefix or suffix has a rule maps to that rule’s title.standard (title.match is pattern). Each rule records its support (titles it was learned from) and precision. Used in step 07, standardize_titles().

pat <- get_title_patterns()
dim(pat)
#> [1] 121   6
head(pat, 6)
#>   position      head title.standard     rule support precision
#> 1   prefix    ACTIVE   BOARD MEMBER majority       6     0.833
#> 2   prefix  ADVISORY   BOARD MEMBER majority       8     1.000
#> 3   prefix AFFILIATE   BOARD MEMBER majority       5     1.000
#> 4   prefix     ALPHA   BOARD MEMBER majority      16     1.000
#> 5   prefix       ALT   BOARD MEMBER majority      11     1.000
#> 6   prefix ALTERNATE   BOARD MEMBER majority      16     0.875

Title taxonomy (get_title_taxonomy())

Maps each canonical title.standard to its taxonomy dimensions: functional domain.category / domain.label, the BLS SOC occupation codes, and its role. A title is either an employee level or a board role:

  • emp.level:
    • CEO: the top staff job.
    • OFFICER: C-suite, vice presidents, deputies.
    • MANAGER: directors of departments, managers.
    • PROFESSIONAL: non-managerial jobs often reported for their pay, such as physicians, lawyers, professors and coaches.
    • STAFF: everything else.
  • board.role: CHAIR, VICE CHAIR, SECRETARY, TREASURER or MEMBER.

The legacy flags (ceo, c.level, mgr, spec, board, pres, …) are derived from these two columns. dir.vp is retired. Used in step 08, categorize_titles().

tax <- get_title_taxonomy()
dim(tax)
#> [1] 450  22
head(tax[, c("title.standard", "domain.label", "soc.label",
             "emp.level", "board.role")], 8)
#>             title.standard     domain.label
#> 1               ACCOUNTANT          finance
#> 2      ACCOUNTING DIRECTOR          finance
#> 3                    ACTOR arts and history
#> 4                  ACTUARY          finance
#> 5  ADMINISTRATION DIRECTOR   administration
#> 6   ADMINISTRATION OFFICER   administration
#> 7 ADMINISTRATIVE ASSISTANT   administration
#> 8            ADMINISTRATOR   administration
#>                                   soc.label    emp.level board.role
#> 1                  Accountants and Auditors PROFESSIONAL           
#> 2                        Financial Managers      MANAGER           
#> 3                                    Actors PROFESSIONAL           
#> 4                                 Actuaries PROFESSIONAL           
#> 5          Administrative Services Managers      MANAGER           
#> 6                                                  STAFF           
#> 7 Secretaries and Administrative Assistants        STAFF           
#> 8          Administrative Services Managers      MANAGER
table(tax$emp.level)
#> 
#>                       CEO      MANAGER      OFFICER PROFESSIONAL        STAFF 
#>           15           11          129          139           40          116
table(tax$board.role)
#> 
#>                 CHAIR     MEMBER  SECRETARY  TREASURER VICE CHAIR 
#>        445          1          1          1          1          1

Status codes (get_status_codes())

Maps status-qualifier variants (e.g. ACTING, EMERITUS, INTERIM) to a standardized status.qualifier (e.g. INTERIM, FORMER). Used in step 06, gen_status_codes().

sc <- get_status_codes()
dim(sc)
#> [1] 294   2
head(sc, 8)
#>   status.variant status.qualifier
#> 1      AS NEEDED         AT LARGE
#> 2       AT LARGE         AT LARGE
#> 3       AT-LARGE         AT LARGE
#> 4          PROXY         AT LARGE
#> 5          AT LG         AT LARGE
#> 6        CURRENT          CURRENT
#> 7     EX OFFICIO        EXOFFICIO
#> 8     EX-OFFICIO        EXOFFICIO

Word lists (package data)

These character vectors are lazy-loaded package datasets used by the regex cleaning steps. Load any of them with data().

Dataset Used in Purpose
date.words remove_dates() (02) month/date tokens to detect and strip
number.words gen_status_codes() (06) number words removed from titles
likely.titles standardize_conj() (03) recognizable titles for split detection
likely.subjects fix_of() (05) subjects that follow “of” in a title
possible.titles fix_of() (05) candidate title tokens
former.words not used FORMER variants; superseded by status.codes
future.words not used FUTURE variants; superseded by status.codes
interim.words not used INTERIM variants; superseded by status.codes
regional.words not used REGIONAL variants; superseded by status.codes
possible.regional.list not used candidate regional tokens
data(number.words)
head(number.words, 12)
#>  [1] "ONE"    "TWO"    "THREE"  "FOUR"   "FIVE"   "SIX"    "SEVEN"  "EIGHT" 
#>  [9] "NINE"   "TEN"    "ELEVEN" "TWELVE"

data(likely.titles)
head(likely.titles, 12)
#>  [1] "PRESIDENT"   "CEO"         "DIRECTOR\\b" "CHAIR"       "TRUSTEE\\b" 
#>  [6] "TREASURER"   "SECRETARY"   "OFFICER"     "COUNSEL"     "FOUNDER"    
#> [11] "PUBLISHER"   "EDITOR\\b"

Demo data

Dataset Description
tinypartvii ~81k raw Part VII rows (10,000 orgs) in the modern schema, ready for standardize_df().
raw.titles A small vector of raw title strings for quick experiments.
data(tinypartvii)
str(tinypartvii[, 1:8], vec.len = 1)
#> 'data.frame':    81309 obs. of  8 variables:
#>  $ EIN2            : chr  "EIN-72-1424183" ...
#>  $ OBJECTID        : chr  "OID-202400189349300715" ...
#>  $ ORG_EIN         : chr  "721424183" ...
#>  $ ORG_NAME_L1     : chr  "MU TAU INC" ...
#>  $ ORG_NAME_L2     : chr  "" ...
#>  $ RETURN_AMENDED_X: chr  "FALSE" ...
#>  $ RETURN_GROUP_X  : chr  "FALSE" ...
#>  $ RETURN_PARTIAL_X: chr  "FALSE" ...