Spatial Epidemiology Fundamentals & Data Standards
Production spatial epidemiology fails not at the statistics but at the data layer — an undefined datum, a silently truncated attribute, or a census-tract revision that manufactures a “cluster” out of a denominator change. This section establishes the engineering standards a Python/GIS surveillance pipeline must enforce so that every case rate, exposure surface, and cluster declaration it emits is reproducible, privacy-compliant, and defensible under regulatory audit.
The reference architecture below shows how raw feeds become defensible intelligence through sequential validation gates:
Each gate in this diagram is a hard stop: a record that fails it is quarantined, not passed downstream with a warning. The four implementation areas that own these gates each have a dedicated guide — Coordinate Reference Systems for Public Health, Spatial Data Types & Formats, Precision Standards in Epi-Mapping, and Compliance Mapping Frameworks — and the sections below walk the pipeline in execution order, linking each to the standard that governs it.
Data Governance & Compliance Architecture
Public health GIS operates inside a lattice of overlapping legal constraints: the HIPAA Safe Harbor and Expert Determination de-identification standards at the federal level, GDPR Article 9 special-category protections for any EU-resident data, and state-level health information privacy statutes that frequently impose stricter small-count suppression thresholds than HIPAA alone. Treating these as a post-hoc reporting filter is the most common architectural error — by the time data reaches the reporting tier, raw coordinates have already been written to intermediate tables, logs, and spatial indexes. Compliance must therefore be an ingestion-layer property, enforced before any patient-level geometry is persisted at full precision. The full statutory mapping, suppression-threshold logic, and lineage requirements are covered in Compliance Mapping Frameworks; the architectural commitments below are the ones every pipeline in this section assumes.
De-identification at ingestion means three things run before the first spatial join. Direct identifiers (name, MRN, full date of birth) are hashed or dropped; small-count cells are suppressed against a documented threshold so that no published areal unit can be back-solved to an individual; and geocoded coordinates that fall below an analytical confidence interval are masked or aggregated rather than stored rooftop-precise. The suppression threshold itself is a logged parameter, not a constant buried in code — auditors must be able to read it from the run record.
Audit logging is the other half of governance. Every pipeline stage emits structured logs capturing input/output record counts, validation failure rates, and a SHA-256 checksum of the input artifact, so that any published result can be traced back to the exact bytes it was computed from. Immutable lineage tracking records transformation timestamps, library and algorithm versions, and operator credentials. This is what makes a result defensible: a reviewer can re-run the documented configuration and obtain byte-identical output. The following pattern hashes the input and stamps an ISO 19115-style lineage record at the moment of ingestion:
# Versions: geopandas==0.14.4, pyproj==3.6.1, pandas==2.2.2 (Python 3.11)
import hashlib
import json
import logging
from datetime import datetime, timezone
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
def attest_ingest(path: str, suppression_threshold: int, operator: str) -> dict:
"""Hash the source artifact and emit an immutable lineage record at ingestion."""
with open(path, "rb") as fh:
digest = hashlib.sha256(fh.read()).hexdigest()
record = {
"source_path": path,
"sha256": digest,
"ingested_utc": datetime.now(timezone.utc).isoformat(),
"suppression_threshold": suppression_threshold, # logged, not hard-coded silently
"operator": operator,
"schema_version": "epi-ingest/1.4.0",
}
logging.info("INGEST lineage: %s", json.dumps(record))
return record # persist to an append-only provenance store
Spatial Data Preparation
Once an artifact is attested, preparation enforces the geometric preconditions that every downstream statistic silently assumes. The first is coordinate reference governance. Projection mismatch is the primary failure vector in multi-source epidemiological mapping: surveillance points, environmental rasters, and administrative boundaries routinely arrive with conflicting datums or no defined CRS at all. Distance and adjacency computed on unprojected WGS84 degrees are geometrically meaningless, and the distortion grows with latitude — a fixed-distance band that behaves at 30°N silently mis-neighbours features at 60°N. Pipelines must declare a single canonical CRS for analytical operations, reject geometries lacking a valid EPSG code, and choose a projection by analytical intent: equal-area projections preserve the rate denominators in continental incidence modeling, while localized outbreak investigations demand high-precision UTM or State Plane zones. The selection rationale, datum-shift handling, and tolerance checks are detailed in Coordinate Reference Systems for Public Health; the official pyproj documentation is the authoritative reference for transformation-pipeline configuration.
The second precondition is topological validity. Self-intersecting polygons, unclosed rings, and mixed geometry types cause geopandas operations to fail or, worse, return wrong areas without raising. Validation gates must assert validity and heal slivers before any weights matrix or buffer is constructed, routing irreparable geometries to the quarantine table rather than dropping them silently:
# Versions: geopandas==0.14.4, shapely==2.0.4, pyproj==3.6.1
import geopandas as gpd
from shapely.validation import make_valid
import logging
CANONICAL_CRS = "EPSG:5070" # CONUS Albers equal-area; rate-preserving for incidence
def prepare(gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
"""Enforce CRS, repair topology, and quarantine irreparable geometry."""
if gdf.crs is None:
raise ValueError("Geometry has no CRS; reject to prevent silent misalignment.")
gdf = gdf.to_crs(CANONICAL_CRS)
bad = ~gdf.geometry.is_valid
if bad.any():
logging.warning("Repairing %d invalid geometries", int(bad.sum()))
gdf.loc[bad, "geometry"] = gdf.loc[bad, "geometry"].apply(make_valid)
still_bad = ~gdf.geometry.is_valid
quarantine = gdf[still_bad].assign(error_code="TOPOLOGY_IRREPARABLE")
return gdf[~still_bad], quarantine # valid frame, quarantined frame
Schema validation belongs in this same layer. Mandatory fields — case identifier, onset date, diagnostic code, geocoded coordinates — are enforced declaratively at parse time with pydantic or great_expectations, and records that fail are quarantined with a structured error code rather than propagating into spatial joins or kernel density estimates. Validation failure rate is itself a monitored metric: a sudden spike usually signals an upstream feed schema change, not bad luck.
Core Methods Overview
Prepared, governed geometry feeds the detection layer, where the correct method is dictated by data geometry rather than analyst preference. The full implementations live in the Disease Clustering & Spatial Statistical Modeling section; the decision order below is what routes a dataset to the right one.
Aggregated counts per administrative unit — cases per census tract, normalized to a population denominator — go first to global autocorrelation. Global & Local Moran’s I Implementation answers a single yes/no question about whether spatial structure exists at all before any local map is drawn. The global statistic is
where is the row-standardized spatial weight between units and . Only when global is significant does the local decomposition (LISA) earn the right to flag individual units.
When the operational need is to zone an intervention — to draw the boundary of a hot area for resource targeting — Getis-Ord Gi* Hotspot Detection produces a signed z-score surface in which high-value and low-value clusters are distinguishable. Its statistic is
For precise event points rather than areal aggregates — geocoded vector-trap captures or individual case residences where the events are the data — K-Function & Point Pattern Analysis measures clustering as a function of distance scale via Ripley’s estimator,
where is an edge-correction weight. Finally, when where and when must be answered together — a timestamped event stream in active surveillance — Spatial Scan Statistics Configuration applies a likelihood-ratio scan across overlapping space-time windows. Routing every dataset through this ordered decision keeps the entire section operating on one consistent weights object and one consistent CRS.
Threshold Tuning & Validation
Local statistics test one hypothesis per spatial unit, so a raw cutoff applied across a thousand units yields roughly fifty false hotspots by construction. Every method above must therefore correct for multiplicity. The recommended control is the Benjamini–Hochberg false-discovery-rate procedure, which bounds the expected proportion of false positives among declared clusters while retaining far more power than Bonferroni at surveillance scale:
# Versions: numpy==1.26.4
import numpy as np
def bh_fdr(pvals: np.ndarray, alpha: float = 0.05) -> np.ndarray:
"""Benjamini-Hochberg FDR mask over local p-values; returns survivors."""
p = np.asarray(pvals, dtype=float)
n = p.size
order = np.argsort(p)
thresh = (np.arange(1, n + 1) / n) * alpha
passed = p[order] <= thresh
k = np.max(np.where(passed)[0]) + 1 if passed.any() else 0
keep = np.zeros(n, dtype=bool)
if k:
keep[order[:k]] = True
return keep # boolean mask of units surviving FDR control at alpha
Per-run correction is necessary but not sufficient. Drift detection monitors shifts in the denominator population and covariate distributions between releases — a quietly revised census tract will manufacture a “signal” that is really a reclassification artifact, the same failure mode that motivates the versioned-boundary registry below. Cross-validation against historical baselines separates a genuine emerging signal from recurring seasonal structure, and in near-real-time architectures, reporting-delay correction through nowcasting and adaptive windowing prevents both premature declarations and missed onsets. The alpha level, FDR method, drift thresholds, and permutation seed are all logged parameters, because a clustering declaration is only defensible if a reviewer can reproduce the exact tuning that produced it.
Operationalization & Output Standards
The final stage serializes results for handoff, and format choice is itself a compliance decision. Legacy shapefiles introduce attribute truncation, encoding inconsistency, and topology errors that compromise reproducibility; production pipelines deprecate them. Prefer GeoPackage for transactional vector storage, GeoParquet for analytical handoff — it preserves column types, CRS, and bounding box, and reads column-selectively at scale — and Cloud-Optimized GeoTIFF for environmental covariate surfaces. The format-by-format selection criteria, spatial indexing, and conversion patterns are detailed in Spatial Data Types & Formats, with the OGC GeoPackage specification as the authoritative baseline.
Every serialized artifact carries the same provenance block recorded at ingestion: the CRS authority code, an ISO 19115 lineage record, and the SHA-256 configuration hash, so the audit loop opened at ingestion closes at output. Positional accuracy metadata travels with the geometry as well — geocoder confidence, the precision tier, and any uncertainty buffer — following Precision Standards in Epi-Mapping so that downstream consumers can propagate locational error into regression and exposure models rather than treating coordinates as exact.
Administrative boundaries are not static, which is why output must be stamped with the boundary vintage it was computed against. Census tracts, voting districts, and health service areas undergo periodic revision, so a time series spanning multiple vintages requires deterministic alignment — areal interpolation or dasymetric mapping to normalize historical counts onto a contemporary geography — before aggregation. A versioned boundary registry and automated drift detection for slivers, gaps, and overlaps guarantee longitudinal consistency. When a confirmed surface is handed to a downstream accessibility analysis — pairing a hotspot with Healthcare Access & Network Analysis Automation to size the response — the shared provenance metadata is what lets the two pipelines be reconciled after the fact.
The matrix below scores the four serialization targets a pipeline actually emits against the properties that decide which one a given handoff requires:
Production Implementation Checklist
Related Topics
- Coordinate Reference Systems for Public Health — projection selection and datum governance the entire pipeline depends on.
- Spatial Data Types & Formats — vector, raster, and columnar serialization standards for audit-ready handoff.
- Precision Standards in Epi-Mapping — geocoder accuracy tiers and uncertainty propagation into spatial models.
- Compliance Mapping Frameworks — HIPAA, GDPR, and state-law constraints encoded as ingestion-layer gates.
- Disease Clustering & Spatial Statistical Modeling — the detection methods this prepared, governed data feeds.