(*)> mudnester

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)

Installation

# Install from GitHub:
# install.packages("pak")
pak::pak("nrsmoll/mudnester")

# Or from a local clone:
devtools::install("path/to/mudnester")

The pipeline

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 epicurve

roost() 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.


Functions

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

Vignettes

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

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


Funding

Development of this package was supported by the Moderna Global Research Fellowship.


Licence

MIT © 2026 Nicolas Smoll, Sunshine Coast Hospital and Health Service