% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/calc_sds.R
\name{calc_sds}
\alias{calc_sds}
\title{Calculate Standard Deviation Scores (SDS; z-scores) for health markers}
\usage{
calc_sds(
  data,
  vars,
  ref,
  id_col = NULL,
  sds_cap = 6,
  na_strategy = c("omit", "error", "keep"),
  extreme_strategy = c("cap", "warn", "error", "NA"),
  warn_thresholds = list(na_prop = 0.05, extreme_prop = 0.01),
  return = c("data", "list"),
  verbose = TRUE,
  na_action = NULL,
  check_extreme = TRUE,
  extreme_action = NULL
)
}
\arguments{
\item{data}{A data.frame/tibble containing the variables.}

\item{vars}{Character vector of variable names in \code{data} to compute SDS for.
Must be non-empty and unique.}

\item{ref}{A data.frame with columns: \code{variable}, \code{mean}, \code{sd} supplying reference
statistics for each variable listed in \code{vars}. Must contain exactly one row per
requested variable, with finite \code{mean} and \code{sd > 0}.}

\item{id_col}{Optional character scalar naming an ID column in \code{data} (used only
in messages and duplicate-ID notes).}

\item{sds_cap}{Numeric scalar; absolute cap for SDS when \code{extreme_strategy = "cap"}.
Must be positive. Default 6.}

\item{na_strategy}{One of c("omit","error","keep"):
\itemize{
\item "omit": drop rows with missing values across any of \code{vars} (default)
\item "error": stop if any missing values among \code{vars}
\item "keep": keep rows; SDS for missing inputs will be NA
}}

\item{extreme_strategy}{One of c("cap","warn","error","NA"):
\itemize{
\item "cap": cap |SDS| at \code{sds_cap} and warn (default)
\item "warn": keep extreme SDS, but warn
\item "error": stop if any |SDS| > \code{sds_cap}
\item "NA": set extreme SDS to NA
}}

\item{warn_thresholds}{Named list controlling warnings (proportions in \eqn{[0,1]}):
\itemize{
\item na_prop: warn if proportion of rows with NA among \code{vars} exceeds this (default 0.05)
\item extreme_prop: warn if proportion of extreme SDS (cells) exceeds this (default 0.01)
}}

\item{return}{One of c("data","list"). "data" returns a tibble with added
\verb{[var]_sds} columns (default). "list" returns a list with components
\code{data}, \code{summary}, and \code{warnings} (backward compatible).}

\item{verbose}{Logical; if TRUE, emit progress via hm_inform(). Also controlled by
options(healthmarkers.verbose = "none"|"inform"|"debug").}

\item{na_action}{Optional HM-CS alias for \code{na_strategy}
(accepted values: keep/omit/error; used if provided).}

\item{check_extreme}{Logical; if TRUE, enables SDS extreme handling (alias for
legacy behavior; defaults to TRUE in this implementation).}

\item{extreme_action}{Optional HM-CS alias for \code{extreme_strategy}
(accepted values: cap/NA/error; used if provided).}
}
\value{
\itemize{
\item If \code{return = "data"} (default): a tibble with added \verb{[var]_sds} columns.
\item If \code{return = "list"}: a list with:
\itemize{
\item data: tibble with added SDS columns
\item summary: list with input/output row counts, omitted rows, total extremes, and per-variable summary
\item warnings: character vector of warning messages emitted
}
}
}
\description{
Computes per-variable SDS as (x - mean) / sd using supplied reference statistics.
Includes input validation, NA/error handling, data quality warnings, and
verbose progress via the package logger (hm_inform), aligned with HM-CS v3.
}
\details{
Derivation: for each requested variable, SDS is calculated as
\code{(observed_value - reference_mean) / reference_sd} using user-supplied
reference statistics in \code{ref}.

Usage note: this function does not derive normative reference values internally.
Users should provide \code{ref} from the target population (preferred), or from an
external source matched as closely as possible on age/sex/ethnicity/context.
Interpretability depends on the quality and relevance of those supplied
reference means and SDs.

By default, returns a tibble with added \verb{[var]_sds} columns (tidyverse-friendly).
For backward compatibility, you can request the previous list output.
}
\examples{
ref <- data.frame(
  variable = c("bmi","sbp"),
  mean     = c(25, 120),
  sd       = c(4, 15)
)
df <- data.frame(
  id  = 1:6,
  bmi = c(24, 30, NA, 29, 10, 26),
  sbp = c(118, 200, 119, 121, 500, 120)
)
out_tbl <- calc_sds(
  data = df,
  vars = c("bmi","sbp"),
  ref = ref,
  id_col = "id",
  na_strategy = "omit",
  extreme_strategy = "cap",
  sds_cap = 6,
  verbose = FALSE
)
}
