Exposure-response relationships are often non-linear. A small change in an environmental exposure may correspond to little change in the expected disease response in one region of the fitted curve but a much larger change in another.
Effect summaries describe the direction and magnitude of modeled associations. Sensitivity analysis addresses a complementary question:
Where does the model-predicted disease response change most rapidly as an exposure changes?
EpiExposure provides tools for examining:
What you will learn. This tutorial shows how to generate controlled exposure gradients, predict disease responses along those gradients, calculate local sensitivity and elasticity, and identify regions in which the fitted response changes most rapidly.
Sensitivity results describe mathematical features of the fitted model. They do not automatically establish biological thresholds, causal intervention points, or management recommendations. Such interpretations require biological validation and decision criteria appropriate to the pathosystem.
This section uses the same example dataset and DLNM specification introduced in the previous tutorials.
Define the exposure-lag structures:
cb <- define_exposures(
data = epi_data,
vars = c(
"tmean",
"rain",
"wetness"
),
max_lag = 85,
df_var = 3,
df_lag = 2
)Build the epidemic-level design:
Prepare the disease response:
Fit the DLNM:
fit <- fit_epidlnm(
data = dat,
model_engine = "glmmTMB",
family = "beta",
random_effect = NULL,
epiexposure_spec = attr(
cb,
"spec"
)
)The fitted model is now used to predict the expected disease response along controlled environmental gradients.
The Understanding Effects section introduced lag-specific, period-specific, and cumulative summaries of the fitted exposure-lag-response relationship.
Sensitivity analysis provides a different view. Rather than summarizing the magnitude of an effect at an exposure-lag combination, it estimates how rapidly the predicted response changes along a selected exposure gradient.
Conceptually:
effect analysis
→ What modeled contrast is associated with an exposure?
sensitivity analysis
→ How rapidly does the predicted response change as the exposure changes?
The two approaches are complementary. A region can have a relatively large predicted response but low sensitivity if the curve is locally flat. A region with a moderate predicted response can have high sensitivity if the curve is changing rapidly.
The sensitivity workflow uses simulate_ranges() and
simulate_scenarios() to create controlled exposure
gradients.
In this section, these functions are used specifically to evaluate one environmental variable across a sequence of values while the remaining variables are held constant.
The broader use of simulation tools for constructing complete exposure profiles, structured events, and multivariable scenarios is covered in the Simulation and Prediction section.
First, define epidemiological lag periods:
periods <- define_periods(
max_lag = 85,
cuts = c(
20,
40,
60
),
prefix = "Period"
)
periods
#> period lag_start lag_end
#> 1 Period1 0 20
#> 2 Period2 21 40
#> 3 Period3 41 60
#> 4 Period4 61 85These periods divide the retrospective lag interval into four sections.
Remember that lag order is retrospective:
smaller lag → closer to disease assessment
larger lag → earlier exposure condition
The following scenario grid evaluates mean temperature from 18 to 34 °C while holding rainfall and leaf wetness constant:
temp_range <- simulate_ranges(
periods = periods,
vary = list(
rain = 5,
wetness = 10,
tmean = seq(
18,
34,
by = 0.5
)
),
scenario_type = "grid",
scenario_var = "tmean"
)This is a controlled model-based gradient. It does not represent additional observed data.
temp_predictions <- simulate_scenarios(
fit = fit,
scenarios = temp_range,
data = epi_data,
uncertainty = TRUE,
output = "summary",
n_samples = 100,
seed = 123
)The predictions from the fitted Beta model are returned as proportions. For visualization, they are converted to percentages:
response_curve <- temp_predictions |>
dplyr::transmute(
value = tmean,
prediction = prediction * 100,
lower = prediction_lower * 100,
upper = prediction_upper * 100
) |>
dplyr::arrange(
value
)Inspect the response curve:
| value | prediction | lower | upper |
|---|---|---|---|
| 18.0 | 60.494 | 39.115 | 81.108 |
| 18.5 | 57.796 | 38.299 | 76.875 |
| 19.0 | 54.725 | 37.171 | 72.546 |
| 19.5 | 52.903 | 36.369 | 68.435 |
| 20.0 | 52.225 | 36.226 | 66.500 |
| 20.5 | 51.628 | 36.636 | 66.483 |
| 21.0 | 52.329 | 37.890 | 67.138 |
| 21.5 | 53.978 | 39.868 | 68.476 |
| 22.0 | 56.220 | 42.945 | 70.361 |
| 22.5 | 58.697 | 47.244 | 72.219 |
ggplot(
response_curve,
aes(
x = value,
y = prediction
)
) +
geom_ribbon(
aes(
ymin = lower,
ymax = upper
),
fill = "#C44E52",
alpha = 0.18
) +
geom_line(
linewidth = 1,
color = "#C44E52"
) +
theme_bw() +
labs(
x = "Mean temperature (°C)",
y = "Expected disease response (%)",
title = "Predicted response along the temperature gradient"
)The line represents the central expected response under the fitted model. The ribbon represents uncertainty associated with the fitted model coefficients.
The curve should not be interpreted as a causal dose-response relationship unless the study design and assumptions support that interpretation.
Prediction curves show the expected response along an exposure gradient.
Sensitivity curves describe the local slope of those prediction curves.
For a response function \(f(x)\), local sensitivity is conceptually related to:
\[ S(x) = \frac{\partial f(x)}{\partial x} \]
where \(x\) is the exposure value.
A large absolute sensitivity indicates that the predicted response is changing rapidly at that point of the fitted curve. A sensitivity near zero indicates a locally flat region.
temp_sensitivity <- epi_sensitivity(
data = response_curve,
x = "value",
y = "prediction",
scenario_var = NULL,
elasticity = TRUE,
critical = TRUE,
k = 3
)Inspect the resulting columns:
| value | prediction | lower | upper | sensitivity | sensitivity_curve_value | elasticity | critical | critical_type | critical_x |
|---|---|---|---|---|---|---|---|---|---|
| 18.0 | 60.4939 | 39.1146 | 81.1078 | 9.2108 | 37.3974 | 4.4333 | FALSE | NA | NA |
| 18.5 | 57.7958 | 38.2991 | 76.8746 | 9.1765 | 41.9971 | 4.0423 | FALSE | NA | NA |
| 19.0 | 54.7253 | 37.1710 | 72.5464 | 9.0736 | 46.5625 | 3.7025 | FALSE | NA | NA |
| 19.5 | 52.9027 | 36.3691 | 68.4354 | 8.9022 | 51.0593 | 3.3998 | FALSE | NA | NA |
| 20.0 | 52.2246 | 36.2260 | 66.4998 | 8.6621 | 55.4532 | 3.1241 | FALSE | NA | NA |
| 20.5 | 51.6278 | 36.6358 | 66.4830 | 8.3535 | 59.7100 | 2.8680 | FALSE | NA | NA |
| 21.0 | 52.3285 | 37.8897 | 67.1383 | 7.9763 | 63.7953 | 2.6256 | FALSE | NA | NA |
| 21.5 | 53.9778 | 39.8684 | 68.4755 | 7.5305 | 67.6749 | 2.3924 | FALSE | NA | NA |
| 22.0 | 56.2202 | 42.9446 | 70.3610 | 7.0161 | 71.3144 | 2.1644 | FALSE | NA | NA |
| 22.5 | 58.6974 | 47.2438 | 72.2187 | 6.4332 | 74.6796 | 1.9382 | FALSE | NA | NA |
Positive sensitivity indicates that the expected disease response increases locally as the exposure increases.
Negative sensitivity indicates that the expected disease response decreases locally as the exposure increases.
Values near zero indicate a locally flat region of the model-predicted response curve.
Sensitivity describes the local slope of the prediction curve. It should not automatically be interpreted as disease risk or as a causal effect of changing the exposure.
ggplot(
temp_sensitivity,
aes(
x = value,
y = sensitivity
)
) +
geom_hline(
yintercept = 0,
color = "grey60",
linetype = "dashed"
) +
geom_line(
linewidth = 1,
color = "#C44E52"
) +
theme_bw() +
labs(
x = "Mean temperature (°C)",
y = "Local sensitivity",
title = "Sensitivity along the temperature gradient"
)The sign describes the direction of local change, whereas the absolute magnitude describes how rapidly the prediction changes.
Sensitivity measures the absolute local rate of change in the predicted response with respect to an exposure.
Elasticity expresses the local response change relative to the current exposure and response scales.
Conceptually, elasticity can be represented as:
\[ E(x) = \frac{\partial f(x)}{\partial x} \frac{x}{f(x)} \]
It addresses the question:
What proportional change in the expected disease response is associated with a proportional change in the exposure at this point of the fitted curve?
Elasticity is dimensionless, which can facilitate comparisons across variables measured in different units.
However, elasticity may become unstable when the exposure or predicted response is close to zero. It should be interpreted cautiously in those regions.
ggplot(
temp_sensitivity,
aes(
x = value,
y = elasticity
)
) +
geom_hline(
yintercept = 0,
color = "grey60",
linetype = "dashed"
) +
geom_line(
linewidth = 1,
color = "#4C72B0"
) +
theme_bw() +
labs(
x = "Mean temperature (°C)",
y = "Elasticity",
title = "Elasticity along the temperature gradient"
)Elasticity should be interpreted together with the underlying prediction and sensitivity curves. A large elasticity value can arise from a small denominator rather than from a large absolute response change.
When:
epi_sensitivity() identifies points or regions that
satisfy the function’s criterion for comparatively strong local response
change.
These locations are model-derived critical regions. They may suggest exposure ranges that deserve closer biological investigation, but they should not automatically be described as biological thresholds.
A biological or management threshold requires additional justification, such as:
critical_temperature <- temp_sensitivity |>
dplyr::filter(
critical
)
critical_temperature
#> value prediction lower upper sensitivity sensitivity_curve_value
#> 1 26 90.32056 86.96177 93.959 0.4321628 87.67416
#> elasticity critical critical_type critical_x
#> 1 0.128159 TRUE local_maximum 26.20327ggplot(
temp_sensitivity,
aes(
x = value,
y = sensitivity
)
) +
geom_hline(
yintercept = 0,
color = "grey60",
linetype = "dashed"
) +
geom_line(
linewidth = 0.9,
color = "#C44E52"
) +
geom_point(
data = critical_temperature,
color = "#B22222",
size = 2.8
) +
theme_bw() +
labs(
x = "Mean temperature (°C)",
y = "Local sensitivity",
title = "Model-derived critical regions along the temperature gradient"
)The highlighted points indicate comparatively strong local changes
according to the criterion used by epi_sensitivity(). They
do not, by themselves, establish biologically validated thresholds.
Sensitivity analyses can also be conducted for rainfall and leaf wetness.
The following examples evaluate one exposure at a time while holding the other environmental variables constant.
Sample-level predictions are requested so that sensitivity can be evaluated across uncertainty realizations:
Rainfall and leaf wetness are measured on different scales. Therefore, they should not be placed on a shared exposure axis without preserving their original units.
Create a common exposure-value column and retain the variable identifier:
sens_rain_plot <- sens_rain |>
dplyr::mutate(
variable = "Rainfall",
exposure_value = rain
)
sens_wetness_plot <- sens_wetness |>
dplyr::mutate(
variable = "Leaf wetness",
exposure_value = wetness
)
combined_sensitivity <- dplyr::bind_rows(
sens_rain_plot,
sens_wetness_plot
)ggplot(
combined_sensitivity,
aes(
x = exposure_value,
y = sensitivity,
group = sample
)
) +
geom_hline(
yintercept = 0,
color = "grey60",
linetype = "dashed"
) +
geom_line(
alpha = 0.10,
linewidth = 0.35,
color = "#4C72B0"
) +
facet_wrap(
vars(
variable
),
scales = "free_x"
) +
theme_bw() +
labs(
x = "Exposure value",
y = "Local sensitivity",
title = "Sensitivity across environmental gradients"
)Each line represents one uncertainty realization. The collection of lines shows how coefficient uncertainty propagates into the estimated sensitivity curves.
If the sample identifier returned by
simulate_scenarios() has a different column name,
replace:
with the corresponding sample-identification column.
Sample-level sensitivity results can be summarized at each exposure value.
sensitivity_summary <- combined_sensitivity |>
dplyr::group_by(
variable,
exposure_value
) |>
dplyr::summarise(
sensitivity_median = stats::median(
sensitivity,
na.rm = TRUE
),
sensitivity_lower = stats::quantile(
sensitivity,
probs = 0.025,
na.rm = TRUE
),
sensitivity_upper = stats::quantile(
sensitivity,
probs = 0.975,
na.rm = TRUE
),
.groups = "drop"
)Inspect the summaries:
| variable | exposure_value | sensitivity_median | sensitivity_lower | sensitivity_upper |
|---|---|---|---|---|
| Leaf wetness | 0.0 | -0.0241 | -0.0455 | -0.0053 |
| Leaf wetness | 0.5 | -0.0236 | -0.0453 | -0.0047 |
| Leaf wetness | 1.0 | -0.0225 | -0.0449 | -0.0037 |
| Leaf wetness | 1.5 | -0.0205 | -0.0432 | -0.0019 |
| Leaf wetness | 2.0 | -0.0175 | -0.0406 | 0.0006 |
| Leaf wetness | 2.5 | -0.0136 | -0.0366 | 0.0038 |
| Leaf wetness | 3.0 | -0.0086 | -0.0312 | 0.0078 |
| Leaf wetness | 3.5 | -0.0028 | -0.0244 | 0.0125 |
| Leaf wetness | 4.0 | 0.0036 | -0.0165 | 0.0180 |
| Leaf wetness | 4.5 | 0.0107 | -0.0074 | 0.0241 |
ggplot(
sensitivity_summary,
aes(
x = exposure_value,
y = sensitivity_median
)
) +
geom_hline(
yintercept = 0,
color = "grey60",
linetype = "dashed"
) +
geom_ribbon(
aes(
ymin = sensitivity_lower,
ymax = sensitivity_upper
),
fill = "#4C72B0",
alpha = 0.18
) +
geom_line(
linewidth = 0.9,
color = "#4C72B0"
) +
facet_wrap(
vars(
variable
),
scales = "free_x"
) +
theme_bw() +
labs(
x = "Exposure value",
y = "Local sensitivity",
title = "Summarized sensitivity across environmental gradients"
)The uncertainty interval describes uncertainty propagated from the fitted model into the sensitivity calculation. It does not include uncertainty in the scenario values or additional observation-level variability.
Absolute sensitivity values depend on the units of both the exposure and the predicted response.
For example:
Consequently, the numerical magnitudes of raw sensitivity should not be compared directly across variables without considering their units and scales.
Elasticity can facilitate proportional comparisons because it is dimensionless. However, elasticity can be unstable near zero exposure or zero predicted response.
A defensible comparison should therefore consider:
Sensitivity analysis can help identify model-derived regions that merit closer attention, but it does not automatically define a management rule.
Potential applications include:
A decision-support interpretation should combine sensitivity with additional information, including:
High sensitivity is not automatically high disease. Sensitivity describes the local slope of the predicted response curve. A region can have high sensitivity but a moderate predicted response, or high predicted disease but low sensitivity if the response curve has reached a plateau.
Suppose the temperature sensitivity analysis indicates:
Under the fitted model, the expected disease response changes most rapidly along the 24–28 °C portion of the evaluated temperature gradient.
This region may deserve closer monitoring or biological investigation. However, high sensitivity alone does not establish a management threshold.
A management interpretation should also consider:
Before reporting sensitivity or elasticity results, verify:
This section demonstrated how EpiExposure can be used to
examine local changes along model-predicted response curves.
The sensitivity workflow consists of:
controlled exposure gradient
↓
predicted disease-response curve
↓
local sensitivity
↓
elasticity
↓
model-derived critical regions
The principal tools are:
simulate_ranges() for creating controlled exposure
gradients;simulate_scenarios() for predicting responses along
those gradients;epi_sensitivity() for calculating sensitivity,
elasticity, and critical regions.Sensitivity analysis complements the effect summaries introduced in the Understanding Effects section
Lag-specific and period-specific effects describe the fitted exposure-lag association, whereas sensitivity describes how rapidly a predicted response changes along a selected environmental gradient.
Sensitivity and elasticity are model-derived quantities. Their use in decision support requires biological interpretation, uncertainty assessment, and decision criteria appropriate to the pathosystem.
The next section, Simulation and Prediction, expands from controlled one-variable gradients to complete hypothetical exposure profiles and multivariable scenarios.
It introduces:
simulate_exposures() for generating complete
chronological profiles;simulate_ranges() for constructing candidate exposure
combinations;simulate_scenarios() for predicting across scenario
grids;predict_outcomes() for complete exposure profiles;compare_exposures() for comparing environmental
profiles;compare_predictions() for comparing their expected
disease outcomes.These tools allow researchers to investigate exposure timing, construct alternative environmental profiles, propagate parameter uncertainty, and compare model-based disease predictions.