---
title: "regtab() & survtab(): Multivariable Modeling and Longitudinal Outcomes"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{regtab() & survtab(): Multivariable Modeling and Longitudinal Outcomes}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 4.5
)
library(SimtablR)
data(epitabl)
has_survival <- requireNamespace("survival", quietly = TRUE)
has_logistf <- requireNamespace("logistf", quietly = TRUE)
has_ggplot2 <- requireNamespace("ggplot2", quietly = TRUE)
```

Epidemiological modeling requires aligning statistical models with study design, estimands, confounding adjustment, and potential data sparsity.

In this guide, we follow the hospital course and 1-year longitudinal follow-up of the **ESTROBE-ACS study**. We demonstrate how `regtab()` and `survtab()` allow epidemiologists to estimate adjusted odds ratios, robust sandwich standard errors, Firth penalized likelihood for rare clinical conditions, and Cox proportional hazards for time-to-MACE survival.

---

## 1. Study Design & Effect Measure Alignment

> **Clinical Context & Research Question:** In observational cardiovascular research, how does the underlying study design dictate whether the target estimand is a Risk Ratio, Odds Ratio, or Hazard Ratio?

In SimtablR, the study design can be explicitly declared via `design = "cohort"`, `"case_control"`, or `"cross_sectional"`. SimtablR aligns the estimand and advises when a chosen model or measure might deviate from sound epidemiological practice:

- **Prospective Cohort:** Risk Ratio (RR) in binary tables or Hazard Ratio (HR) in time-to-event analysis.
- **Case-Control:** Odds Ratio (OR).
- **Cross-Sectional:** Prevalence Ratio (PR).

```{r design-resolution}
# Declaring cohort design in bivariate analysis resolves to Risk Ratio (RR)
tb_cohort <- tb(
  epitabl,
  renal_impairment,
  adjudicated_acs,
  flags = "row",
  design = "cohort",
  ref = "No"
)
tb_cohort
```

---

## 2. Multivariable GLMs with `regtab()`

> After adjusting for age, sex, smoking, hypertension, and diabetes, does renal impairment remain independently associated with confirmed acute coronary syndrome?

`regtab()` fits generalized linear models for binary, continuous, or count outcomes over a shared predictor formula.

### 2.1 Logistic Regression & Robust Sandwich Covariance

For binary endpoints, logistic regression yields adjusted Odds Ratios (ORs):

```{r logistic-regtab}
fit_logistic <- regtab(
  epitabl,
  outcomes = "adjudicated_acs",
  predictors = ~ age + sex + smoking + hypertension + diabetes + renal_impairment,
  family = stats::binomial("logit"),
  robust = TRUE,
  predictor_labels = c(
    smokingCurrent = "Current Smoker",
    hypertensionYes = "Hypertension",
    diabetesYes = "Diabetes Mellitus",
    renal_impairmentYes = "Renal Impairment"
  )
)
fit_logistic
```

#### Robust Standard Errors:
By default, `regtab()` applies HC0 heteroscedasticity-consistent standard errors (`robust = TRUE`). You can request small-sample corrected estimators such as `robust = "HC3"` or classical model-based variance with `robust = FALSE`.

---

### 2.2 Multi-Outcome Regression

> **Clinical Context & Research Question:** Does baseline renal impairment confer similar adjusted risks for acute ACS presentation as it does for 1-year hospital readmission?

In multi-morbidity studies, the same predictor set is frequently evaluated against multiple clinical outcomes. `regtab()` fits all models concurrently and presents a consolidated table:

```{r multi-outcome-regtab}
fit_multi <- regtab(
  epitabl,
  outcomes = c("adjudicated_acs", "rehospitalized"),
  predictors = ~ age + sex + renal_impairment,
  family = stats::binomial("logit"),
  robust = TRUE,
  labels = c(
    adjudicated_acs = "Acute Coronary Syndrome",
    rehospitalized = "1-Year Readmission"
  )
)
fit_multi
```

---

### 2.3 Model Extraction & Multicollinearity Diagnostics

`regtab()` objects implement standard broom generics for downstream inspection:

```{r model-extract}
# Broom-style tidy coefficients
head(generics::tidy(fit_logistic), 5)

# Model-level statistics including Generalized Variance Inflation Factors (GVIF)
generics::glance(fit_logistic, vif = TRUE)
```

---

## 3. Sparse Data & Firth Penalized Likelihood Regression

>In patients presenting with acute symptoms who are on maintenance dialysis (a rare clinical condition with small event counts), how do we avoid infinite odds ratios caused by sparse-data separation?

When outcomes or exposures are rare, classical maximum likelihood estimation can suffer from quasi-complete separation or small-sample bias, producing unstable Wald confidence intervals or infinite point estimates.

`regtab()` supports Firth's penalized likelihood method via `method = "firth"` (powered by `logistf`):

```{r firth-regtab, eval=has_logistf}
fit_firth <- regtab(
  epitabl,
  outcomes = "adjudicated_acs",
  predictors = ~ age + sex + dialysis,
  family = stats::binomial("logit"),
  method = "firth"
)
fit_firth
```

Firth's penalized likelihood adds a Jeffreys prior penalty to the score equations, constructing reliable profile-penalized likelihood confidence bounds.

---

## 4. Time-to-Event Survival Analysis with `survtab()`

> Over 365 days of follow-up after the index emergency visit, which baseline clinical factors independently predict the hazard of Major Adverse Cardiovascular Events (MACE)?

When follow-up time varies and participants are subject to right-censoring, `survtab()` fits Cox proportional hazards models. In `epitabl`, participants were followed for MACE (`mace_event`) over `mace_time_days`:

```{r survtab-cox, eval=has_survival}
fit_cox <- survtab(
  epitabl,
  time = mace_time_days,
  event = mace_event,
  predictors = ~ age + sex + renal_impairment + hypertension + smoking,
  design = "cohort"
)
fit_cox
```

---

### 4.1 Proportional Hazards Diagnostics & Advisory Audit

`survtab()` integrates with SimtablR's advice engine to audit proportional hazards assumptions:

```{r cox-advise, eval=has_survival}
# Inspect model fit and Schoenfeld residual diagnostics
generics::glance(fit_cox)

# Review methodological audit rules
advise(fit_cox, audit = TRUE)
```

---

### 4.2 Forest Plot Visualization & Methods Generation

`survtab()` results can be visualized directly with `autoplot()`:

```{r cox-plot, eval=has_survival && has_ggplot2, fig.alt="Forest plot displaying adjusted hazard ratios and 95% confidence intervals"}
ggplot2::autoplot(fit_cox) +
  ggplot2::labs(
    title = "Adjusted Hazard Ratios for 365-Day MACE",
    subtitle = "ESTROBE-ACS Prospective Cohort"
  )
```

Finally, `as_methods()` produces publication-ready text describing the Cox modeling strategy:

```{r cox-methods, eval=has_survival}
cat(as_methods(fit_cox))
```
