flock: Create Blocking Variables for Probabilistic Record Linkage

View source: R/flock.R

flockR Documentation

Create Blocking Variables for Probabilistic Record Linkage

Description

**Bird note**: Before a murmuration forms, starlings first gather into loose flocks — smaller, manageable sub-groups that share a roost site or feeding ground. flock() plays that preparatory role: it partitions records into candidate sub-groups (blocks) so that murmuration() only compares records within the same block, rather than every record against every other. Good blocking dramatically reduces computation without sacrificing linkage quality, provided the blocking variable is near-complete and consistent across both datasets.

Generates one or more blocking variables from demographic fields already standardised by clean_the_nest(). Blocking variables partition the record space so that murmuration() only compares candidate pairs within the same block. Three strategies are offered:

  • Single field — use one column directly (e.g. "gender", "postcode").

  • Phonetic — Soundex or Double Metaphone encoding of a name field, so that near-spelling-variants of the same name block together.

  • Composite — concatenation of two or more fields into one blocking key (e.g. first letter of lettername2 + birth year).

All three strategies can be generated in a single flock() call and appended as new columns to the data frame, ready to pass to murmuration()'s blocking_var argument.

Usage

flock(
  data,
  block1_vars = NULL,
  block2_vars = NULL,
  block3_vars = NULL,
  phonetic_vars = NULL,
  phonetic_method = "soundex",
  birth_year_col = NULL,
  postcode_col = NULL
)

Arguments

data

A data frame that has been processed by clean_the_nest(). Must contain the columns referenced by block1_vars / block2_vars / block3_vars.

block1_vars

Character vector of one or more column names to combine into the primary blocking variable (block1). Single element = direct use of that column. Multiple elements = concatenated composite key.

block2_vars

Optional character vector for a second blocking variable (block2). Use a second, independent variable to allow murmuration() to be run twice with different blocks and results merged — the standard multi-pass blocking strategy to improve recall. NULL (default) suppresses block2.

block3_vars

Optional character vector for a third blocking variable (block3). NULL (default) suppresses block3.

phonetic_vars

Optional character vector of name columns to encode phonetically. Each column x generates a new column x_soundex. These can then be referenced in block1_vars / block2_vars / block3_vars. Requires the phonics package.

phonetic_method

One of "soundex" (default) or "metaphone". Applied to all columns in phonetic_vars.

birth_year_col

Optional name of a Date column from which birth year is extracted. If supplied, a birth_year integer column is added, which can be referenced in composite blocking keys.

postcode_col

Optional name of a postcode column. If supplied, the first 3 digits are extracted as postcode3 (broad geographic blocking).

Details

## Blocking strategy guidance

The goal of blocking is to be broad enough to keep true matches in the same block, and narrow enough to avoid exploding the number of candidate pairs. Practical guidance for Australian surveillance linkage:

Block Recommended variable Notes
Primary "gender" Near-universal; halves the candidate space immediately
Secondary "postcode" or "postcode3" Good geographic signal; use postcode3 if postcode completeness is low
Tertiary Soundex of lettername2 Catches surname spelling variants; do not use as the sole block

Multi-pass blocking (running murmuration() separately with block1 and block2 then unioning results) substantially improves recall at modest computational cost. This is the recommended approach for large datasets (> 100 000 records in either dataset).

## Why not block on Medicare number?

Medicare number is an excellent comparison variable but a poor blocking variable: missing or transcription-error values will split a true pair across blocks, causing them to never be compared. Use Medicare as a compare_var in murmuration(), and as a component of a composite block only when completeness is verified (e.g. > 95% non-missing in both datasets).

Value

The input data frame with new columns appended:

block1

Primary blocking key (always present).

block2

Secondary blocking key (if block2_vars supplied).

block3

Tertiary blocking key (if block3_vars supplied).

<col>_soundex or <col>_metaphone

Phonetic encoding columns (if phonetic_vars supplied).

birth_year

Integer birth year (if birth_year_col supplied).

postcode3

First 3 digits of postcode (if postcode_col supplied).

Original columns are always preserved.

See Also

murmuration, mudnester::clean_the_nest()

Examples

## Not run: 
# Single-field primary block (gender) + postcode secondary block
cases_blocked <- flock(cases_clean,
  block1_vars = "gender",
  block2_vars = "postcode")

# Composite primary block: first letter of surname + gender
cases_blocked <- flock(cases_clean,
  block1_vars  = c("lettername2_initial", "gender"),
  block2_vars  = "gender",
  phonetic_vars = "lettername2")

# Full three-pass setup
cases_blocked <- flock(cases_clean,
  block1_vars   = "gender",
  block2_vars   = "postcode3",
  block3_vars   = "birth_year",
  phonetic_vars = "lettername2",
  birth_year_col = "dob",
  postcode_col  = "postcode")

# Then pass to murmuration() separately for each block:
linked1 <- murmuration(cases_blocked, vax_blocked,
  blocking_var = "block1", ...)
linked2 <- murmuration(cases_blocked, vax_blocked,
  blocking_var = "block2", ...)
linked_all <- dplyr::bind_rows(linked1, linked2) |>
  dplyr::distinct(id_var.x, .keep_all = TRUE)

## End(Not run)


starling documentation built on July 10, 2026, 9:07 a.m.