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


## ----starting-data------------------------------------------------------------
meta <- data.frame(
  study  = c(
    "Chen (2016)", "Ibrahim (2022)",
    "Bauer (2015)", "Evans (2018)", "Garcia (2020)", "Jensen (2023)",
    "Fuentes (2019)"
  ),
  region = c(
    "Asia",   "Asia",
    "Europe", "Europe", "Europe", "Europe",
    "Latin America"
  ),
  or     = c(1.081, 1.092, 1.095, 1.057, 1.086, 1.070, 1.116),
  lower  = c(1.038, 1.052, 1.058, 1.019, 1.050, 1.036, 1.063),
  upper  = c(1.126, 1.134, 1.134, 1.096, 1.123, 1.105, 1.171),
  weight = c(2065,  1736,  816,   1041,  1479,  918,   567),
  is_sum = c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE),
  or_text = sprintf("%.2f (%.2f\u2013%.2f)",
                    c(1.081, 1.092, 1.095, 1.057, 1.086, 1.070, 1.116),
                    c(1.038, 1.052, 1.058, 1.019, 1.050, 1.036, 1.063),
                    c(1.126, 1.134, 1.134, 1.096, 1.123, 1.105, 1.171))
)
meta


## ----plain--------------------------------------------------------------------
forrest(
  meta,
  estimate  = "or",
  lower     = "lower",
  upper     = "upper",
  label     = "study",
  weight    = "weight",
  log_scale = TRUE,
  ref_line  = 1,
  xlab      = "OR (95% CI)"
)


## ----build-sections-call------------------------------------------------------
# build_sections() is an internal function; access via :::
expanded <- forrest:::build_sections(
  df             = meta,
  estimate       = "or",
  lower          = "lower",
  upper          = "upper",
  label          = "study",
  is_summary     = "is_sum",
  weight         = "weight",
  section        = "region",
  subsection     = NULL,
  section_indent = TRUE,
  section_spacer = TRUE,
  cols           = "or_text",
  section_cols   = NULL
)


## ----expanded-df--------------------------------------------------------------
expanded$df[, c("study", "region", "or", "is_sum", "or_text")]


## ----expanded-flags-----------------------------------------------------------
data.frame(
  study              = expanded$df$study,
  is_section_header  = expanded$is_section_header,
  is_subsection_hdr  = expanded$is_subsection_header,
  is_spacer          = expanded$is_spacer
)


## ----section-plot-------------------------------------------------------------
#| fig-height: 7
forrest(
  meta,
  estimate  = "or",
  lower     = "lower",
  upper     = "upper",
  label     = "study",
  section   = "region",
  weight    = "weight",
  log_scale = TRUE,
  ref_line  = 1,
  xlab      = "OR (95% CI)"
)


## ----subsection-data----------------------------------------------------------
meta2 <- data.frame(
  region = c("Europe", "Europe", "Europe", "Europe", "Asia", "Asia"),
  design = c("Cohort", "Cohort", "Case-control", "Case-control",
             "Cohort", "Case-control"),
  study  = c("Bauer (2015)", "Evans (2018)",
             "Garcia (2020)", "Jensen (2023)",
             "Chen (2016)", "Ibrahim (2022)"),
  or     = c(1.095, 1.057, 1.086, 1.070, 1.081, 1.092),
  lower  = c(1.058, 1.019, 1.050, 1.036, 1.038, 1.052),
  upper  = c(1.134, 1.096, 1.123, 1.105, 1.126, 1.134)
)


## ----subsection-expanded------------------------------------------------------
exp2 <- forrest:::build_sections(
  df           = meta2,
  estimate     = "or",
  lower        = "lower",
  upper        = "upper",
  label        = "study",
  is_summary   = NULL,
  weight       = NULL,
  section      = "region",
  subsection   = "design",
  section_indent = TRUE,
  section_spacer = TRUE
)

data.frame(
  study               = exp2$df$study,
  is_section_header   = exp2$is_section_header,
  is_subsection_header = exp2$is_subsection_header,
  is_spacer           = exp2$is_spacer
)


## ----subsection-plot----------------------------------------------------------
#| fig-height: 7
forrest(
  meta2,
  estimate   = "or",
  lower      = "lower",
  upper      = "upper",
  label      = "study",
  section    = "region",
  subsection = "design",
  log_scale  = TRUE,
  ref_line   = 1,
  xlab       = "OR (95% CI)"
)


## ----row-types----------------------------------------------------------------
df  <- expanded$df
est <- as.numeric(df$or)
is_sum    <- as.logical(df$is_sum)
is_struct <- expanded$is_section_header |
             expanded$is_subsection_header |
             expanded$is_spacer
is_ref    <- is.na(est) & !is_sum & !is_struct
is_bold   <- (expanded$is_section_header |
              expanded$is_subsection_header) &
             nchar(trimws(df$study)) > 0L

data.frame(
  study      = df$study,
  is_sum     = is_sum,
  is_struct  = is_struct,
  is_ref     = is_ref,
  is_bold    = is_bold,
  CI_drawn   = !is_sum & !is_struct & !is_ref & !is.na(est)
)


## ----dodge-no-dodge-----------------------------------------------------------
lbl       <- as.character(expanded$df$study)
group_ids <- forrest:::compute_dodge_groups(lbl, is_struct)
n_vis     <- max(group_ids)
# y slot for each row (top = n_vis, bottom = 1)
row_y     <- (n_vis + 1L) - group_ids

data.frame(study = lbl, group_id = group_ids, y = row_y)


## ----dodge-example-data-------------------------------------------------------
dodge_ex <- data.frame(
  label    = rep(c("Asia", "Europe"), each = 2),
  method   = rep(c("Cohort", "Case-control"), 2),
  or       = c(1.08, 1.05, 1.09, 1.07),
  lower    = c(1.04, 1.01, 1.05, 1.03),
  upper    = c(1.13, 1.09, 1.14, 1.11)
)


## ----dodge-example-groups-----------------------------------------------------
lbl2 <- as.character(dodge_ex$label)
grp2 <- forrest:::compute_dodge_groups(lbl2, rep(FALSE, nrow(dodge_ex)))

dodge_amt <- 0.25
n_vis2    <- max(grp2)
grp_cy    <- (n_vis2 + 1L) - seq_len(n_vis2)

row_y2 <- numeric(nrow(dodge_ex))
for (g in seq_len(n_vis2)) {
  idx     <- which(grp2 == g)
  k       <- length(idx)
  offsets <- seq(-(k - 1L) / 2, (k - 1L) / 2, length.out = k) * dodge_amt
  row_y2[idx] <- grp_cy[g] + offsets
}

data.frame(
  label    = lbl2,
  method   = dodge_ex$method,
  group_id = grp2,
  y        = row_y2
)


## ----dodge-plot---------------------------------------------------------------
forrest(
  dodge_ex,
  estimate = "or",
  lower    = "lower",
  upper    = "upper",
  label    = "label",
  group    = "method",
  dodge    = TRUE,
  log_scale = TRUE,
  ref_line  = 1,
  xlab      = "OR (95% CI)"
)


## ----group-colors-------------------------------------------------------------
forrest:::group_colors(c("Asia", "Europe", "Latin America"))


## ----color-assignment---------------------------------------------------------
grp     <- c("Asia", "Asia", "Europe", "Europe", "Latin America")
col_map <- forrest:::group_colors(grp)
col_vec <- unname(col_map[grp])
data.frame(grp, colour = col_vec)


## ----section-cols-data--------------------------------------------------------
meta$k_text <- c("k = 2", "k = 2",
                 "k = 4", "k = 4", "k = 4", "k = 4",
                 "k = 1")

exp_sc <- forrest:::build_sections(
  df           = meta,
  estimate     = "or",
  lower        = "lower",
  upper        = "upper",
  label        = "study",
  is_summary   = "is_sum",
  weight       = "weight",
  section      = "region",
  section_cols = c(k_text = "k_text"),
  cols         = c("or_text", "k_text"),
  section_spacer = FALSE,
  section_indent = FALSE
)

exp_sc$df[, c("study", "or_text", "k_text")]


## ----section-cols-plot--------------------------------------------------------
#| fig-height: 7
#| fig-width: 10
forrest(
  meta,
  estimate     = "or",
  lower        = "lower",
  upper        = "upper",
  label        = "study",
  section      = "region",
  section_cols = c("k" = "k_text"),
  weight       = "weight",
  log_scale    = TRUE,
  ref_line     = 1,
  header       = "Study",
  cols         = c("OR (95% CI)" = "or_text", "k" = "k_text"),
  widths       = c(3.5, 3.5, 2.2, 1.0),
  xlab         = "OR (95% CI)"
)


## ----ref-category-data--------------------------------------------------------
dose <- data.frame(
  quartile = c("Q1", "Q2", "Q3", "Q4"),
  or       = c(NA,   1.21, 1.45, 1.82),
  lower    = c(NA,   1.08, 1.28, 1.60),
  upper    = c(NA,   1.36, 1.65, 2.07)
)
dose


## ----ref-category-plot--------------------------------------------------------
forrest(
  dose,
  estimate  = "or",
  lower     = "lower",
  upper     = "upper",
  label     = "quartile",
  ref_label = TRUE,
  log_scale = TRUE,
  ref_line  = 1,
  xlab      = "OR (95% CI)"
)


## ----diamond-data-------------------------------------------------------------
with_pool <- rbind(
  meta[, c("study", "region", "or", "lower", "upper", "is_sum")],
  data.frame(
    study  = "Pooled", region = "Overall",
    or     = 1.082, lower = 1.058, upper = 1.107,
    is_sum = TRUE
  )
)


## ----diamond-plot-------------------------------------------------------------
#| fig-height: 8
forrest(
  with_pool,
  estimate   = "or",
  lower      = "lower",
  upper      = "upper",
  label      = "study",
  section    = "region",
  is_summary = "is_sum",
  log_scale  = TRUE,
  ref_line   = 1,
  xlab       = "OR (95% CI)"
)


## ----theme-defaults-----------------------------------------------------------
forrest:::.theme_defaults


## ----theme-list---------------------------------------------------------------
forrest:::.themes


## ----custom-theme-------------------------------------------------------------
#| fig-height: 3.5
dat <- data.frame(
  label    = c("A", "B", "C"),
  estimate = c(0.2, -0.1, 0.4),
  lower    = c(0.0, -0.3, 0.2),
  upper    = c(0.4,  0.1, 0.6)
)

forrest(
  dat,
  estimate = "estimate",
  lower    = "lower",
  upper    = "upper",
  label    = "label",
  theme    = list(ref_col = "#e63946", ref_lty = 1L,
                  grid_col = "#eeeeee", stripe_col = "#fafafa"),
  stripe   = TRUE,
  xlab     = "Coefficient (95% CI)"
)

