Hazard Proximity & Drinking Water Metrics
This guide is part of the Environmental Exposure & Risk Surface Modeling section. For most environmental hazards there is no monitoring network, no satellite product and no model — only a list of facilities, a set of service area boundaries, and a regulatory compliance history. This page is about doing honest work with those.
Concept & Epidemiological Alignment
A proximity metric substitutes geometry for measurement. Distance to the nearest landfill, presence within a facility’s permitted radius, count of industrial sites within a kilometre — each encodes a hypothesis that exposure decreases with distance from a discrete source, without ever estimating a concentration. Drinking water metrics are a close relative: membership in a public water system’s service area, the system’s violation history, and reliance on a private well are all categorical or count proxies for what someone actually drank.
The epidemiological honesty required here is higher than elsewhere in this section, because the gap between the metric and the dose is wider. Distance is not dose. A residence 300 m downwind of a stack has a materially different exposure from one 300 m upwind, and a circular distance metric assigns them the same value. A household inside a water system’s boundary may be on a well, may drink bottled water, and may receive water from a different intake than a neighbour on the same street.
What these metrics are genuinely good for is comparison and screening. They identify populations plausibly more exposed, support environmental justice analyses where the question is about the distribution of burden rather than a dose-response slope, and produce testable hypotheses. What they do not support is a quantitative risk estimate per unit of exposure, because there is no unit.
Three assumptions must be stated whenever one is used. That the source inventory is complete for the study period — permitted facility lists routinely omit unpermitted and historical sites. That the geocoded source location represents the emission point rather than an administrative address. And that the exposure pathway is plausibly isotropic, or, where it is not, that the metric has been given a direction.
Metric Families
| Metric | Data needed | Supports | Fails when |
|---|---|---|---|
| Distance to nearest source | Source inventory with coordinates | Ranking, screening | Sources are unlisted, or coordinates are mailing addresses |
| Count within a radius | Inventory plus a declared radius | Cumulative burden | Sources differ greatly in size or emissions |
| Inverse-distance weighted sum | Inventory plus a decay assumption | Dose-like ranking | The decay exponent is unjustified |
| Directional or plume exposure | Inventory plus wind or flow direction | Realistic near-source contrast | Direction data are coarse or seasonal |
| Water system membership | Service area boundaries | Regulated-supply contrast | Boundaries are approximate or absent |
| Violation history | Compliance records by system | Regulatory exceedance exposure | Violations reflect monitoring effort, not just water quality |
| Private well reliance | Survey or modelled estimates | Unregulated-supply contrast | Reliance is estimated, not observed |
Spatial Data Prerequisites
- A source inventory with coordinates, operating dates and, ideally, an emissions or capacity attribute. Permit databases, hazardous site registries and discharge monitoring reports are the usual sources.
- Coordinate reference system: one projected metric system, since every metric here is a distance.
- Source coordinate provenance: whether each coordinate is a stack, a parcel centroid or a mailing address, because the three differ by hundreds of metres.
- Operating dates: a facility that closed in 2009 should not contribute to a 2020 exposure, and one that opened in 2015 should not contribute to a 2010 one.
- Water system service areas where available; many states publish approximate boundaries and some publish none, in which case system membership must be inferred from billing geography or modelled.
- Study-area padding: the inventory must extend beyond the study boundary by at least the largest radius so edge residences are not undercounted.
Production Implementation
The routine below computes distance, count and inverse-distance-weighted metrics in one pass with a spatial index, respecting operating dates and returning the provenance of each source that contributed.
# Proximity metrics with date filtering and source provenance retained.
# Pinned: geopandas==0.14.4, numpy==1.26.4, pandas==2.2.2, scipy==1.13.1
import logging
import numpy as np
import pandas as pd
import geopandas as gpd
from scipy.spatial import cKDTree
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
log = logging.getLogger("exposure.proximity")
RADII_M = (500, 1000, 2000, 5000)
def active_sources(sources: gpd.GeoDataFrame, as_of: pd.Timestamp) -> gpd.GeoDataFrame:
"""Sources operating on a given date. Closed and future facilities are excluded."""
opened = pd.to_datetime(sources["open_date"], errors="coerce")
closed = pd.to_datetime(sources["close_date"], errors="coerce")
live = (opened.isna() | (opened <= as_of)) & (closed.isna() | (closed >= as_of))
dropped = int((~live).sum())
log.info("sources active at %s: %d of %d (%d excluded by operating dates)",
as_of.date(), int(live.sum()), len(sources), dropped)
return sources[live].reset_index(drop=True)
def proximity_metrics(residences: gpd.GeoDataFrame, sources: gpd.GeoDataFrame,
radii=RADII_M, idw_power: float = 1.0,
idw_floor_m: float = 50.0) -> pd.DataFrame:
"""Nearest distance, counts within radii, and an inverse-distance-weighted sum."""
if residences.crs != sources.crs or residences.crs.is_geographic:
raise ValueError("both layers must share one projected metric CRS")
residences = residences.sort_values("study_id").reset_index(drop=True)
sxy = np.c_[sources.geometry.x.values, sources.geometry.y.values]
rxy = np.c_[residences.geometry.x.values, residences.geometry.y.values]
tree = cKDTree(sxy)
nearest_d, nearest_i = tree.query(rxy, k=1)
out = pd.DataFrame({"study_id": residences["study_id"].to_numpy(),
"dist_nearest_m": nearest_d,
"nearest_source_id": sources.iloc[nearest_i]["source_id"].to_numpy()})
for r in sorted(radii):
idx = tree.query_ball_point(rxy, r)
out[f"count_{int(r)}m"] = [len(i) for i in idx]
# Inverse-distance sum over the widest radius, floored so a co-located source
# does not produce an infinite score.
widest = max(radii)
idx = tree.query_ball_point(rxy, widest)
idw = np.zeros(len(rxy))
for i, js in enumerate(idx):
if not js:
continue
d = np.maximum(np.linalg.norm(sxy[js] - rxy[i], axis=1), idw_floor_m)
idw[i] = float(np.sum(d ** (-idw_power)))
out[f"idw_p{idw_power:g}_{widest}m"] = idw
log.info("proximity metrics for %d residences against %d sources; "
"median nearest distance=%.0f m, %d with none within %d m",
len(out), len(sources), float(np.median(nearest_d)),
int((out[f"count_{int(widest)}m"] == 0).sum()), widest)
return out
Filtering by operating date is the step most often omitted and the one that most often invalidates a study. A hazardous site inventory is a snapshot of today, and using it for a cohort exposed in the 1990s assigns exposure from facilities that had not been built and misses ones that closed. Where operating dates are absent from the inventory — which is common — that limitation must be stated rather than quietly ignored.
The inverse-distance floor prevents an infinite score for a residence at a facility’s coordinates, which happens more often than expected because some inventories geocode a facility to the centroid of the parcel it shares with housing. The floor value should be reported, because it caps the maximum score and therefore the top of the exposure distribution.
Parameter Selection & Tuning
The radius set should be declared before the outcome is examined, with one primary radius and the rest as a sensitivity ladder, following Choosing a Buffer Radius for Proximity Exposure.
The inverse-distance exponent has the same status as the exponent in a spatial interpolation: it is the model. A value of 1 corresponds to a plume-like decay, 2 to a point-source dilution; neither is universally right, and the choice should be stated and varied in sensitivity analysis.
Source weighting. Where an emissions or capacity attribute exists, weighting sources by it is far more informative than counting them equally. A large refinery and a small dry cleaner are not the same source, and an unweighted count treats them as such.
Water system assignment method. Where service area boundaries exist, a point-in-polygon join is direct. Where they do not, assignment by ZIP code or by the nearest system’s centroid introduces error that is large and structured, and a sensitivity analysis restricted to residences with a confident boundary match is worth running.
Violation windows. A violation history should be summarised over the exposure window, not over the whole record. A system with a lead exceedance in 1998 and none since is not currently exposing anyone to a 1998 violation.
Edge Cases & Failure Modes
Facility coordinates that are mailing addresses. A corporate headquarters geocode can be hundreds of kilometres from the emitting site. Screen for sources whose coordinates fall in an implausible land-use context, and check any facility that many residences are close to.
An incomplete inventory. Regulatory lists cover permitted, current facilities. Historical, unpermitted and small sources are systematically missing, and their absence biases toward the null in a way that cannot be quantified without a better inventory.
Water systems that purchase water. A system’s own compliance record does not describe the water it buys from a wholesaler. Trace the purchase relationships or state that they were not traced.
Boundary files that are approximate. Many published service area boundaries are drawn from billing ZIP codes rather than from pipe networks. A point-in-polygon join against them is more precise than the input justifies.
Private well reliance as a modelled quantity. Where well use is estimated from housing age and system boundaries rather than observed, it carries the errors of that model, and treating it as an observed exposure overstates precision.
Edge effects. Residences near the study boundary have sources outside it that the inventory omits, producing systematically low counts. Extend the inventory beyond the boundary by the widest radius.
The operating-date filter is the single most consequential line in a proximity study with a historical exposure window, and its effect is easy to show:
Compliance & Audit Controls
Record the source inventory identifier and extract date, which attributes were used for weighting, the coordinate provenance for each source class, the operating-date filter and how many sources it excluded, the radii and exponent with their justification, the inverse-distance floor, the study-area padding, and the count of residences with no source within the widest radius.
For water metrics, record the service area boundary source and its construction method, the assignment method for residences outside any boundary, whether purchase relationships were traced, the violation window, and which violation categories were counted.
Proximity metrics are frequently used in environmental justice analyses, which are read closely by the communities they describe. Two practices matter there. Publish the source inventory used, so a resident can see whether the facility they are concerned about was included. And state the metric’s limitations in the same document as the result, because a distance metric presented without them invites an interpretation it cannot support.
Production Implementation Checklist
Frequently Asked Questions
Is distance to a facility a legitimate exposure measure? It is a legitimate proxy for ranking and screening, and it is not a dose. It supports statements about which populations are plausibly more exposed and about the distribution of burden; it does not support a risk estimate per unit exposure, because there is no unit. Describe it as proximity, not as exposure concentration.
Should I use a binary buffer or a continuous distance? Continuous distance retains more information and avoids an arbitrary cut point, so it is the better default. A binary buffer is easier to communicate and suits a policy question framed as “who lives within X”. Report both where the audience includes both analysts and decision-makers.
How do I handle facilities with no operating dates? Include them with a flag, run the analysis with and without them, and report the difference. Excluding them assumes they were never operating; including them assumes they always were. The sensitivity between those two is the honest range.
What if no water service area boundaries exist for my state? Assignment by billing geography or by system service population is the usual fallback, and it is substantially less accurate. Report the fraction of residences assigned by each method and run the primary analysis restricted to confident matches as a sensitivity check.
Do violations measure water quality or monitoring effort? Both, and they cannot be fully separated. A system that monitors diligently records more violations than one that does not, so a violation count partly measures compliance behaviour. Where possible, use measured contaminant levels rather than violation counts, and where not, say that the metric conflates the two.
Related Topics
- Environmental Exposure & Risk Surface Modeling — the parent section and where proximity sits among the modeling families.
- Computing Distance to the Nearest Hazard Site at Scale — the computation for millions of residences against a national inventory.
- Linking Case Addresses to Public Water System Boundaries — the service area join and what to do where boundaries do not exist.
- Choosing a Buffer Radius for Proximity Exposure — justifying the radius that every metric here depends on.