
Modeling 08: Vulnerability Index and SWOT Synthesis
climasus4r Team
17/10/2026
Source:vignettes/mod-08-vulnerabilidade-swot.Rmd
mod-08-vulnerabilidade-swot.RmdObjective
By the end of this tutorial you will be able to:
-
Compose a Composite Vulnerability Index (CVI)
following the IPCC AR6 three-pillar structure — climate Exposure,
population Sensitivity, and Adaptive Capacity — from health-climate,
socioeconomic, and health infrastructure indicators, using
sus_mod_vulnerability_index(); - Interpret the vulnerability ranking across municipalities and measure territorial inequality with the Gini Coefficient and the Lorenz curve;
-
Synthesize the results into a SWOT analysis
(Strengths, Weaknesses, Opportunities and Threats) oriented toward
health-climate public policy, using
sus_mod_swot(); -
Visualize and communicate the results with the
paired plotting functions
sus_mod_plot_vulnerability()(ranking, pillars, Lorenz) andsus_mod_plot_swot()(radar, 2×2 matrix, bars).
This is the eighth module in the Modeling series of
climasus4r. The main inputs are the
climasus_af object from Module M2 (mod_af.rds)
and the climasus_dlnm object from Module M1
(mod_dlnm_fit.rds). The main output is the
climasus_vi object saved as mod_vi.rds for
reuse in final reports and risk communication.
Scientific background
Climate vulnerability according to the IPCC
The IPCC’s Fifth Assessment Report (AR5, 2014) established the three-pillar framework that defines vulnerability — later refined in AR6 (2022) — as a function of three interdependent components:
- Exposure: the degree to which a system or population is affected by climate stressors (extreme temperature, heat waves, days above the 90th percentile of heat);
- Sensitivity: the level of response of a system to the stressor, conditioned by intrinsic factors such as the proportion of elderly people, prevalence of chronic disease, and the dose-response relationship estimated by DLNM models;
- Adaptive Capacity: the set of institutional, economic, and infrastructural resources that allow a system to modulate its impacts (human development index, treated water coverage, density of primary health care units).
The composite index formula, originally proposed by Turner et al. (2003) and adopted in the social vulnerability literature (Cutter, Boruff & Shirley, 2003; Benmarhnia et al., 2015), inverts the Adaptive Capacity pillar before combination, since higher capacity means lower vulnerability:
where , , and are the weighted averages of the normalized indicators (min-max or z-score) of municipality for each pillar, and , , are the inter-pillar weights. Missing indicators are handled through automatic reweighting.
Min-max and z-score normalization
Min-max normalization projects each indicator onto the interval :
Z-score normalization standardizes by mean and standard deviation, preserving the original distribution — useful when indicators have very heterogeneous scales, but it requires a back-transformation for direct interpretation.
Territorial inequality and the Lorenz Curve
The Lorenz Curve is the classic instrument for visualizing the concentration of any resource or burden across an ordered population. In the context of climate risk, the curve accumulates the proportion of total CVI (y-axis) against the proportion of municipalities (x-axis), from least to most vulnerable. The larger the area between the curve and the diagonal of perfect equality, the higher the Gini Coefficient — which ranges from 0 (perfect equality) to 1 (all risk concentrated in a single municipality).
Climate risk concentration analyses have been applied at multi-city scale by Gasparrini et al. (2017) and in national socio-environmental vulnerability studies in Brazil by Confalonieri et al. (2009) and Marengo et al. (2022).
SWOT analysis oriented toward health-climate policy
The SWOT framework (Andrews, 1971), widely used in strategic planning, has been adapted to climate-health risk management. In this approach:
- Strengths (S) represent existing protective factors — high adaptive capacity, low total attributable fraction;
- Weaknesses (W) reflect current vulnerabilities — high population sensitivity, high heat- and cold-attributable fractions;
- Opportunities (O) identify windows for intervention — municipalities with a relatively low vulnerability index and moderate current exposure have room to advance prevention before reaching critical levels;
- Threats (T) signal emerging or already present risks — high climate exposure, high relative heat risk (DLNM), high attributable number.
Data used
| Object | Source | Content |
|---|---|---|
caso_espacial.rds |
Tutorial T5 | sf geometries of the RMSP municipalities |
caso_socio.rds |
Tutorial T6 | Socioeconomic indicators per municipality (HDI, % elderly, etc.) |
mod_dlnm_fit.rds |
Module M1 |
climasus_dlnm object fitted for the RMSP |
mod_af.rds |
Module M2 |
climasus_af object with total/heat/cold AF% |
Whenever any of these four files is missing (execution outside the full chain), the pre-rendering script synthesizes realistic data with a warning — the Rmd renders normally, displaying illustrative results.
Complete pipeline
Load chained inputs
# Objeto climasus_af do Módulo M2
mod_af <- if (file.exists("vignettes-pt/dados/mod_af.rds")) {
readRDS("vignettes-pt/dados/mod_af.rds")
} else {
NULL # fallback: SWOT rodará sem AF
}
# Objeto climasus_dlnm do Módulo M1
mod_dlnm <- if (file.exists("vignettes-pt/dados/mod_dlnm_fit.rds")) {
readRDS("vignettes-pt/dados/mod_dlnm_fit.rds")
} else {
NULL # fallback: sem extração DLNM automática
}
# Indicadores socioeconômicos
caso_socio <- if (file.exists("vignettes-pt/dados/caso_socio.rds")) {
readRDS("vignettes-pt/dados/caso_socio.rds")
} else {
# Mínimo realista para o script funcionar sem a cadeia completa
data.frame(
city = c("Sao Paulo", "Guarulhos", "Santo Andre", "Osasco", "Maua"),
pct_idosos = c(16.2, 12.4, 14.8, 13.1, 11.9),
pct_doenca_cr = c(28.1, 24.3, 26.7, 22.8, 20.5),
hdi = c(0.845, 0.763, 0.815, 0.776, 0.742),
pct_agua = c(97.2, 88.4, 94.1, 90.3, 85.7),
densidade_ubs = c(6.8, 3.2, 5.1, 4.0, 2.9)
)
}Build the three IPCC pillars
Each pillar is supplied as a data.frame with a municipal
identifier column (city_col = "city") and numeric indicator
columns. Indicators missing for a given municipality are filled with
NA and excluded from the pillar’s weighted average, without
forcing complete exclusion.
# ----- Pilar E: Exposição Climática ------------------------------------------
# Fonte: sus_climate_aggregate() (temperatura maxima media, dias de calor P90,
# contagem de ondas de calor por ano)
exposure_df <- data.frame(
city = caso_socio$city,
tmax_media = c(29.8, 31.2, 28.9, 30.1, 31.8), # grau Celsius
dias_calor_p90 = c(52, 68, 45, 58, 72), # dias/ano
ondas_calor = c(4, 8, 3, 6, 9) # eventos/ano
)
# ----- Pilar S: Sensibilidade Populacional -----------------------------------
# Fonte: caso_socio.rds + extração automática de climasus_dlnm (argumento fits)
sensitivity_df <- caso_socio[, c("city", "pct_idosos", "pct_doenca_cr")]
# ----- Pilar AC: Capacidade Adaptativa ---------------------------------------
# Fonte: caso_socio.rds (HDI, cobertura hídrica, densidade UBS)
adaptive_capacity_df <- caso_socio[, c("city", "hdi", "pct_agua", "densidade_ubs")]Fit the Composite Vulnerability Index
sus_mod_vulnerability_index() accepts a
fits argument (a named list of climasus_dlnm
objects) for automatic extraction of the metrics
dlnm_hot_rr, dlnm_cold_rr, and
dlnm_sensitivity_index, which are automatically merged into
the sensitivity pillar.
# Opcional: lista nomeada de climasus_dlnm (um por cidade)
# fits_dlnm <- list(sao_paulo = mod_dlnm) # ajuste por municipio
vi_fit <- sus_mod_vulnerability_index(
exposure_df = exposure_df,
sensitivity_df = sensitivity_df,
adaptive_capacity_df = adaptive_capacity_df,
fits = NULL, # ou: fits_dlnm (lista climasus_dlnm)
city_col = "city",
normalize = "minmax", # "minmax" ou "zscore"
weights = c(tmax_media = 2, # dobrar peso da Tmax
pct_idosos = 2), # dobrar peso da proporção de idosos
pillar_weights = c(exposure = 1.5,
sensitivity = 1.0,
adaptive_capacity = 1.0),
hot_percentile = 0.99,
cold_percentile = 0.01,
lang = "pt",
verbose = TRUE
)
# Inspecionar o resultado
print(vi_fit)The climasus_vi object contains:
| Element | Type | Content |
|---|---|---|
$vi_table |
tibble | CVI, pillar scores, rank, and percentile per city |
$pillar_scores |
tibble (long) | Raw scores for the three pillars per city |
$normalized_indicators |
tibble | Normalized indicators (prefixes exp_,
sen_, ac_) |
$raw_indicators |
tibble | Original indicators without normalization |
$weights |
list | Intra-pillar and inter-pillar weights effectively used |
$gini_coefficient |
numeric | Gini of the CVI (0 = perfect equality) |
$meta |
list | Call parameters, counts, timing |
Fit the SWOT Analysis
sus_mod_swot() aggregates climasus objects from multiple
modules into normalized (0–100) and categorized SWOT quadrants. The
argument breaks = c(25, 50, 75) produces four categories
(Low / Medium / High / Very High) — the default c(33, 66)
produces three categories.
swot_fit <- sus_mod_swot(
vulnerability = vi_fit,
af = mod_af, # climasus_af do Módulo M2 (ou NULL)
burden = NULL, # climasus_burden do Módulo M2 (opcional)
dlnm = mod_dlnm, # climasus_dlnm do Módulo M1 (broadcast)
sensitivity = NULL, # climasus_sensitivity do Módulo M7 (opcional)
score_type = "both", # "numeric", "categorical" ou "both"
breaks = c(25, 50, 75),
labels = c("Baixo", "Médio", "Alto", "Muito Alto"), # 4 cats para 3 breaks
city_col = "city",
lang = "pt",
verbose = TRUE
)
# Visualizar tabela de escores
swot_fit$scoresFunction characteristics
sus_mod_vulnerability_index() — IPCC Vulnerability
Index
Full signature:
sus_mod_vulnerability_index(
exposure_df = NULL,
sensitivity_df = NULL,
adaptive_capacity_df = NULL,
fits = NULL,
city_col = "city",
normalize = "minmax",
weights = NULL,
pillar_weights = c(exposure = 1, sensitivity = 1, adaptive_capacity = 1),
hot_percentile = 0.99,
cold_percentile = 0.01,
lang = "pt",
verbose = TRUE
)Key parameters:
| Argument | Type | Description |
|---|---|---|
exposure_df |
data.frame |
Indicators for the Exposure pillar (higher = more exposed) |
sensitivity_df |
data.frame |
Indicators for the Sensitivity pillar (higher = more sensitive) |
adaptive_capacity_df |
data.frame |
Indicators for the Adaptive Capacity pillar (higher = more adapted) |
fits |
named list of climasus_dlnm
|
Automatic extraction of heat/cold RR and sensitivity index |
city_col |
character |
Name of the municipal identifier column (default
"city") |
normalize |
"minmax" or "zscore"
|
Indicator normalization method |
weights |
named vector | Intra-pillar weights by column name; unlisted columns get weight 1 |
pillar_weights |
named vector
c(exposure, sensitivity, adaptive_capacity)
|
Inter-pillar weights; missing pillars automatically get weight 0 |
hot_percentile / cold_percentile
|
numeric | Quantiles for RR extraction from the DLNM fits |
Return — climasus_vi object:
-
$vi_table: tibble ordered byvi_rank(rank 1 = most vulnerable), with columnsvi_score∈ [0, 1],exposure_score,sensitivity_score,adaptive_capacity_score,vi_rank,vi_percentile. -
$pillar_scores: long tibble withcity,pillar,score(raw score before the AC inversion). -
$normalized_indicators/$raw_indicators: wide tibbles with prefixesexp_,sen_,ac_. -
$weights: list with the intra-pillar and inter-pillar weights effectively used. -
$gini_coefficient: Gini of the CVI distribution. -
$meta: list of parameters, counts, and timestamp.
Available S3 methods: print(),
summary(), tidy() (returns a flat tibble),
coef() (returns a named vector city → vi_score).
sus_mod_plot_vulnerability() — CVI Visualizations
Full signature:
sus_mod_plot_vulnerability(
x,
type = c("ranking", "pillars", "lorenz"),
output_type = c("plot", "table", "all"),
interactive = FALSE,
base_size = 12L,
save_plot = NULL,
lang = c("pt", "en", "es"),
verbose = FALSE
)Plot types (type=):
type |
Description | Data returned in "table"
|
|---|---|---|
"ranking" |
Horizontal lollipop: CVI per city, most vulnerable at the top | $vi_table |
"pillars" |
Horizontal stacked bars: contribution of E / S / AC per city | $pillar_scores |
"lorenz" |
Lorenz curve of CVI inequality with the Gini annotated | $vi_table |
Return: ggplot
(output_type = "plot"), tibble ("table"), or a
named list $plot, $table, $data
("all"). With interactive = TRUE, returns a
plotly widget (requires the plotly
package).
sus_mod_swot() — Climate-Health SWOT Synthesis
Full signature:
sus_mod_swot(
vulnerability = NULL,
af = NULL,
burden = NULL,
dlnm = NULL,
sensitivity = NULL,
score_type = c("both", "numeric", "categorical"),
breaks = c(33, 66),
labels = NULL,
city_col = "city",
lang = c("pt", "en", "es"),
verbose = TRUE
)Indicators per quadrant:
| Quadrant | Source | Extracted indicators |
|---|---|---|
| S Strengths | climasus_vi |
adaptive_capacity_score (high capacity = strength) |
| S Strengths | climasus_af |
100 − total AF% (low burden = strength) |
| S Strengths | climasus_burden |
Inverted burden rank |
| W Weaknesses | climasus_vi |
sensitivity_score (high sensitivity = weakness) |
| W Weaknesses | climasus_af |
Heat AF%; cold AF% |
| W Weaknesses | climasus_sensitivity |
RR inequality across strata |
| O Opportunities | climasus_vi |
100 − CVI percentile (low percentile = window); current exposure inverted |
| T Threats | climasus_vi |
exposure_score; vi_score
|
| T Threats | climasus_dlnm |
Heat RR at P95 (scaled 0–100) |
| T Threats | climasus_burden |
Normalized attributable number |
| T Threats | climasus_sensitivity |
Maximum RR across strata |
Return — climasus_swot object:
-
$scores: tibble with one row per entity; columnsentity,S_score,W_score,O_score,T_score(0–100) and, whenscore_type %in% c("categorical","both"),S_cat,W_cat,O_cat,T_cat; countsn_S,n_W,n_O,n_T. -
$indicators: long tibble with one row per (entity × quadrant × indicator):entity,quadrant,ind_code,indicator,raw_value,norm_score,direction("positive"or"negative"). -
$meta: list withn_entities,n_indicators,inputs_used,score_type,breaks,labels,lang,call_time.
S3 methods: print(),
summary(), tidy() (returns
$scores).
sus_mod_plot_swot() — SWOT Visualizations
Full signature:
sus_mod_plot_swot(
x,
type = c("radar", "matrix", "bar"),
output_type = c("plot", "table", "all"),
interactive = FALSE,
entities = NULL,
top_n = 3L,
base_size = 12L,
save_plot = NULL,
lang = c("pt", "en", "es"),
verbose = FALSE
)Plot types (type=):
type |
Description | Recommended use |
|---|---|---|
"radar" |
Spider/radar chart of the four SWOT scores (0–100) per entity, with overlapping polygons for multi-city comparison | Comparing profiles across municipalities |
"matrix" |
Classic 2×2 chart: numeric score, category, and bullet points of the
leading indicators per quadrant. Shows only one entity (the first in the
entities selection) |
Risk communication for a single municipality |
"bar" |
Grouped horizontal bars of the four SWOT scores per entity | Quick comparison across all municipalities |
Argument top_n (only for
type = "matrix"): maximum number of indicator bullets
displayed per quadrant (default 3).
Return: ggplot or plotly
(output_type = "plot"), tibble ("table"), or a
list $plot, $table ("all").
Reference formulas
Composite Vulnerability Index (IPCC)
The central formula combines the three pillars with the Adaptive Capacity inversion:
where each pillar is the weighted average of the normalized indicators:
Missing indicators are excluded and the remaining weights are renormalized, partially preserving municipalities with incomplete data.
Illustrated results
Vulnerability ranking
The lollipop chart orders municipalities from most (top) to least vulnerable, with the CVI score on the horizontal axis. The Gini Coefficient in the subtitle quantifies the territorial inequality of vulnerability.

Figure 1. Climate-health vulnerability ranking of the RMSP municipalities. Min-max scores on the x-axis; the municipality at the top = most vulnerable (highest CVI). Gini indicates the concentration of risk across municipalities.
Decomposition of the IPCC pillars
The stacked bars allow identification of which pillar dominates the vulnerability of each municipality: Exposure (red), Sensitivity (blue), or Adaptive Capacity (green). Municipalities with balanced pillars indicate multifactorial risk.

Figure 2. Decomposition of the three IPCC pillar scores by municipality, ordered by total CVI (most vulnerable at the top).
Lorenz curve of vulnerability
The Lorenz curve accumulates the proportion of total CVI (y-axis) as a function of the proportion of municipalities (x-axis), from least to most vulnerable. The farther from the diagonal (perfect equality), the greater the concentration of risk in a few municipalities.

Figure 3. Lorenz curve of the Composite Vulnerability Index in the RMSP. The shaded area between the curve and the diagonal of perfect equality (dashed) is proportional to the Gini Coefficient annotated on the plot.
Vulnerability score table
| city | vi_score | exposure_score | sensitivity_score | adaptive_capacity_score | vi_rank | vi_percentile |
|---|---|---|---|---|---|---|
| 350950 | 0.8069 | 0.7717 | 0.7500 | 0.0836 | 1 | 100.0 |
| 351880 | 0.5076 | 0.4375 | 0.5713 | 0.4510 | 2 | 83.3 |
| rmsp | 0.5000 | NA | 0.5000 | NA | 3 | 66.7 |
| 355030 | 0.4317 | 0.4033 | 0.5352 | 0.6291 | 4 | 50.0 |
| 351380 | 0.3617 | 0.2576 | 0.5165 | 0.6369 | 5 | 33.3 |
| 354870 | 0.1561 | 0.1069 | 0.3283 | 0.9421 | 6 | 16.7 |
SWOT profile — Radar
The radar chart shows the four SWOT scores (0–100) for all municipalities simultaneously. Larger polygons (especially in W and T) signal greater fragility; wide polygons in S and O indicate protective assets and intervention opportunities.

Figure 4. SWOT profile by municipality in the RMSP. Axes: Strengths (top), Opportunities (right), Threats (bottom), Weaknesses (left). Scale 0–100.
SWOT 2×2 chart — Most vulnerable municipality
The classic 2×2 chart displays, for the municipality with the highest CVI, the numeric score and category of each quadrant, together with the leading indicators (with normalized score) that contributed the most to each quadrant.

Figure 5. SWOT 2×2 chart for the most vulnerable municipality in the RMSP. An ideal format for risk communication to municipal managers.
SWOT scores — Comparative bars

Figure 6. Grouped SWOT scores by municipality. Allows simultaneous comparison of Strengths, Weaknesses, Opportunities, and Threats across all municipalities in the RMSP.
SWOT score table
| entity | S_score | n_S | W_score | n_W | O_score | n_O | T_score | n_T | S_cat | W_cat | O_cat | T_cat |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 350950 | 40.44680 | 2 | 6.643333 | 3 | 49.61415 | 2 | 6.898991 | 3 | Cat2 | Cat1 | Cat2 | Cat1 |
| 351880 | 40.63050 | 2 | 6.583767 | 3 | 58.13125 | 2 | 6.687824 | 3 | Cat2 | Cat1 | Cat3 | Cat1 |
| rmsp | 80.81000 | 2 | 6.560000 | 3 | 33.30000 | 2 | 9.809187 | 3 | Cat4 | Cat1 | Cat2 | Cat1 |
| 355030 | 40.71955 | 2 | 6.571733 | 3 | 74.79835 | 2 | 6.651124 | 3 | Cat2 | Cat1 | Cat3 | Cat1 |
| 351380 | 40.72345 | 2 | 6.565500 | 3 | 83.22120 | 2 | 6.579224 | 3 | Cat2 | Cat1 | Cat4 | Cat1 |
| 354870 | 40.87605 | 2 | 6.502767 | 3 | 91.59655 | 2 | 6.460458 | 3 | Cat2 | Cat1 | Cat4 | Cat1 |
References
Andrews, K. (1971). The Concept of Corporate Strategy. Dow Jones-Irwin.
Benmarhnia, T., Deguen, S., Kaufman, J. S., & Smargiassi, A. (2015). Vulnerability to heat-related mortality: a systematic review, meta-analysis, and meta-regression analysis. Epidemiology, 26(6), 781–793. https://doi.org/10.1097/EDE.0000000000000375
Confalonieri, U., Marinho, D., Dias, H., & Malheiros, T. (2009). O índice de vulnerabilidade aos riscos climáticos do Brasil. Parcerias Estratégicas, 27, 161–172.
Cutter, S. L., Boruff, B. J., & Shirley, W. L. (2003). Social vulnerability to environmental hazards. Social Science & Medicine, 56(11), 2301–2322. https://doi.org/10.1016/S0277-9536(02)00605-X
Gasparrini, A., & Armstrong, B. (2013). Attributable risk from distributed lag models. BMC Medical Research Methodology, 13, 3. https://doi.org/10.1186/1471-2288-13-3
Gasparrini, A., et al. (2017). Projections of temperature-related excess mortality under climate change scenarios. The Lancet Planetary Health, 1(9), e360–e367. https://doi.org/10.1016/S2542-5196(17)30156-0
IPCC. (2014). Fifth Assessment Report — Working Group II: Impacts, Adaptation and Vulnerability. Part A: Global and Sectoral Aspects. Chapter 19: Emergent Risks and Key Vulnerabilities. Cambridge University Press. https://doi.org/10.1017/CBO9781107415379
IPCC. (2022). Sixth Assessment Report — Working Group II: Impacts, Adaptation and Vulnerability. Chapter 16: Key Risks across Sectors and Regions. Cambridge University Press. https://doi.org/10.1017/9781009325844
Marengo, J. A., et al. (2022). Vulnerability to climate change in Brazil: current status and future scenarios. International Journal of Climate Change Strategies and Management, 14(2), 133–149.
Turner, B. L., et al. (2003). A framework for vulnerability analysis in sustainability science. PNAS, 100(14), 8074–8079. https://doi.org/10.1073/pnas.1231335100
Navigation
End of the Modeling section. This is the final module in the Modeling series of
climasus4r. The results produced here (mod_vi.rds) can be loaded into final reports and risk communication for managers and decision-makers.
| Previous module | Modeling 07: Spatial and Spatio-Temporal Bayes |
| Tutorial hub | Tutorial Index |
How to reproduce the figures. Run once, from the package root:
Rscript scripts/modelagem_08_vulnerabilidade_swot.R. The script saves the figures invignettes-pt/figuras/(prefixesmodvi_andmodswot_), the tables invignettes-pt/dados/, and the chained vulnerability object (mod_vi.rds).