## ----setup--------------------------------------------------------------------
#| include: false
library(forrest)


## ----basic--------------------------------------------------------------------
dat <- data.frame(
  predictor = c("Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)",
                "Current smoker", "Physically active"),
  estimate  = c( 0.18, -0.42,  0.11, -0.31,  0.24),
  lower     = c( 0.05, -0.61, -0.04, -0.52,  0.08),
  upper     = c( 0.31, -0.23,  0.26, -0.10,  0.40)
)

forrest(
  dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "predictor",
  xlab     = "Regression coefficient (95% CI)"
)


## ----section------------------------------------------------------------------
#| fig-height: 5
sub_dat <- data.frame(
  subgroup = c("Sex",    "Sex",
               "Age group", "Age group", "Age group"),
  label    = c("Female", "Male",
               "30\u201349 years", "50\u201369 years", "70+ years"),
  estimate = c(-0.38,  0.12,  0.22, -0.15, -0.41),
  lower    = c(-0.58, -0.08,  0.02, -0.38, -0.66),
  upper    = c(-0.18,  0.32,  0.42,  0.08, -0.16)
)

forrest(
  sub_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "label",
  section  = "subgroup",
  xlab     = "Regression coefficient (95% CI)",
  header   = "Subgroup"
)


## ----subsection---------------------------------------------------------------
#| fig-height: 7
nested_dat <- data.frame(
  domain    = c(
    "Physical environment", "Physical environment", "Physical environment",
    "Physical environment", "Physical environment",
    "Social environment",   "Social environment",
    "Social environment",   "Social environment"
  ),
  type      = c(
    "Air quality", "Air quality",
    "Urban form",  "Urban form",  "Urban form",
    "Support",     "Support",
    "Deprivation", "Deprivation"
  ),
  predictor = c(
    "PM2.5 (per 10 \u03bcg/m\u00b3)", "NO2 (per 10 ppb)",
    "Green space (%)", "Walkability", "Noise (per 10 dB)",
    "Social cohesion", "Social isolation",
    "Area deprivation", "Employment rate"
  ),
  estimate  = c(-0.18,  0.12, -0.22,  0.15, -0.08,
                -0.11,  0.09,  0.05, -0.03),
  lower     = c(-0.38, -0.08, -0.42, -0.05, -0.28,
                -0.31, -0.09, -0.12, -0.20),
  upper     = c( 0.02,  0.32, -0.02,  0.35,  0.12,
                 0.09,  0.27,  0.22,  0.14)
)

forrest(
  nested_dat,
  estimate   = "estimate",
  lower      = "lower",
  upper      = "upper",
  label      = "predictor",
  section    = "domain",
  subsection = "type",
  xlab       = "Mean difference in SBP (mmHg, 95% CI)"
)


## ----summary------------------------------------------------------------------
sex_dat <- data.frame(
  label    = c("Female", "Male", "Overall"),
  estimate = c(-0.42, -0.29, -0.36),
  lower    = c(-0.61, -0.48, -0.50),
  upper    = c(-0.23, -0.10, -0.22),
  is_sum   = c(FALSE, FALSE, TRUE)
)

forrest(
  sex_dat,
  estimate   = "estimate",
  lower      = "lower",
  upper      = "upper",
  label      = "label",
  is_summary = "is_sum",
  xlab       = "Regression coefficient (95% CI)",
  title      = "Association of female sex with SBP by subgroup"
)


## ----grouped------------------------------------------------------------------
#| fig-height: 5
grp_dat <- data.frame(
  predictor = rep(
    c("Air pollution (PM2.5)", "Noise exposure",
      "Green space access", "Walkability index",
      "Food environment"), 2
  ),
  domain    = rep(c("Physical environment", "Social environment"),
                  each = 5),
  estimate  = c(-0.18,  0.12, -0.22,  0.15, -0.08,
                 0.05, -0.03,  0.09, -0.11,  0.14),
  lower     = c(-0.38, -0.08, -0.42, -0.05, -0.28,
                -0.12, -0.20, -0.09, -0.31, -0.04),
  upper     = c( 0.02,  0.32, -0.02,  0.35,  0.12,
                 0.22,  0.14,  0.27,  0.09,  0.32)
)

forrest(
  grp_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "predictor",
  group    = "domain",
  xlab     = "Mean difference in SBP (mmHg, 95% CI)"
)


## ----dodge--------------------------------------------------------------------
#| fig-height: 4
#| fig-width: 9
dodge_dat <- data.frame(
  exposure = rep(
    c("PM2.5 (per 10 \u03bcg/m\u00b3)", "NO2 (per 10 ppb)",
      "Noise (per 10 dB)", "Green space (%)", "Walkability"),
    each = 2
  ),
  period   = rep(c("Childhood", "Adulthood"), 5),
  estimate = c(
     0.14, -0.05,  0.08,  0.12, -0.19, -0.06,  0.11, -0.03,  0.07,  0.10
  ),
  lower    = c(
    -0.10, -0.26, -0.09, -0.08, -0.40, -0.25, -0.05, -0.12, -0.14, -0.09
  ),
  upper    = c(
     0.38,  0.16,  0.25,  0.32,  0.02,  0.13,  0.27,  0.06,  0.28,  0.29
  )
)

forrest(
  dodge_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "exposure",
  group    = "period",
  dodge    = TRUE,
  header   = "Environmental exposure",
  ref_line = 0,
  xlab     = "Mean difference in SBP (mmHg, 95% CI)"
)


## ----dodge-cols---------------------------------------------------------------
#| fig-height: 4
#| fig-width: 11
# Add per-condition formatted text columns to the long-format data
dodge_dat$est_ci     <- sprintf("%.2f (%.2f, %.2f)",
                                dodge_dat$estimate,
                                dodge_dat$lower,
                                dodge_dat$upper)
dodge_dat$text_child <- ifelse(
  dodge_dat$period == "Childhood", dodge_dat$est_ci, ""
)
dodge_dat$text_adult <- ifelse(
  dodge_dat$period == "Adulthood", dodge_dat$est_ci, ""
)

forrest(
  dodge_dat,
  estimate      = "estimate",
  lower         = "lower",
  upper         = "upper",
  label         = "exposure",
  group         = "period",
  dodge         = TRUE,
  cols_by_group = TRUE,
  cols          = c("Childhood (95% CI)" = "text_child",
                    "Adulthood (95% CI)" = "text_adult"),
  widths        = c(2.8, 3.5, 2.2, 2.2),
  header        = "Environmental exposure",
  ref_line      = 0,
  xlab          = "Mean difference in SBP (mmHg, 95% CI)"
)


## ----shape--------------------------------------------------------------------
#| fig-height: 5
#| fig-width: 9
shape_dat <- data.frame(
  exposure = rep(
    c("PM2.5 (per 10 \u03bcg/m\u00b3)", "NO2 (per 10 ppb)",
      "Noise (per 10 dB)", "Green space (%)", "Walkability"),
    each = 4
  ),
  period   = rep(rep(c("Childhood", "Adulthood"), each = 2), 5),
  sex      = rep(c("Female", "Male"), 10),
  estimate = c(
     0.22, -0.08, -0.10,  0.18,
     0.11,  0.05,  0.00,  0.14,
    -0.31,  0.06, -0.09, -0.02,
     0.08,  0.12, -0.04,  0.03,
     0.17, -0.06,  0.22,  0.01
  ),
  lower    = c(
    -0.20, -0.38, -0.28, -0.14,
    -0.12, -0.22, -0.22, -0.14,
    -0.56, -0.24, -0.38, -0.30,
    -0.18, -0.14, -0.22, -0.15,
    -0.09, -0.38, -0.04, -0.27
  ),
  upper    = c(
     0.64,  0.22,  0.08,  0.50,
     0.34,  0.32,  0.22,  0.42,
    -0.06,  0.36,  0.20,  0.26,
     0.34,  0.38,  0.14,  0.21,
     0.43,  0.26,  0.48,  0.29
  )
)

forrest(
  shape_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "exposure",
  group    = "period",
  shape    = "sex",
  dodge    = TRUE,
  ref_line = 0,
  xlab     = "Mean difference in SBP (mmHg, 95% CI)"
)


## ----text-cols----------------------------------------------------------------
#| fig-height: 4.5
#| fig-width: 10
tc_dat <- data.frame(
  predictor = c("Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)",
                "Current smoker", "Physically active"),
  estimate  = c( 0.18, -0.42,  0.11, -0.31,  0.24),
  lower     = c( 0.05, -0.61, -0.04, -0.52,  0.08),
  upper     = c( 0.31, -0.23,  0.26, -0.10,  0.40),
  coef_ci   = c(
    " 0.18 ( 0.05,  0.31)",
    "-0.42 (-0.61, -0.23)",
    " 0.11 (-0.04,  0.26)",
    "-0.31 (-0.52, -0.10)",
    " 0.24 ( 0.08,  0.40)"
  ),
  pval = c("0.006", "<0.001", "0.148", "0.003", "0.009")
)

forrest(
  tc_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "predictor",
  header   = "Predictor",
  cols     = c("Coef (95% CI)" = "coef_ci", "P-value" = "pval"),
  widths   = c(2.8, 4, 2.5, 1.2),
  xlab     = "Regression coefficient (95% CI)"
)


## ----section-cols-------------------------------------------------------------
#| fig-height: 5
#| fig-width: 11
sc_dat <- data.frame(
  subgroup  = c("Sex",    "Sex",   "Age group", "Age group", "Age group"),
  label     = c("Female", "Male",  "30\u201349 y", "50\u201369 y", "70+ y"),
  estimate  = c(-0.38,  0.12,  0.22, -0.15, -0.41),
  lower     = c(-0.58, -0.08,  0.02, -0.38, -0.66),
  upper     = c(-0.18,  0.32,  0.42,  0.08, -0.16),
  coef_ci   = c(
    "-0.38 (-0.58, -0.18)",
    " 0.12 (-0.08,  0.32)",
    " 0.22 ( 0.02,  0.42)",
    "-0.15 (-0.38,  0.08)",
    "-0.41 (-0.66, -0.16)"
  ),
  # Constant within each section — section header will show this value
  k_text    = c("k = 2", "k = 2", "k = 3", "k = 3", "k = 3")
)

forrest(
  sc_dat,
  estimate     = "estimate",
  lower        = "lower",
  upper        = "upper",
  label        = "label",
  section      = "subgroup",
  section_cols = c("k" = "k_text"),
  header       = "Subgroup",
  cols         = c("Coef (95% CI)" = "coef_ci", "k" = "k_text"),
  widths       = c(2.5, 4, 2.5, 1.2),
  xlab         = "Regression coefficient (95% CI)"
)


## ----stripe-------------------------------------------------------------------
#| fig-height: 6
stripe_dat <- data.frame(
  label    = c(
    "Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)",
    "Current smoker", "Physically active",
    "Alcohol intake", "Sleep duration", "Depressive symptoms"
  ),
  estimate = c( 0.42, -0.18,  0.31, -0.07,  0.25, -0.12,  0.19, -0.34),
  lower    = c( 0.22, -0.38,  0.12, -0.24,  0.06, -0.30,  0.01, -0.52),
  upper    = c( 0.62,  0.02,  0.50,  0.10,  0.44,  0.06,  0.37, -0.16)
)

forrest(
  stripe_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "label",
  stripe   = TRUE,
  xlab     = "Regression coefficient (95% CI)"
)


## ----themes-minimal-----------------------------------------------------------
#| fig-height: 3.5
theme_dat <- data.frame(
  predictor = c("Age (per 10 y)", "Female sex", "BMI (per 5 kg/m\u00b2)"),
  estimate  = c( 0.18, -0.42,  0.11),
  lower     = c( 0.05, -0.61, -0.04),
  upper     = c( 0.31, -0.23,  0.26)
)

# "minimal" theme — lighter gridlines and softer reference line
forrest(
  theme_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "predictor",
  theme    = "minimal",
  title    = 'theme = "minimal"',
  xlab     = "Coefficient (95% CI)"
)


## ----themes-classic-----------------------------------------------------------
#| fig-height: 3.5
# "classic" theme — dotted gridlines and solid black reference line
forrest(
  theme_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "predictor",
  theme    = "classic",
  title    = 'theme = "classic"',
  xlab     = "Coefficient (95% CI)"
)


## ----themes-custom------------------------------------------------------------
#| fig-height: 3.5
# Custom theme — override individual style keys
forrest(
  theme_dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "predictor",
  theme    = list(ref_col = "#e63946", ref_lty = 1L, grid_col = "#eeeeee"),
  title    = "Custom theme (red reference line)",
  xlab     = "Coefficient (95% CI)"
)


## ----save---------------------------------------------------------------------
#| eval: false
# save_forrest(
#   file   = "my_forest_plot.pdf",
#   plot   = function() {
#     forrest(
#       dat,
#       estimate = "estimate",
#       lower    = "lower",
#       upper    = "upper",
#       label    = "predictor",
#       xlab     = "Regression coefficient (95% CI)"
#     )
#   },
#   width  = 8,
#   height = 5
# )

