
Impute Country-Week Tropical-Cyclone Probability from EM-DAT and Climate
Source:R/impute_cyclone_probability.R
impute_cyclone_probability.RdFits a binomial GAM on observed EM-DAT tropical-cyclone / storm-surge
events (emdat_cyclone_active, 0/1) as a function of a
wind/coastal mechanistic predictor set that is deliberately
distinct from the precipitation-driven flood GAM. The key proxy is the
weekly maximum 10m wind speed (wind_speed_10m_max); precipitation
channels capture the co-arriving surge/rain, and ENSO/IOD teleconnection
lags capture the seasonal steering of cyclone tracks into the Southwest
Indian Ocean / Mozambique Channel. The fitted model predicts a
continuous cyclone probability for every (iso_code, year, week) row –
historical AND forecast – so the downstream psi LSTM consumes the same
feature definition in training and inference.
Usage
impute_cyclone_probability(
d,
output_col = "emdat_cyclone_prob",
gam_train_stop = NULL,
diagnostics = TRUE,
diag_dir = NULL,
verbose = TRUE
)Arguments
- d
A data.frame with one row per (iso_code, year, week). Must contain the columns returned by
.impute_cyclone_probability_required():iso_code,year,week,date; the binary targetemdat_cyclone_active(0/1; NA in forecast rows is fine); the WHO subregionregion; the storm proxywind_speed_10m_max; precipitation channelsprecipitation_sum,precip_sum_2w,precip_sum_4w; and the teleconnection indicesENSO34,IOD(lags computed inline by the function).- output_col
Character. Name of the new probability column. Default
"emdat_cyclone_prob".- gam_train_stop
Date or character (
"YYYY-MM-DD") orNULL. When non-NULL, the binomial GAM is FIT only on rows withdate <= gam_train_stop; the fitted model then PREDICTS every row (rows<= gam_train_stopin-sample, rows> gam_train_stopleak-free extrapolation). The leakage-hygiene hook for rolling-origin forecast CV. DefaultNULL= current full-data fit (back-compatible). Only the fit-row subset changes;select=TRUE/fREML/the formula are identical.- diagnostics
Logical. If
TRUE, fits a rolling-year cross-validation and writes diagnostic artefacts todiag_dir.- diag_dir
Character. Directory for diagnostic outputs (created if missing). Ignored when
diagnostics = FALSE.- verbose
Logical. Echo progress messages.
Value
The input data.frame with one added column named
output_col carrying a non-NA numeric in [0, 1] for every row.
Details
Why a separate GAM (not folded into the flood label). Tropical cyclones carry the opposite climate signature from ordinary precipitation floods: a sharp wind spike with a short, crisply-dated footprint. The flood-only EM-DAT filter historically dropped all 49 tropical-cyclone / surge events, which neutered the flood GAM's wind smooth. Modeling cyclones with their own wind-led GAM restores that signal as a clean input channel; the psi LSTM recombines the flood and cyclone probabilities downstream (the shared cholera-contamination mechanism lives in the LSTM, not in the label).
The GAM is fit with mgcv::bam(),
family = stats::binomial(link = "logit") (predictions naturally in
[0, 1]), method = "fREML", select = TRUE (smoothness
null-space shrinkage – drives uninformative smooths toward zero, the same
principled mechanism used by impute_flood_probability).
Predictors computed inline (the caller need not supply them):
ENSO34 and IOD at lags 8, 16, 24 weeks (seasonal cyclone-season steering; SWIO cyclone activity co-varies with ENSO/IOD phase).
Nothing else – the wind and short-window precip channels are the acute proxy; the country random effect absorbs baseline coastal-exposure differences.
The active fraction is very low (~74 weeks out of ~35k country-weeks,
~0.2%). The country random effect s(iso_code_f, bs = "re")
concentrates predicted probability on the historically cyclone-exposed
coastal countries (MOZ, MWI, ZWE, MDG-adjacent belt) and keeps landlocked
/ non-cyclone countries near zero. A region-conditional wind smooth
(s(wind_speed_10m_max, by = region_f)) lets Southern Africa (the
cyclone belt) map wind to risk more steeply than the other subregions.
Sentinel handling mirrors the flood imputer: any NA prediction (lag warm-up edge, residual missing predictor) is filled with that country's mean predicted probability; global mean is the last resort. The function asserts the final column is numeric, in [0, 1], and NA-free.
If diagnostics = TRUE, a rolling-year CV (3 most-recent
fully-observed years) writes per-fold AUC / Brier / log-loss to
cyclone_gam_cv_metrics.csv. A mean CV AUC below 0.65 emits a
warning but the column is still returned.