This document explains how ClimateCast computes the climate, demographic, and risk values shown for each location. It is written for a technically literate reader who wants to understand where the numbers come from and whether they should trust them.
Geography
Each ZIP code is represented by a single latitude and longitude used for all climate data lookups. We use a centroid hierarchy to pick the most representative point:
- Primary source: HUD population-weighted centroid. The U.S. Department of Housing and Urban Development publishes pre-computed centroids that reflect where residents are concentrated within each ZIP code, rather than the geometric center of the ZIP's boundary.
- Fallback: ZCTA geometric centroid. When HUD does not provide a centroid for a given 5-digit ZIP code, we fall back to the geometric center of the Census Bureau's ZIP Code Tabulation Area (ZCTA) polygon from TIGER/Line 2023.
- Land-snap. If the chosen point falls in water (common for coastal ZIPs), we shift it inland to the nearest land pixel using a CONUS land mask derived from WorldClim.
| Field | Description |
|---|---|
meta.centroid_source | Either "hud_population_weighted" or "zcta_geometric_fallback". |
meta.large_zcta | true when the ZCTA spans more than 50 km. |
meta.coastal_water_zcta | true when the ZCTA is predominantly water and climate data is unavailable. |
meta.usps_preferred_city | Optional. USPS preferred city from HUD (USPS_ZIP_PREF_CITY), used for the location report headline when present. |
meta.zcta_boundary | Optional. Simplified ZCTA outline as GeoJSON for the county/ZIP map section. |
Current Monthly Climate
Source: WorldClim historical monthly weather (CRU-TS 4.09 downscaled with WorldClim 2.1), averaged over the 2005–2024 reference period, 2.5 arc-minute resolution (~4.6 km per pixel).
Method: Year-by-year monthly rasters over 2005–2024 are averaged per calendar month, then point-sampled at the representative latitude and longitude selected for each ZIP. No area-averaging is performed; each ZIP gets the value of the single grid cell containing its representative point.
| Field | Description |
|---|---|
climate.current.monthly.tmin_c | 12-element array of monthly minimum temperature in °C. |
climate.current.monthly.tmax_c | 12-element array of monthly maximum temperature in °C. |
climate.current.monthly.prec_mm | 12-element array of monthly total precipitation in mm. |
Attribution: Fick, S.E. and R.J. Hijmans, 2017. WorldClim 2: new 1-km spatial resolution climate surfaces for global land areas. International Journal of Climatology 37(12): 4302–4315.
Extreme Heat Days and Wet-Bulb Days (Current)
These metrics require daily temperature distributions and cannot be derived from WorldClim monthly means alone. We compute them from NOAA's Global Historical Climatology Network Daily (GHCNd) dataset.
Station Selection
| Rule | Detail |
|---|---|
| Baseline period | 2005–2024 (recent 20-year window) |
| Quality threshold | At least 16 complete years during 2005–2024 |
| ZIP assignment | Nearest qualifying station within 150 km; otherwise values are null |
The assigned station is recorded in:
| Field | Description |
|---|---|
climate.current.monthly.noaa_station_id | NOAA GHCNd station identifier for the assigned station. |
climate.current.monthly.noaa_station_distance_km | Distance from the ZIP centroid to that station. |
Heat Day Thresholds
For each month, ClimateCast counts the average annual days where TMAX exceeds the threshold below.
| Threshold | Field |
|---|---|
| 90 °F (32.2 °C) | climate.current.monthly.heat_days_90f |
| 95 °F (35.0 °C) | climate.current.monthly.heat_days_95f |
| 100 °F (37.8 °C) | climate.current.monthly.heat_days_100f |
Wet-Bulb Temperature Calculation
Wet-bulb temperature (Tw) uses the Stull (2011) empirical approximation:
Tw = T · atan(0.151977 · (RH + 8.313659)^0.5)
+ atan(T + RH)
- atan(RH − 1.676331)
+ 0.00391838 · RH^1.5 · atan(0.023101 · RH)
− 4.686035
Where T is dry-bulb temperature in °C and RH is relative humidity in %.
Relative humidity is derived from TMAX and dew-point using the Magnus formula. When dew-point is missing, ClimateCast uses TMIN as a dew-point proxy (a conservative approach that can bias wet-bulb counts high in arid climates).
| Threshold | Field |
|---|---|
| 28 °C wet-bulb exceedance days | climate.current.monthly.wet_bulb_days_28c |
| 30 °C wet-bulb exceedance days | climate.current.monthly.wet_bulb_days_30c |
Frost Dates
| Metric | Definition | Field |
|---|---|---|
| Last spring frost | Latest day in spring (Jan–Jun) with TMIN ≤ 28 °F | climate.current.frost.last_spring_frost_doy |
| First fall frost | Earliest day in fall (Jul–Dec) with TMIN ≤ 28 °F | climate.current.frost.first_fall_frost_doy |
Future Monthly Climate
Source: WorldClim CMIP6 downscaled projections, 10 arc-minute resolution (~18 km per pixel on the UC Davis mirror), point-sampled at the same representative location as historical data (nearest finite cell search handles occasional coastal nodata on the coarse grid).
Scenarios and Time Periods
ClimateCast exposes three SSP pathways:
| Frontend label | SSP scenario | Approximate warming by 2100 |
|---|---|---|
| Low emissions | SSP1-2.6 | ~1.8 °C |
| Medium emissions | SSP2-4.5 | ~2.7 °C |
| High emissions | SSP5-8.5 | ~4.4 °C |
Each scenario includes four 20-year windows:
| Label in API / UI | Twenty-year window |
|---|---|
"2040" | 2021–2040 |
"2060" | 2041–2060 |
"2080" | 2061–2080 |
"2100" | 2081–2100 |
Multi-Model Mean
Future values are averaged across eight WorldClim CMIP6 GCMs (same set for every emissions pathway):
- ACCESS-CM2
- BCC-CSM2-MR
- CNRM-CM6-1
- CNRM-ESM2-1
- CanESM5
- IPSL-CM6A-LR
- MIROC6
- MRI-ESM2-0
GFDL-ESM4 (the ninth GCM on WorldClim) is excluded because the UC Davis download mirror lacks complete coverage for the SSPs we use.
Scenario keys are low, mid, and high; period keys are 2040, 2060, 2080, and 2100 (each
maps to the twenty-year windows above). All monthly.* arrays are 12 elements (Jan–Dec). In the
paths below, <tier> is one of low, mid, or high, and <window> is one of 2040, 2060,
2080, or 2100.
| Field | Description |
|---|---|
climate.future.source | Dataset note for projections (8-model mean), when present. |
climate.future.scenarios.<tier>.source | Per-scenario CMIP6 ensemble note (same eight-model mean), when present. |
climate.future.scenarios.<tier>.ssp | SSP label (e.g. SSP1-2.6), when present. |
climate.future.scenarios.<tier>.periods.<window>.period | Human-readable window label, when present. |
climate.future.scenarios.<tier>.periods.<window>.monthly.tmin_c | Monthly minimum temperature in °C. |
climate.future.scenarios.<tier>.periods.<window>.monthly.tmax_c | Monthly maximum temperature in °C. |
climate.future.scenarios.<tier>.periods.<window>.monthly.prec_mm | Monthly total precipitation in mm. |
climate.future.scenarios.<tier>.periods.<window>.monthly.heat_days_90f | Twelve monthly values recomputed with the delta method below; same semantics as the current monthly 90 °F heat-day series. |
climate.future.scenarios.<tier>.periods.<window>.monthly.wet_bulb_days_28c | Monthly wet-bulb exceedance counts at 28 °C. |
climate.future.scenarios.<tier>.periods.<window>.monthly.wet_bulb_days_30c | Monthly wet-bulb exceedance counts at 30 °C. |
climate.future.scenarios.<tier>.periods.<window>.frost.last_spring_frost_doy | Last spring frost day-of-year. |
climate.future.scenarios.<tier>.periods.<window>.frost.first_fall_frost_doy | First fall frost day-of-year. |
Delta Method for Future Heat and Wet-Bulb Days
ClimateCast uses a mean-shift (delta) approach:
- Compute
Δtmax = CMIP6_future_tmax − WorldClim_historical_tmax - Shift the historical daily TMAX distribution by
Δtmax - Recount threshold exceedances and recompute wet-bulb days
This method does not model shifts in variance/tails, only the mean.
Climate analog (reference locations)
Shows which existing places have a baseline climate most similar to this ZIP's projected future — one closest match from the combined U.S. + international catalog. This is an illustrative similarity in climate-variable space, not a forecast that a ZIP "becomes" another city.
How it works
The app compares each reference location's WorldClim / CRU-TS 4.09 (2005–2024) baseline against this ZIP's projected monthly climate (CMIP6 multi-model mean for the selected scenario and period) across seven dimensions:
| Dimension | Definition |
|---|---|
| Mean annual daily high (°F) | Mean of 12 monthly tmax, converted from °C |
| Mean annual daily low (°F) | Mean of 12 monthly tmin, converted from °C |
| Annual precipitation (in) | Sum of 12 monthly prec_mm, converted to inches |
| Aridity index | MAP (mm) / MAE (mm), Hargreaves-style reference evaporation by latitude. Same formula as Drought Risk below. Undefined cases excluded. |
| Temperature seasonality (°C) | Max monthly tmax − min monthly tmin (continental vs maritime) |
| Precipitation phase (cos) | When rain falls: months placed on a circle and weighted by rainfall give a vector, rotated so the local warm season sits at 0°. cos > 0 = warm-season-wet (monsoon), cos < 0 = cool-season-wet (Mediterranean). Hemisphere-agnostic. |
| Precipitation phase (sin) | Quadrature component of the same precipitation-timing vector. |
Distance calculation
All reference features are z-scored using means and standard deviations from the full reference set. The projected vector is z-scored with the same parameters. Distance is weighted Euclidean in z-space with weights: mean high 2.2, mean low 2.2, aridity index 1.9, temperature seasonality 0.85, precipitation phase 0.7 each (cos and sin), and annual precipitation 0.8. Temperature is weighted most, followed by aridity; annual precipitation is down-weighted because it overlaps heavily with the aridity and precipitation-phase dimensions.
The single closest row from the full combined reference set is reported. The user's own location is excluded from candidates by ZIP and by normalized place name + state (same city at a different catalog ZIP).
When it's omitted
The section is hidden when the reference dataset fails to load, monthly futures are incomplete, or centroid latitude is missing. Centroid longitude is only needed for the map arcs.
Downloads (same origin as the site; use “Save link as…” if your browser opens JSON instead of downloading):
| Resource | Notes |
|---|---|
| climate-analog-reference.json | Built reference data (JSON). |
Drought Risk
Drought risk is derived, not pass-through from an external risk tier dataset. It uses an Aridity Index (AI):
AI = MAP / MAE
Where:
| Symbol | Meaning |
|---|---|
| MAP | Mean annual precipitation (mm) |
| MAE | Mean annual potential evapotranspiration (Hargreaves-Samani estimate) |
Classification thresholds:
| AI range | Drought risk level | UNEP climate zone |
|---|---|---|
| AI < 0.05 | very_high | Hyper-arid |
| 0.05 ≤ AI < 0.20 | high | Arid |
| 0.20 ≤ AI < 0.50 | elevated | Semi-arid |
| 0.50 ≤ AI < 0.65 | moderate | Dry sub-humid |
| AI ≥ 0.65 | low | Humid |
| Field | Description |
|---|---|
risks.drought.level | Binned drought risk level from the AI ranges above. |
Risk Level Binning
ClimateCast reports eight risk categories:
- Six county-level scores from ProPublica/Rhodium
- One storm intensity category from EPA CREAT
- One derived drought category
ProPublica / Rhodium Group Risks
Categories: heat, wet_bulb, farm_crop_yields, sea_level_rise, very_large_fires,
economic_damages.
ProPublica publishes county-level scores on a 1–10 scale. ClimateCast bins those scores:
| Score range | Risk level |
|---|---|
| 1–2 | low |
| 3–4 | moderate |
| 5–6 | elevated |
| 7–8 | high |
| 9–10 | very_high |
Storm Intensity (EPA CREAT)
Category: storm_intensity
Binning thresholds:
| % change in intensity | Risk level |
|---|---|
| < 10% | low |
| 10–20% | moderate |
| 20–30% | elevated |
| 30–40% | high |
| ≥ 40% | very_high |
Null Reason Values
null_reason value | When it applies |
|---|---|
"no_data_for_state" | Unsupported state coverage in source datasets. |
"missing" | Other missingness causes. |
Demographics
Three demographic fields are included as pass-through values from named sources.
| Topic | Source | Geography | Output field(s) |
|---|---|---|---|
| Median household income | U.S. Census ACS 5-year estimates (B19013_001E) | ZCTA | demographics.median_household_income_usd |
| Life expectancy | CDC USALEEP (2010–2015) | Census tract aggregated to ZCTA | demographics.life_expectancy_years, demographics.life_expectancy_period |
| Plant hardiness zone | USDA PHZM 2023 | — | demographics.plant_hardiness_zone |
On city and county pages (see City and County Pages), median household income and total population are pulled directly from ACS at the Census place and county summary levels rather than aggregated from ZIP values, so they are the official figures for the whole place or county.
ZIP-to-County Assignment
Each ZIP is assigned to a single county for county-level risk joins.
| Aspect | Detail |
|---|---|
| Source | HUD USPS ZIP Crosswalk |
| Rule | Select county with highest residential-address share |
| Field | Description |
|---|---|
meta.county_fips | Assigned county FIPS code. |
meta.county_name | Assigned county name. |
meta.state | State for the assigned county. |
meta.crosswalk_vintage | HUD crosswalk file vintage used for the assignment. |
Representative ZIP per county
Each county also has one representative ZIP, used for the county page's climate data (see City and County Pages) and as the climate source for that county.
| Aspect | Detail |
|---|---|
| Source | HUD USPS ZIP Crosswalk (same quarterly file), with optional ACS ZIP population as a tie-break helper |
| Goal | Avoid selecting a large metro ZIP that only partially overlaps the clicked county and is primarily associated with a neighboring county. |
Selection order (first match wins; later steps break ties):
| Step | Criterion |
|---|---|
| 1 | Prefer ZIPs where that county is the ZIP's primary county (highest residential share for that ZIP). |
| 2 | Then highest county share (res_ratio). |
| 3 | Then highest ZIP population (if available). |
| 4 | Final tie-break by ZIP code for deterministic output. |
City and County Pages
Alongside ZIP reports, ClimateCast publishes city and county pages. Searching for a city opens its city page, and clicking a county in the county-risk map opens that county page.
Geography
| Page type | Entity | Route |
|---|---|---|
| City | U.S. Census place (STATEFP + PLACEFP, 7 digits) | /city/{geoid} |
| County | County FIPS (5 digits) | /county/{fips} |
| ZIP | 5-digit ZIP / ZCTA | /location/{zip} |
How values are sourced
| Data | City page | County page |
|---|---|---|
| Income & population | ACS at the place level | ACS at the county level |
| Climate | Representative ZIP for the place | Representative ZIP for the county |
| Life expectancy & plant hardiness | Representative ZIP | Representative ZIP |
| Risks | Representative ZIP's county | The county itself |
Income and population are read directly from ACS for the whole place or county, so they are not a single ZIP's numbers nor an average of ZIP medians. Climate, life expectancy, and plant hardiness use one representative ZIP (see Representative ZIP per county for how the county ZIP is chosen). For cities, the pipeline first picks the highest-population allowed ZCTA whose centroid falls inside the Census place; if none qualify, it uses the highest-population ZCTA that intersects the place polygon.
Search routing
Search routes by the selected result's place type: a city or locality opens the matching city page,
an administrative area opens the county page, and a ZIP code or street address opens the ZIP page.
The city search index lists only places with a published city/{geoid}.json (representative ZIP
must exist in the location dataset). When a city can't be matched to that index, search shows an
error instead of silently falling back to a ZIP page.
Known Limitations
| Topic | Detail |
|---|---|
| Life expectancy | CDC tract-based values are from 2010–2015. |
| ProPublica / Rhodium risks | County scores are from 2020 and based on RCP 8.5. |
| EPA CREAT (storm intensity) | Coarse 0.5° grid and may miss sub-county variation. |
| Wet-bulb estimates | TMIN-as-dew-point proxy can overestimate humidity for some stations. |
| Future heat / wet-bulb (delta method) | Adjusts mean but not variance/tails. |
| CMIP6 multi-model mean | Uses eight GCMs (excludes GFDL-ESM4 — incomplete on the UC Davis mirror for our SSPs). |
| Climate analog “match” | Similarity in a few z-scored climate averages (current references vs your selected projected window); not a full ecological forecast; references use 2005–2024 baselines only. |
| City / county climate | Uses a single representative ZIP, not an area average; a city or county that spans multiple climates is summarized by one point. Risks for a city reflect its representative ZIP's county. |
Data Sources
- WorldClim ↗ — Historical climate normals and CMIP6 downscaled future projections.
- NOAA GHCNd ↗ — Daily station data used for heat-day, wet-bulb, and frost metrics.
- ProPublica Climate Risk ↗ — County-level climate risk indicators sourced from ProPublica/Rhodium.
- EPA CREAT ↗ — Legacy tool reference for the Climate Resilience Evaluation & Awareness Tool (CREAT).
- CREAT ArcGIS Data (CRWU) ↗ — Primary downloadable storm projection dataset used because the original CREAT app is no longer active.
- U.S. Census ACS ↗ — Median household income by ZCTA.
- CDC USALEEP ↗ — Small-area life expectancy estimates.
- USDA PHZM ↗ — Plant hardiness zone reference values.
- HUD ZIP Crosswalk ↗ — ZIP-to-county assignment using residential address weights.