% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot_forest}
\alias{plot_forest}
\title{Publication-ready forest plot}
\usage{
plot_forest(
  data,
  est,
  lower,
  upper,
  ci_column = 2L,
  ref_line = 1,
  xlim = NULL,
  ticks_at = NULL,
  arrow_lab = c("Lower risk", "Higher risk"),
  header = NULL,
  indent = NULL,
  bold_label = NULL,
  ci_col = "black",
  ci_sizes = 0.6,
  ci_Theight = 0.2,
  ci_digits = 2L,
  ci_sep = ", ",
  p_cols = NULL,
  p_digits = 3L,
  bold_p = TRUE,
  p_threshold = 0.05,
  align = NULL,
  background = "zebra",
  bg_col = "#F0F0F0",
  border = "three_line",
  border_width = 3,
  row_height = NULL,
  col_width = NULL,
  save = FALSE,
  dest = NULL,
  save_width = 20,
  save_height = NULL,
  theme = "default"
)
}
\arguments{
\item{data}{data.frame. First column must be the label column (\code{item}).
Additional columns are displayed as-is (character) or formatted if named
in \code{p_cols} (must be numeric). Column order is preserved.}

\item{est}{Numeric vector. Point estimates (\code{NA} = no CI drawn).}

\item{lower}{Numeric vector. Lower CI bounds (same length as \code{est}).}

\item{upper}{Numeric vector. Upper CI bounds (same length as \code{est}).}

\item{ci_column}{Integer. Column position in the final rendered table where
the gap/CI graphic is placed. Must be between \code{2} and
\code{ncol(data) + 1} (inclusive). Default: \code{2L}.}

\item{ref_line}{Numeric. Reference line. Default: \code{1} (HR/OR).
Use \code{0} for beta coefficients.}

\item{xlim}{Numeric vector of length 2. X-axis limits. \code{NULL} (default)
uses \code{c(0, 2)}.}

\item{ticks_at}{Numeric vector. Tick positions. \code{NULL} (default) = 5
evenly spaced ticks across \code{xlim}.}

\item{arrow_lab}{Character vector of length 2. Directional labels.
Default: \code{c("Lower risk", "Higher risk")}. \code{NULL} = none.}

\item{header}{Character vector of length \code{ncol(data) + 2}. Column
header labels for the final rendered table (original columns + gap_ci +
OR label). \code{NULL} (default) = use column names from \code{data} plus
\code{"gap_ci"} and \code{"OR (95\% CI)"}. Pass \code{""} for the gap
column position.}

\item{indent}{Integer vector (length = \code{nrow(data)}). Indentation
level of the label column: each unit adds two leading spaces.
Default: all zeros.}

\item{bold_label}{Logical vector (length = \code{nrow(data)}). Which rows
to bold in the label column. \code{NULL} (default) = auto-derive from
\code{indent}: rows where \code{indent == 0} are bolded (parent rows),
indented sub-rows are plain.}

\item{ci_col}{Character scalar or vector (length = \code{nrow(data)}).
CI colour(s). \code{NA} rows are skipped automatically.
Default: \code{"black"}.}

\item{ci_sizes}{Numeric. Point size. Default: \code{0.6}.}

\item{ci_Theight}{Numeric. CI cap height. Default: \code{0.2}.}

\item{ci_digits}{Integer. Decimal places for the auto-generated
\code{OR (95\% CI)} column. Default: \code{2L}.}

\item{ci_sep}{Character. Separator between lower and upper CI in the label,
e.g. \code{", "} or \code{" - "}. Default: \code{", "}.}

\item{p_cols}{Character vector. Names of numeric p-value columns in
\code{data}. These are formatted to \code{p_digits} decimal places with
\code{"<0.001"}-style clipping. \code{NULL} = none.}

\item{p_digits}{Integer. Decimal places for p-value formatting.
Default: \code{3L}.}

\item{bold_p}{\code{TRUE} (bold all non-NA p below \code{p_threshold}),
\code{FALSE} (no bolding), or a logical vector (per-row control).
Default: \code{TRUE}.}

\item{p_threshold}{Numeric. P-value threshold for bolding when
\code{bold_p = TRUE}. Default: \code{0.05}.}

\item{align}{Integer vector of length \code{ncol(data) + 2}. Alignment per
column: \code{-1} left, \code{0} centre, \code{1} right. Must cover all
final columns (original + gap_ci + OR label).
\code{NULL} = auto (column 1 left, all others centre).}

\item{background}{Character. Row background style: \code{"zebra"},
\code{"bold_label"} (shade rows where \code{bold_label = TRUE}),
or \code{"none"}. Default: \code{"zebra"}.}

\item{bg_col}{Character. Shading colour for backgrounds (scalar), or a
per-row vector of length \code{nrow(data)} (overrides style).
Default: \code{"#F0F0F0"}.}

\item{border}{Character. Border style: \code{"three_line"} or \code{"none"}.
Default: \code{"three_line"}.}

\item{border_width}{Numeric. Border line width(s). Scalar = all three lines
same width; length-3 vector = top-of-header, bottom-of-header,
bottom-of-body. Default: \code{3}.}

\item{row_height}{\code{NULL} (auto), numeric scalar, or numeric vector
(length = total gtable rows including margins). Auto sets 8 / 12 / 10 / 15
mm for top / header / data / bottom respectively.}

\item{col_width}{\code{NULL} (auto), numeric scalar, or numeric vector
(length = total gtable columns). Auto rounds each default width up so the
adjustment is in \eqn{[5, 10)} mm.}

\item{save}{Logical. Save output to files? Default: \code{FALSE}.}

\item{dest}{Character. Destination file path (extension ignored; all four
formats are saved). Required when \code{save = TRUE}.}

\item{save_width}{Numeric. Output width in cm. Default: \code{20}.}

\item{save_height}{Numeric or \code{NULL}. Output height in cm.
\code{NULL} = \code{nrow(data) * 0.9 + 3}.}

\item{theme}{Character preset (\code{"default"}) or a
\code{forestploter::forest_theme} object. Default: \code{"default"}.}
}
\value{
A \pkg{forestploter} plot object (gtable), returned invisibly.
Display with \code{plot()} or \code{grid::grid.draw()}.
}
\description{
Produces a publication-ready forest plot with UKB-standard styling.
The user supplies a data frame whose first column is the row label
(\code{item}), plus any additional display columns (e.g. \code{Cases/N}).
The gap column and the auto-formatted \code{OR (95\% CI)} text column are
inserted automatically at \code{ci_column}. Numeric p-value columns
declared via \code{p_cols} are formatted in-place.
}
\examples{
df <- data.frame(
  item      = c("Exposure vs. control", "Unadjusted", "Fully adjusted"),
  `Cases/N` = c("", "89/4521", "89/4521"),
  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  = 2L,
  indent     = c(0L, 1L, 1L),
  bold_label = c(TRUE, FALSE, FALSE),
  p_cols     = "p_value",
  xlim       = c(0.5, 3.0)
)
plot(p)
}
