% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/assoc.R
\name{assoc_coxph}
\alias{assoc_coxph}
\alias{assoc_cox}
\title{Cox proportional hazards association analysis}
\usage{
assoc_coxph(
  data,
  outcome_col,
  time_col,
  exposure_col,
  covariates = NULL,
  base = TRUE,
  strata = NULL,
  conf_level = 0.95
)

assoc_cox(
  data,
  outcome_col,
  time_col,
  exposure_col,
  covariates = NULL,
  base = TRUE,
  strata = NULL,
  conf_level = 0.95
)
}
\arguments{
\item{data}{(data.frame or data.table) Analysis dataset. Must contain all
columns referenced by \code{outcome_col}, \code{time_col}, and
\code{exposure_col}.}

\item{outcome_col}{(character) Name of the event indicator column.
Accepts \code{logical} (\code{TRUE}/\code{FALSE}) or numeric/integer
(\code{0}/\code{1}).}

\item{time_col}{(character) Name of the follow-up time column (numeric,
in consistent units, e.g. years).}

\item{exposure_col}{(character) One or more exposure variable names.
Each variable is analysed separately; results are stacked row-wise.}

\item{covariates}{(character or NULL) Additional covariate column names for
the \strong{Fully adjusted} model (e.g.
\code{c("tdi", "smoking", paste0("pc", 1:10))}). When \code{NULL}
(default), the Fully adjusted model is not run.}

\item{base}{(logical) If \code{TRUE} (default), always include the
\strong{Unadjusted} and \strong{Age and sex adjusted} models in addition
to any user-specified \code{covariates} model. Set to \code{FALSE} to run
only the Fully adjusted model (requires \code{covariates} to be non-NULL).}

\item{strata}{(character or NULL) Optional stratification variable.
Passed to \code{survival::strata()} in the Cox formula.}

\item{conf_level}{(numeric) Confidence level for hazard ratio intervals.
Default: \code{0.95}.}
}
\value{
A \code{data.table} with one row per exposure \eqn{\times} term
\eqn{\times} model combination, and the following columns:
\describe{
\item{\code{exposure}}{Exposure variable name.}
\item{\code{term}}{Coefficient name as returned by \code{coxph} (e.g.
\code{"bmi_categoryObese"} for a factor, or the variable name itself
for numeric/binary exposures).}
\item{\code{model}}{Ordered factor: \code{Unadjusted} <
\code{Age and sex adjusted} < \code{Fully adjusted}.}
\item{\code{n}}{Number of participants included in the model (after
\code{NA} removal).}
\item{\code{n_events}}{Number of events in the model's analysis set
(after \code{NA} removal).}
\item{\code{person_years}}{Total person-years of follow-up in the
model's analysis set (rounded, after \code{NA} removal).}
\item{\code{HR}}{Hazard ratio (point estimate).}
\item{\code{CI_lower}}{Lower bound of the confidence interval.}
\item{\code{CI_upper}}{Upper bound of the confidence interval.}
\item{\code{p_value}}{Wald test p-value.}
\item{\code{HR_label}}{Formatted string, e.g.
\code{"1.23 (1.05-1.44)"}.}
}
}
\description{
Fits one or more Cox models for each exposure variable and returns a tidy
result table suitable for downstream forest plots. By default, two standard
adjustment models are always included alongside any user-specified model:
}
\details{
\itemize{
\item \strong{Unadjusted} - no covariates (crude).
\item \strong{Age and sex adjusted} - age + sex auto-detected from the
data via UKB field IDs (21022 and 31). Skipped with a warning if either
column cannot be found.
\item \strong{Fully adjusted} - the covariates supplied via the
\code{covariates} argument. Only run when \code{covariates} is non-NULL.
}

\strong{Outcome coding}: \code{outcome_col} may be \code{logical}
(\code{TRUE}/\code{FALSE}) or integer/numeric (\code{0}/\code{1}).
Logical values are converted to integer internally.

\strong{Exposure types supported}:
\itemize{
\item \emph{Binary} - \code{0}/\code{1} or \code{TRUE}/\code{FALSE};
produces one \code{term} row per model.
\item \emph{Factor} - produces one \code{term} row per non-reference level.
\item \emph{Numeric} (continuous) - produces one \code{term} row per model.
}
}
\examples{
dt <- ops_toy(scenario = "association", n = 500)
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"),
  base         = FALSE
)

# Fully adjusted only (skip Unadjusted + Age-sex)
res <- assoc_coxph(
  data         = dt,
  outcome_col  = "dm_status",
  time_col     = "dm_followup_years",
  exposure_col = "p20116_i0",
  covariates   = c("p21022", "p31", "bmi_cat", "tdi_cat"),
  base         = FALSE
)
}
