% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/assoc.R
\name{assoc_logistic}
\alias{assoc_logistic}
\alias{assoc_logit}
\title{Logistic regression association analysis}
\usage{
assoc_logistic(
  data,
  outcome_col,
  exposure_col,
  covariates = NULL,
  base = TRUE,
  ci_method = c("wald", "profile"),
  conf_level = 0.95
)

assoc_logit(
  data,
  outcome_col,
  exposure_col,
  covariates = NULL,
  base = TRUE,
  ci_method = c("wald", "profile"),
  conf_level = 0.95
)
}
\arguments{
\item{data}{(data.frame or data.table) Analysis dataset.}

\item{outcome_col}{(character) Binary outcome column (\code{0}/\code{1} or
\code{TRUE}/\code{FALSE}).}

\item{exposure_col}{(character) One or more exposure variable names.}

\item{covariates}{(character or NULL) Covariate column names for the
\strong{Fully adjusted} model. Default: \code{NULL}.}

\item{base}{(logical) Include \strong{Unadjusted} and \strong{Age and sex
adjusted} models. Default: \code{TRUE}.}

\item{ci_method}{(character) CI calculation method: \code{"wald"} (default)
or \code{"profile"}.}

\item{conf_level}{(numeric) Confidence level. Default: \code{0.95}.}
}
\value{
A \code{data.table} with one row per exposure \eqn{\times} term
\eqn{\times} model combination, and columns:
\describe{
\item{\code{exposure}}{Exposure variable name.}
\item{\code{term}}{Coefficient name (e.g. \code{"bmi_categoryObese"}).}
\item{\code{model}}{Ordered factor: \code{Unadjusted} <
\code{Age and sex adjusted} < \code{Fully adjusted}.}
\item{\code{n}}{Participants in model (after NA removal).}
\item{\code{n_cases}}{Number of cases (outcome = 1) in model.}
\item{\code{OR}}{Odds ratio (point estimate).}
\item{\code{CI_lower}}{Lower confidence bound.}
\item{\code{CI_upper}}{Upper confidence bound.}
\item{\code{p_value}}{Wald test p-value.}
\item{\code{OR_label}}{Formatted string, e.g. \code{"1.23 (1.05-1.44)"}.}
}
}
\description{
Fits one or more logistic regression 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:
}
\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{CI methods}:
\itemize{
\item \code{"wald"} (default) - fast, appropriate for large UKB samples.
\item \code{"profile"} - profile likelihood CI via \code{confint.glm()};
slower but more accurate for small or sparse data.
}
}
\examples{
dt <- ops_toy(scenario = "association", n = 500)

res <- assoc_logistic(
  data         = dt,
  outcome_col  = "dm_status",
  exposure_col = "p20116_i0",
  covariates   = c("bmi_cat", "tdi_cat"),
  base         = FALSE
)
}
