The plot() method for objects returned by
ei_sens() produces a standard sensitivity contour plot. For
publication-quality figures with more control over styling, labeled
contour lines, and benchmark annotations, a custom ggplot2
implementation is often preferable. This vignette shows a generic
version of such a plot, using the geomtextpath
package for labeled contours and ggrepel
for non-overlapping benchmark labels.
The code below assumes sens is an object returned by
ei_sens() and bench is a benchmarking data
frame from ei_bench(), both filtered to a single outcome of
interest. Both are described in
vignette("sensitivity").
library(ggplot2)
library(geomtextpath)
library(ggrepel)
# --- filter to one outcome --------------------------------------------------
outcome_name = "my_outcome"
d_sens = subset(sens, outcome == outcome_name)
d_bench = subset(bench, outcome == outcome_name)
# clamp any Inf bias values for plotting
d_sens$bias_bound = with(d_sens, ifelse(
is.finite(bias_bound),
bias_bound,
1.5 * max(bias_bound[is.finite(bias_bound)])
))
# --- contour break structure -------------------------------------------------
# major breaks get text labels; semi-major and minor add visual density
contour_exp = -1:1
breaks_minor = 10^c(contour_exp, 2) %x% c(2:4, 6:9)
breaks_semimaj = 10^contour_exp %x% 5
breaks_maj = 10^contour_exp %x% 10
c_col = "#f08f88" # contour line color
# --- build plot --------------------------------------------------------------
ggplot(d_sens, aes(c_predictor, c_outcome)) +
# minor contour lines (no labels)
geom_contour(aes(z = bias_bound), breaks = breaks_minor,
color = c_col, lwd = 0.12) +
# semi-major contour lines (no labels)
geom_contour(aes(z = bias_bound), breaks = breaks_semimaj,
color = c_col, lwd = 0.48) +
# major contour lines with numeric labels
geom_textcontour(
aes(z = bias_bound),
breaks = breaks_maj,
color = c_col, lwd = 0.7,
hjust = 0.55, vjust = 1.25,
halign = "left", size = 3.0,
fontface = "bold", upright = TRUE, straight = TRUE
) +
# a labeled contour for a specific reference value (e.g. the point estimate)
geom_textcontour(
aes(z = bias_bound, label = "Estimated effect"),
breaks = d_sens$estimate[1],
color = "#425682", lwd = 0.7,
hjust = 0.55, vjust = 1.25,
size = 3.0, fontface = "bold"
) +
# benchmark points and labels
geom_point(data = d_bench, size = 0.7) +
geom_text_repel(
aes(label = covariate),
data = d_bench,
hjust = 1.25, nudge_x = 0.002, nudge_y = 0.002,
size = 3
) +
# square-root scale spreads out the lower-left corner
scale_x_continuous(breaks = seq(0, 1, 0.1), transform = "sqrt") +
scale_y_continuous(breaks = seq(0, 1, 0.1), transform = "sqrt") +
coord_cartesian(xlim = 0:1, ylim = 0:1, expand = FALSE) +
labs(
x = bquote(1 - {R^2}[alpha^A ~ "~" ~ alpha]),
y = bquote({R^2}[bar(Y) ~ "~" ~ A ~ "|" ~ bar(X) ~ "," ~ Z]),
title = paste("Sensitivity contour plot:", outcome_name)
) +
theme_bw() +
theme(
panel.grid = element_line(color = "#aaa", linetype = "dotted",
linewidth = 0.24),
panel.grid.minor = element_blank(),
axis.title = element_text(size = 12)
)