## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment  = "#>",
  eval     = FALSE
)

## ----forest-minimal-----------------------------------------------------------
# library(ukbflow)
# 
# df <- data.frame(
#   item      = c("Exposure vs. control", "Unadjusted", "Fully adjusted"),
#   `Cases/N` = c("", "89 / 4 521", "89 / 4 521"),
#   p_value   = c(NA_real_, 0.001, 0.006),
#   check.names = FALSE
# )
# 
# p <- plot_forest(
#   data      = df,
#   est       = c(NA,   1.52, 1.43),
#   lower     = c(NA,   1.18, 1.11),
#   upper     = c(NA,   1.96, 1.85),
#   ci_column = 3L,
#   indent    = c(0L,   1L,   1L),
#   p_cols    = "p_value",
#   xlim      = c(0.5,  3.0)
# )
# plot(p)

## ----forest-from-assoc--------------------------------------------------------
# dt  <- ops_toy(scenario = "association")
# dt  <- dt[dm_timing != 1L]
# 
# res <- assoc_coxph(
#   data         = dt,
#   outcome_col  = "dm_status",
#   time_col     = "dm_followup_years",
#   exposure_col = "p20116_i0",
#   covariates   = c("bmi_cat", "tdi_cat", "p1558_i0")
# )
# res <- as.data.frame(res)
# 
# # Reshape: one row per model, label column first
# df2 <- data.frame(
#   item    = c("Smoking status", as.character(res$model)),
#   `N`     = c("", paste0(res$n, " / ", res$n_events)),
#   p_value = c(NA_real_, res$p_value),
#   check.names = FALSE
# )
# 
# p <- plot_forest(
#   data      = df2,
#   est       = c(NA,   res$HR),
#   lower     = c(NA,   res$CI_lower),
#   upper     = c(NA,   res$CI_upper),
#   ci_column = 3L,
#   indent    = c(0L,   rep(1L, nrow(res))),
#   p_cols    = "p_value",
#   xlim      = c(0.5,  2.5)
# )
# plot(p)

## ----forest-ci----------------------------------------------------------------
# # uses df, est, lower, upper from the minimal example above
# p <- plot_forest(
#   data      = df,
#   est       = est, lower = lower, upper = upper,
#   ci_column = 3L,
#   ci_col    = c("grey50", "steelblue", "steelblue"),  # per-row colours
#   ci_sizes  = 0.5,       # point size
#   ci_Theight = 0.15,     # cap height
#   ref_line  = 1,         # reference line (use 0 for beta coefficients)
#   xlim      = c(0.2, 5), ticks_at = c(0.5, 1, 2, 3)
# )

## ----forest-indent------------------------------------------------------------
# # indent = 0 → bold parent row; indent >= 1 → indented sub-row (plain)
# p <- plot_forest(
#   data       = df,
#   est        = est, lower = lower, upper = upper,
#   ci_column  = 3L,
#   indent     = c(0L, 1L, 1L),        # parent + 2 sub-rows
#   bold_label = c(TRUE, FALSE, FALSE)  # explicit control (overrides indent default)
# )

## ----forest-pval--------------------------------------------------------------
# # p_cols: column names in data that contain raw numeric p-values.
# # Values < 10^(-p_digits) are displayed as e.g. "<0.001".
# # bold_p = TRUE bolds all p < p_threshold (default 0.05).
# p <- plot_forest(
#   data        = df,
#   est         = est, lower = lower, upper = upper,
#   ci_column   = 3L,
#   p_cols      = "p_value",
#   p_digits    = 3L,
#   bold_p      = TRUE,
#   p_threshold = 0.05
# )

## ----forest-header------------------------------------------------------------
# # data has 3 columns → final table has 5 columns (original 3 + gap_ci + OR label)
# # Layout with ci_column = 3L: item | Cases/N | gap_ci | OR (95% CI) | p_value
# p <- plot_forest(
#   data      = df,
#   est       = est, lower = lower, upper = upper,
#   ci_column = 3L,
#   header    = c("Comparison", "Cases / N", "", "HR (95% CI)", "P-value")
#   #             col 1          col 2        gap  OR label       col 5
# )

## ----forest-align-------------------------------------------------------------
# p <- plot_forest(
#   data      = df,
#   est       = est, lower = lower, upper = upper,
#   ci_column = 3L,
#   align     = c(-1L, 0L, 0L, 0L, 1L)   # label left | Cases/N centre | gap | OR centre | p right
# )

## ----forest-style-------------------------------------------------------------
# p <- plot_forest(
#   data       = df,
#   est        = est, lower = lower, upper = upper,
#   ci_column  = 3L,
#   background = "zebra",       # "zebra" | "bold_label" | "none"
#   bg_col     = "#F0F0F0",     # shading colour
#   border     = "three_line",  # "three_line" | "none"
#   border_width = 3            # scalar or length-3 vector (top / mid / bottom)
# )

## ----forest-save--------------------------------------------------------------
# # uses df, est, lower, upper from the minimal example above
# p <- plot_forest(
#   data        = df,
#   est         = est, lower = lower, upper = upper,
#   ci_column   = 3L,
#   row_height  = NULL,   # auto (8 / 12 / 10 / 15 mm); or scalar/vector
#   col_width   = NULL,   # auto (rounds up to nearest 5 mm)
#   save        = TRUE,
#   dest        = "forest_main",   # extension ignored; all 4 formats saved
#   save_width  = 20,              # cm
#   save_height = NULL             # auto: nrow(data) * 0.9 + 3 cm
# )

## ----tableone-minimal---------------------------------------------------------
# library(gtsummary)
# data(trial)   # built-in gtsummary dataset
# 
# plot_tableone(
#   data   = trial,
#   vars   = c("age", "marker", "grade"),
#   strata = "trt",
#   save   = FALSE
# )

## ----tableone-full------------------------------------------------------------
# plot_tableone(
#   data    = trial,
#   vars    = c("age", "marker", "grade", "stage"),
#   strata  = "trt",
#   label   = list(age ~ "Age (years)", marker ~ "Marker level (ng/mL)"),
#   add_p   = TRUE,    # Wilcoxon / chi-squared p-values; formatted as <0.001
#   add_smd = TRUE,
#   overall = TRUE,
#   dest    = "table1",
#   save    = TRUE
# )

## ----tableone-types-----------------------------------------------------------
# dt <- as.data.frame(ops_toy(scenario = "association"))
# 
# plot_tableone(
#   data      = dt,
#   vars      = c("p21022", "p21001_i0", "p31", "p20116_i0"),
#   strata    = "dm_status",
#   type      = list(p21022 = "continuous2"),   # show median + IQR
#   statistic = list(
#     all_continuous()  ~ "{mean} ({sd})",
#     all_categorical() ~ "{n} ({p}%)"
#   ),
#   digits    = list(p21022 ~ 1, p21001_i0 ~ 1),
#   missing   = "ifany",   # show missing counts when present
#   save      = FALSE
# )

## ----tableone-smd-------------------------------------------------------------
# plot_tableone(
#   data    = dt,
#   vars    = c("p21022", "p21001_i0", "p31"),
#   strata  = "dm_status",
#   add_smd = TRUE,
#   save    = FALSE
# )

## ----tableone-exclude---------------------------------------------------------
# plot_tableone(
#   data           = dt,
#   vars           = c("p31", "p20116_i0"),
#   strata         = "dm_status",
#   exclude_labels = "Never",   # e.g. remove reference category from display
#   save           = FALSE
# )

