homing()homing() is the complement to molting(). It
is used when:
The name is precise: homing pigeons navigate back to their loft
regardless of where they were released, using an internal compass that
only they carry. homing() navigates a de-identified dataset
back to its identifiers using the lookup table — and only those who hold
the lookup table can make that journey.
# Construct sample data
patient_data <- data.frame(
patient_name = c("John Doe", "Jane Smith", "Alice Brown"),
dob = as.Date(c("1980-01-01", "1975-05-15", "1992-11-30")),
mrn = c("12345", "67890", "11111"),
diagnosis = c("Condition A", "Condition B", "Condition C"),
severity = c("mild", "moderate", "severe")
)
# Step 1: de-identify (typically done at data collection / storage time)
result <- suppressMessages(molting(patient_data))
# Step 2: share or archive result$deidentified
# store result$lookup securely, separately
# Step 3: relink when authorised
relinked <- homing(
deidentified_data = result$deidentified,
lookup_table = result$lookup
)
head(relinked)
#> # A tibble: 3 × 6
#> row_hash diagnosis severity patient_name dob mrn
#> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 89573bbf928ef324ba95e8d04fd1701df… Conditio… mild John Doe 1980… 12345
#> 2 7b2536bf2d008eb3555f9404d1762dcc5… Conditio… moderate Jane Smith 1975… 67890
#> 3 a650dec662587da298bd3da47a7dcea69… Conditio… severe Alice Brown 1992… 11111
The original identifiers (patient_name,
dob, mrn) are joined back in via the
row_hash column.
If molting() was called with a custom
hash_col_name, pass the same name to
homing().
result_custom <- suppressMessages(
molting(patient_data, hash_col_name = "person_hash")
)
relinked_custom <- homing(
result_custom$deidentified,
result_custom$lookup,
hash_col_name = "person_hash"
)
"patient_name" %in% names(relinked_custom)
#> [1] TRUE
If you want a clean re-identified dataset without the hash column:
relinked_clean <- homing(
result$deidentified,
result$lookup,
keep_hash = FALSE
)
names(relinked_clean) # no row_hash column
#> [1] "diagnosis" "severity" "patient_name" "dob" "mrn"
If the lookup table is incomplete (e.g. some records were excluded
from the lookup for a legitimate reason, or the wrong lookup was
supplied), homing() warns you about unmatched rows and
returns them with NA in the identifier columns rather than
silently dropping them.
# Simulate a truncated lookup — only the first two rows
partial_lookup <- result$lookup[1:2, ]
relinked_partial <- homing(
result$deidentified,
partial_lookup
)
# Third row has NA identifiers
relinked_partial[, c("row_hash","patient_name","diagnosis")]
#> # A tibble: 3 × 3
#> row_hash patient_name diagnosis
#> <chr> <chr> <chr>
#> 1 89573bbf928ef324ba95e8d04fd1701dfc5c15265ab21b3dbbb267… John Doe Conditio…
#> 2 7b2536bf2d008eb3555f9404d1762dcc529e1a7d5e6880c66341e8… Jane Smith Conditio…
#> 3 a650dec662587da298bd3da47a7dcea697e493e4feb35aeccc38c8… <NA> Conditio…
Always check the summary message for the matched count. A significantly lower matched count than expected usually means the wrong lookup was supplied.
Before using homing() in a production workflow,
ensure:
In Queensland Health, re-identification for notifiable disease follow-up typically falls under Public Health Act 2005 obligations and does not require separate ethics approval, but document the basis for re-identification in your outbreak log.
After re-identification, the data is again fully identifiable. If you
need to re-anonymise for a secondary analysis, run
molting() again. See vignette("molting") for
options.
If the purpose of the relink was to add clinical follow-up data, the
updated dataset can be re-cleaned with clean_the_nest()
before further analysis.