mudnester cleans, prepares, and aggregates surveillance data for public
health analysis. Named after the Corcoracidae (White-winged Chough), which
builds its mud nest in meticulous layers — reinforcing each layer before
adding the next. That is exactly how a mudnester pipeline works, and every
function in the package continues the bird theme; see ?mudnester for the
full story behind each name.
Built for Australian public health surveillance practice — Southern
Hemisphere seasons by default, ATAGI-aligned age bands, and jurisdictional
datasets like the Australian Immunisation Register and NNDSS in the
surrounding ecosystem — but nothing in the cleaning or aggregation logic
itself is Australia-specific. See ?roost and the "Worldwide use" note below
for what to change outside Australia.
It is part of the aviary ecosystem:
| Package | Role |
|---|---|
| mudnester | Data cleaning, aggregation & correction ← you are here |
| starling | Probabilistic & deterministic record linkage |
| bowerbird | Visualisation & dashboards |
| aviary | Meta-package (loads all three) |
# Install from GitHub:
# install.packages("pak")
pak::pak("nrsmoll/mudnester")
# Or from a local clone:
devtools::install("path/to/mudnester")
library(mudnester)
# 1. Standardise column names, parse dates, derive blocking variables
df_cases <- clean_the_nest(
cases_raw, data_type = "cases",
id_var = "identity", lettername1 = "first_name", lettername2 = "surname",
dob = "date_of_birth", onset_date = "date_of_onset", gender = "gender",
postcode = "postcode", medicare = "medicare_no"
)
# 2. Age categorisation — choose from ~50 named, referenced schemes
df_cases <- preening(df_cases, age_col = "age", scheme = "flucan_sentinel")
# 3. [optional] Comorbidity flags from ICD-10-AM U-codes and acute codes
df_cases <- plumage(df_cases, icd_column = "icd_codes")
# 4. Aggregate to a time unit with zero-filling -- the epicurve
cases_monthly <- roost(
df_cases, date_col = "onset_date", time_unit = "month",
group_cols = c("age_group", "diagnosis")
)
# 5. [optional] Trace the same cohort through several linked milestone
# dates (onset, admission, ICU, death) into one aligned table
severity_by_month <- flyway(
linked_cohort,
events = c(cases = "onset_date", hospitalisations = "admission_date",
deaths = "fatality_date"),
time_unit = "month"
)
# 6. [optional] Correct a roost()/flyway() count for under-ascertainment
corrected <- corncrake(cases_monthly, method = "ratio_estimate",
secondary_data = lab_positives, secondary_count_col = "n")
# 7. [optional] Vaccine coverage, including interrupted-time-series designs
coverage_ts <- brood(
linked_cohort, data_format = "wide", population_model = "cohort",
vax_date_cols = vax_date_cols, entry_date_col = "dob",
time_series = TRUE, ts_start = as.Date("2024-01-01"),
ts_end = as.Date("2026-06-01"), ts_by = "month"
)
# 8. De-identify before sharing
result <- molting(df_cases)
# Keep result$lookup secure and separate from result$deidentified
# 9. Relink when authorised
relinked <- homing(result$deidentified, result$lookup)
roost(): five ways to build an epicurveroost() is the aggregation engine behind almost everything on the surveillance
side of the ecosystem — anywhere you'd draw an epicurve, roost() is turning
line-list rows into the counts that curve is built from.
# 1. Yearly RSV case counts -- a straightforward epicurve
rsv_yearly <- roost(rsv_cases, date_col = "notification_date", time_unit = "year")
# 2. Influenza, 3 seasons, severity cascade via flyway()
influenza_by_season <- flyway(
influenza_linked_cohort,
events = c(cases = "onset_date", hospitalisations = "admission_date",
icu = "icu_date", deaths = "fatality_date"),
time_unit = "season"
)
influenza_by_season$chr_obs <-
influenza_by_season$n_hospitalisations / influenza_by_season$n_cases
# 3. RSV hospitalisations only, for an interrupted time series
rsv_hosp_monthly <- roost(rsv_infant_admissions, date_col = "admission_date",
time_unit = "month", group_cols = "era")
# 4. Total measles vaccine doses delivered during a rollout
measles_doses_weekly <- roost(measles_vax_records, date_col = "vax_date",
time_unit = "isoweek")
# 5. Disease X, multiple time units and age bands via preening()
disease_x_cases <- preening(disease_x_cases, age_col = "age_years",
scheme = "atagi_covid19_2025")
disease_x_monthly_by_age <- roost(disease_x_cases, date_col = "onset_date",
time_unit = "month", group_cols = "age_group")
See ?roost for the full walkthrough of each, including what flyway() returns
and how to feed a roost_tbl into corncrake() for under-ascertainment
correction.
| Function | Purpose |
|---|---|
clean_the_nest() |
Standardise cases, hospital, vaccination, and generic cohort datasets for linkage |
preening() |
Age categorisation against ~50 named schemes (ABS, ATAGI, WHO, FluCAN…) |
list_age_schemes() |
Browse the age scheme catalogue with family, focus, max_bands filters |
plumage() |
Chronic comorbidity flags from ICD-10-AM U-codes, acute admission codes, and AR-DRG |
roost() |
Build an epicurve: aggregate records by day / ISO week / fortnight / month / quarter / year / season |
flyway() |
Aggregate several linked milestone dates (onset, admission, ICU, death) into one table |
corncrake() |
Correct a surveillance count for under-ascertainment (user-supplied, ratio-estimate, or severity-anchor methods) |
brood() |
Vaccine coverage data, including cohort and interrupted-time-series designs |
molting() |
De-identify with hash-based lookup for relinking |
homing() |
Relink de-identified data back to original identifiers |
vignette("mudnester-getting-started") # full end-to-end pipeline
vignette("clean-the-nest") # all data types, birth-cohort pattern
vignette("preening") # age scheme selection and filtering
vignette("age-schemes") # full catalogue with citations
vignette("plumage") # comorbidity detection, dual-code rationale
vignette("roost") # all time units, zero-filling, seasons
vignette("flyway") # multi-milestone aggregation, severity cascades
vignette("corncrake") # under-ascertainment correction, all three methods
vignette("brood") # vaccine coverage, cohort & interrupted-time-series designs
vignette("molting") # de-identification and security guidance
vignette("homing") # relink workflow and governance checklist
citation("mudnester")
Smoll N (2026). mudnester: Surveillance Data Cleaning and Preparation for Public Health. R package version 0.7.2. https://github.com/nrsmoll/mudnester
Development of this package was supported by the Moderna Global Research Fellowship.
MIT © 2026 Nicolas Smoll, Sunshine Coast Hospital and Health Service