SporeLag

R-CMD-check Codecov test coverage DOI

Deterministic, group-safe utilities that turn daily environmental exposure series — pollen and spore counts, and other time-varying exposures such as ozone or particulate matter — into analysis-ready lagged and moving-average features for environmental epidemiology.

Why

Building a lagged exposure looks like a one-liner. It isn’t, because daily surveillance data has two different defects that are easy to conflate:

is.na() cannot see a gap. And a lag computed by row position on a gapped series is a lag by position, not by time: a “1-day lag” silently becomes however many days happen to separate two adjacent rows. The resulting exposure column looks plausible, runs cleanly through a regression, and yields a misaligned lag–response estimate that nothing downstream will flag.

SporeLag makes that failure impossible: the temporal functions refuse to operate on a gapped grid.

Installation

# install.packages("remotes")
remotes::install_github("friveramariani/SporeLag")

Usage

library(SporeLag)

model_ready <- pollen_demo |>
  complete_daily_grid(date = "date", by = "site") |>   # close gaps in TIME
  assign_iso_week(date = "date") |>                    # iso_year + iso_week
  assign_season(date = "date") |>                      # season label
  impute_weekly_mean(value = "count", by = "site") |>  # fill NAs, flag them
  build_moving_average(value = "count_imputed", window = c(3, 7),
                       date = "date", by = "site") |>
  apply_lag(value = "count_imputed", lags = 0:3,
            date = "date", by = "site")

names(model_ready)
#>  [1] "site"               "date"               "count"             
#>  [4] "iso_week"           "iso_year"           "season"            
#>  [7] "count_imputed"      "count_imputed_flag" "count_imputed_ma3" 
#> [10] "count_imputed_ma7"  "count_imputed_lag0" "count_imputed_lag1"
#> [13] "count_imputed_lag2" "count_imputed_lag3"

complete_daily_grid() must come first, or the last two steps error. The pipeline enforces its own correctness.

Functions

Function Purpose Appends
complete_daily_grid() insert rows for absent calendar days rows, not columns
assign_iso_week() ISO 8601 week and year iso_week, iso_year
assign_season() configurable season label season
impute_weekly_mean() fill NAs with the ISO-week mean {value}_imputed, {value}_imputed_flag
build_moving_average() trailing windowed mean {value}_ma{k}
apply_lag() time-indexed lags {value}_lag{n}

Design principles

Scope

SporeLag builds exposure variables. It does not fit models, merge outcomes, or define aeroallergen or pollutant seasons for you — those are analytic decisions that belong to you, not to a preprocessing package.

Acknowledgements

SporeLag is developed in collaboration with Dr. Benjamín Bolaños-Rosero, director of the San Juan and Caguas, Puerto Rico, aeroallergen monitoring stations — both certified by the National Allergy Bureau (NAB). His expertise in aeroallergen surveillance and access to longitudinal Puerto Rico pollen and spore count data have directly informed the package’s design priorities: complete-grid enforcement, group-safe operations, and explicit, auditable exposure-feature construction.

Learn more

vignette("getting-started", package = "SporeLag") walks through the pipeline and, more importantly, through the ways it can go wrong.