% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/assoc.R
\name{assoc_trend}
\alias{assoc_trend}
\alias{assoc_tr}
\title{Dose-response trend analysis}
\usage{
assoc_trend(
  data,
  outcome_col,
  time_col = NULL,
  exposure_col,
  method = c("coxph", "logistic", "linear"),
  covariates = NULL,
  base = TRUE,
  scores = NULL,
  conf_level = 0.95
)

assoc_tr(
  data,
  outcome_col,
  time_col = NULL,
  exposure_col,
  method = c("coxph", "logistic", "linear"),
  covariates = NULL,
  base = TRUE,
  scores = NULL,
  conf_level = 0.95
)
}
\arguments{
\item{data}{(data.frame or data.table) Analysis dataset.}

\item{outcome_col}{(character) Outcome column name.}

\item{time_col}{(character or NULL) Follow-up time column (required when
\code{method = "coxph"}).}

\item{exposure_col}{(character) One or more exposure column names. Each
must be a \code{factor} (ordered or unordered). The first level is used
as the reference group.}

\item{method}{(character) Regression method: \code{"coxph"} (default),
\code{"logistic"}, or \code{"linear"}.}

\item{covariates}{(character or NULL) Covariates for the Fully adjusted
model. Default: \code{NULL}.}

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

\item{scores}{(numeric or NULL) Numeric scores assigned to factor levels in
level order. Length must equal \code{nlevels} of every exposure.
\code{NULL} (default) uses \code{0, 1, 2, \ldots}}

\item{conf_level}{(numeric) Confidence level. Default: \code{0.95}.}
}
\value{
A \code{data.table} with one row per exposure \eqn{\times} level
\eqn{\times} model, containing:
\describe{
\item{\code{exposure}}{Exposure variable name.}
\item{\code{level}}{Factor level (ordered factor preserving original
level order).}
\item{\code{term}}{Coefficient name as returned by the model (reference
row uses \code{paste0(exposure, ref_level)}).}
\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{...}{Effect estimate columns from the categorical model:
\code{HR}/\code{OR}/\code{beta}, \code{CI_lower}, \code{CI_upper},
\code{p_value}, and a formatted label. Reference row has
\code{HR = 1} / \code{beta = 0} and \code{NA} for CI and p.
Cox models additionally include \code{n_events} and
\code{person_years}; logistic includes \code{n_cases}; linear
includes \code{se}.}
\item{\code{HR_per_score} / \code{OR_per_score} /
\code{beta_per_score}}{Per-score-unit effect estimate from the trend
model. Shared across all levels within the same exposure \eqn{\times}
model.}
\item{\code{HR_per_score_label} / \code{OR_per_score_label} /
\code{beta_per_score_label}}{Formatted string for the per-score
estimate.}
\item{\code{p_trend}}{P-value for linear trend from the trend model.
Shared across all levels within the same exposure \eqn{\times}
model.}
}
}
\description{
Fits categorical and trend models simultaneously for each ordered-factor
exposure, returning per-category effect estimates alongside a p-value for
linear trend. Two models are run internally per exposure \eqn{\times}
adjustment combination:
}
\details{
\enumerate{
\item \strong{Categorical model} - exposure treated as a factor; produces
one row per non-reference level (HR / OR / \eqn{\beta} vs reference).
\item \strong{Trend model} - exposure recoded as numeric scores (default:
0, 1, 2, \ldots); produces the per-score-unit effect estimate
(\code{*_per_score}) and \code{p_trend}.
}

Both results are merged: the output contains a reference row (effect = 1 /
0, CI = NA) followed by non-reference rows, with \code{*_per_score} and
\code{p_trend} appended as shared columns (same value within each
exposure \eqn{\times} model combination).

\strong{Scores}: By default levels are scored 0, 1, 2, \ldots so the
reference group = 0 and each step = 1 unit. Supply \code{scores} to use
meaningful units (e.g. median years per category) - only \code{p_trend} and
the per-score estimate change; per-category HRs are unaffected.

\strong{Adjustment models}: follows the same logic as
\code{\link{assoc_coxph}} - Unadjusted and Age-and-sex-adjusted models are
included by default (\code{base = TRUE}); a Fully adjusted model is added
when \code{covariates} is non-NULL.
}
\examples{
dt <- ops_toy(scenario = "association", n = 500)
dt <- dt[dm_timing != 1L]

res <- assoc_trend(
  data         = dt,
  outcome_col  = "dm_status",
  time_col     = "dm_followup_years",
  exposure_col = "bmi_cat",
  method       = "coxph",
  covariates   = c("tdi_cat", "p20116_i0"),
  base         = FALSE
)
}
