---
title: "Survival Analysis"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Survival Analysis}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

`gtregression` supports a complete survival workflow: describe
the cohort, draw Kaplan-Meier curves, summarise observed survival, compare
groups, fit Cox or parametric survival models, check assumptions, predict
survival probabilities, visualise estimates, and export publication-ready
tables.

```{r surv-setup, message=FALSE, warning=FALSE}
library(gtregression)
library(dplyr)

data("data_lungcancer", package = "gtregression")

lung_data <- data_lungcancer |>
  mutate(
    trt = factor(trt, levels = c(1, 2),
                 labels = c("Standard treatment", "Test treatment")),
    prior = factor(prior, levels = c(0, 10), labels = c("No", "Yes")),
    celltype = factor(
      celltype,
      levels = c("squamous", "smallcell", "adeno", "large"),
      labels = c("Squamous", "Small cell", "Adenocarcinoma", "Large cell")
    )
  )

attr(lung_data$time, "label") <- "Survival time"
attr(lung_data$status, "label") <- "Death status"
attr(lung_data$trt, "label") <- "Treatment group"
attr(lung_data$celltype, "label") <- "Cancer cell type"
attr(lung_data$karno, "label") <- "Karnofsky performance score"
attr(lung_data$age, "label") <- "Age"
attr(lung_data$prior, "label") <- "Prior therapy"

surv_exposures <- c("trt", "celltype", "karno", "age", "prior")
```

## 1. Describe The Cohort

Start with a baseline table. This helps readers understand the treatment groups
before looking at survival curves or models.

```{r surv-describe, message=FALSE, warning=FALSE}
lung_summary <- descriptive_table(
  data = lung_data,
  exposures = c("time", "status", "celltype", "karno", "age", "prior"),
  by = trt,
  statistic = c(time = "median", karno = "mean", age = "mean"),
  percent = column,
  show_overall = last
)

lung_summary$table
```

## 2. Show Observed Survival

Use `km_plot()` for the Kaplan-Meier curve. Add `risk_table = TRUE` when the
number at risk should appear under the curve. When survival remains high, use
`ylim` to focus the y-axis, for example `ylim = c(50, 100)` with the default
percentage scale. Confidence intervals are shown as shaded bands when
`conf.int = TRUE`.

```{r surv-km-plot, message=FALSE, warning=FALSE}
km_curve <- km_plot(
  data = lung_data,
  time = time,
  event = status,
  by = trt,
  break_time_by = 200,
  ylim = c(50, 100),
  title = "Kaplan-Meier Survival by Treatment"
)

km_curve
```

For multi-panel publication figures, make each Kaplan-Meier plot lighter and
let `patchwork` arrange the panels. A common pattern is to remove the risk table,
use short panel titles, reduce `title_size`, and collect legends across panels.

```{r surv-km-panel, fig.width=7, fig.height=5, message=FALSE, warning=FALSE}
km_trt_panel <- km_plot(
  data = lung_data,
  time = time,
  event = status,
  by = trt,
  risk_table = FALSE,
  break_time_by = 200,
  ylim = c(50, 100),
  title = "A. Treatment group",
  title_size = 10,
  title_face = plain,
  legend_position = bottom,
  base_size = 10
)

km_prior_panel <- km_plot(
  data = lung_data,
  time = time,
  event = status,
  by = prior,
  risk_table = FALSE,
  break_time_by = 200,
  ylim = c(50, 100),
  title = "B. Prior therapy",
  title_size = 10,
  title_face = plain,
  legend_position = bottom,
  base_size = 10
)

patchwork::wrap_plots(km_trt_panel, km_prior_panel, ncol = 2) +
  patchwork::plot_layout(guides = "collect") &
  ggplot2::theme(legend.position = "bottom")
```

Use table summaries when readers need exact survival values.

```{r surv-observed-tables, message=FALSE, warning=FALSE}
survival_summary(
  data = lung_data,
  time = time,
  event = status,
  by = trt
)$table

survival_prob(
  data = lung_data,
  time = time,
  event = status,
  by = trt,
  times = c(90, 180, 365)
)$table
```

`rmst_table()` reports restricted mean survival time up to a chosen follow-up
time. This is useful when an absolute survival-time summary is easier to explain
than a ratio measure.

```{r surv-rmst, message=FALSE, warning=FALSE}
rmst_table(
  data = lung_data,
  time = time,
  event = status,
  by = trt,
  tau = 365
)$table
```

## 3. Compare Survival Curves

`logrank_test()` compares Kaplan-Meier curves. It is a group comparison test,
not an effect-size model.

```{r surv-logrank, message=FALSE, warning=FALSE}
logrank_test(
  data = lung_data,
  time = time,
  event = status,
  by = trt
)$table
```

## 4. Fit Cox Regression

`cox_reg()` reports hazard ratios. Use `adjust_for` to produce adjusted hazard
ratios while keeping the syntax aligned with `multi_reg()`.

```{r surv-cox, message=FALSE, warning=FALSE}
cox_crude <- cox_reg(
  data = lung_data,
  time = time,
  event = status,
  exposures = surv_exposures
)

cox_adjusted <- cox_reg(
  data = lung_data,
  time = time,
  event = status,
  exposures = c(trt, celltype, prior),
  adjust_for = c(age, karno)
)

cox_adjusted$table
```

Planned interactions use the same `interaction = exposure*modifier` grammar as
`multi_reg()`. In the default exposure-by-exposure workflow, supply the single
exposure you want to interpret.

```{r surv-cox-interaction, message=FALSE, warning=FALSE}
cox_interaction <- cox_reg(
  data = lung_data,
  time = time,
  event = status,
  exposures = trt,
  adjust_for = c(age, karno),
  interaction = trt*prior
)

cox_interaction$table
```

Check the proportional hazards assumption before treating Cox hazard ratios as
final.

```{r surv-check-ph, message=FALSE, warning=FALSE}
check_ph(cox_adjusted)$table
```

## 5. Fit Parametric Survival Regression

`surv_reg()` fits accelerated failure time style parametric survival models and
reports time ratios. A time ratio above 1 suggests longer survival time; below 1
suggests shorter survival time, conditional on the selected distribution.

Before choosing the final distribution, compare candidate parametric models
numerically and visually. Lower AIC/BIC is useful for screening; the fitted
curve should also look reasonable against the Kaplan-Meier curve.

```{r surv-parametric-checks, message=FALSE, warning=FALSE}
surv_model_compare(
  data = lung_data,
  time = time,
  event = status,
  exposures = c(trt, celltype, prior),
  adjust_for = c(age, karno),
  distributions = c(weibull, exponential, "log-normal", "log-logistic")
)$table

plot_surv_fit(
  data = lung_data,
  time = time,
  event = status,
  by = trt,
  adjust_for = c(age, karno),
  distributions = c(weibull, "log-logistic"),
  break_time_by = 200
)
```

After selecting a distribution, fit crude and adjusted publication-ready tables.

```{r surv-parametric, message=FALSE, warning=FALSE}
surv_crude <- surv_reg(
  data = lung_data,
  time = time,
  event = status,
  exposures = surv_exposures,
  distribution = loglogistic
)

surv_adjusted <- surv_reg(
  data = lung_data,
  time = time,
  event = status,
  exposures = c(trt, celltype, prior),
  adjust_for = c(age, karno),
  distribution = loglogistic,
  model_stats = TRUE
)

surv_adjusted$table
surv_adjusted$model_stats
```

Parametric survival models use the same interaction grammar and display
Adjusted Time Ratio (95% CI) when adjustment or multivariable modelling is used.

```{r surv-parametric-interaction, message=FALSE, warning=FALSE}
surv_interaction <- surv_reg(
  data = lung_data,
  time = time,
  event = status,
  exposures = trt,
  adjust_for = c(age, karno),
  interaction = trt*prior,
  distribution = loglogistic
)

surv_interaction$table
```

## 6. Predict Survival Probabilities

`surv_predict()` turns a fitted parametric survival model into predicted
survival probabilities at selected follow-up times for a profile.

```{r surv-predict, message=FALSE, warning=FALSE}
surv_predict(
  model = surv_adjusted$models$trt,
  newdata = data.frame(
    trt = factor("Test treatment", levels = levels(lung_data$trt)),
    age = 60,
    karno = 70
  ),
  times = c(90, 180, 365)
)$table
```

## 7. Visualise And Export Model Results

The survival model outputs work with the same downstream tools used for other
regression tables.

```{r surv-visualise-export, message=FALSE, warning=FALSE}
plot_reg_combine(
  cox_crude,
  cox_adjusted,
  show_ref = FALSE,
  title_uni = "Crude HR",
  title_multi = "Adjusted HR"
)

surv_forest_data <- forest_df(cox_crude, cox_adjusted, desc = lung_summary)

forest_reg(
  surv_forest_data,
  xlim = list(c(0.25, 8), c(0.25, 8)),
  ticks_at = list(c(0.5, 1, 2, 4, 8), c(0.5, 1, 2, 4, 8)),
  quiet = TRUE
)
```

If forest plot x-axis labels overlap, set `xlim` and `ticks_at`. If the
confidence-interval plot panel is too narrow or too wide, tune `ci_col_width`.
For very wide descriptive-plus-crude-plus-adjusted tables, export using a wider
graphics device or Word canvas.

## Survival Workflow Map

| Task | Function |
|---|---|
| Kaplan-Meier curve | `km_plot()` |
| Number at risk | `km_risk_table()` |
| Median survival | `survival_summary()` |
| Survival quantiles | `survival_quantiles()` |
| Fixed-time survival probability | `survival_prob()` |
| Restricted mean survival time | `rmst_table()` |
| Compare KM curves | `logrank_test()` |
| Cox hazard ratios | `cox_reg()` |
| Cox PH check | `check_ph()` |
| Parametric time ratios | `surv_reg()` |
| Compare parametric distributions | `surv_model_compare()` |
| Plot fitted parametric curves | `plot_surv_fit()` |
| Predict survival probabilities | `surv_predict()` |
| Model plots and forest tables | `plot_reg()`, `plot_reg_combine()`, `forest_df()`, `forest_reg()` |
