---
title: "tidymodels and tidybayes integration"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{tidymodels and tidybayes integration}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 4.5,
  message = FALSE,
  warning = FALSE
)
```

**spsurv** registers [parsnip](https://parsnip.tidymodels.org/) engines for censored
regression when the package is loaded (after **parsnip**). Load **censored** or
**tidymodels** for survival metrics and workflows.

```{r setup}
library(spsurv)
library(survival)
library(parsnip)
library(censored)
library(workflows)
data(veteran)
```

## parsnip engines

| Model | spsurv function | Engines |
|-------|-----------------|---------|
| `proportional_hazards()` | `bpph` | `spsurv` (MLE), `spsurv_bayes` |
| `proportional_odds()` | `bppo` | `spsurv`, `spsurv_bayes` |
| `survival_reg()` | `bpaft` | `spsurv`, `spsurv_bayes` |

Use `scale = FALSE` when covariates are preprocessed with **recipes** (the
package default-scales internally when `scale = TRUE`).

```{r parsnip-fit}
spec <- proportional_hazards() |>
  set_engine("spsurv", degree = 5L, scale = FALSE, init = 0)

fit <- fit(spec, Surv(time, status) ~ karno + celltype, data = veteran)
predict(fit, veteran[1:2, ], type = "survival", eval_time = c(100, 200))
```

## workflows

```{r workflow}
wf <- workflow() |>
  add_formula(Surv(time, status) ~ karno + celltype) |>
  add_model(
    proportional_hazards() |>
      set_engine("spsurv", degree = 5L, scale = FALSE, init = 0)
  )

wf_fit <- fit(wf, data = veteran)
predict(wf_fit, veteran[1:3, ], type = "time")
```

## Convenience constructor

`bp_survival_reg()` maps `family = "ph"`, `"po"`, or `"aft"` to the appropriate
parsnip specification.

```{r bp-survival-reg}
bp_survival_reg(family = "ph", engine = "spsurv")
```

## Censored predictions from `spbp` fits

Direct fits support censored-style `predict()` types (same structure as
**censored**):

```{r predict-types}
fit <- bpph(Surv(time, status) ~ karno, data = veteran, approach = "mle", init = 0)
predict(fit, veteran[1:2, ], type = "survival", eval_time = c(50, 100))
predict(fit, veteran[1:2, ], type = "linear_pred")
generics::augment(fit, data = veteran[1:5, ])
```

Curve predictions (default) are unchanged: `predict(fit, times = seq(0, 200, 2))`.

## Bayesian: tidybayes

For `approach = "bayes"`, use **posterior** and **tidybayes** after fitting:

```{r bayes-draws, cache = TRUE}
fit_bayes <- bpph(
  Surv(time, status) ~ karno,
  data = veteran,
  approach = "bayes",
  degree = 4L,
  iter = 200,
  warmup = 100,
  chains = 1,
  cores = 1,
  init = 0
)

dr <- as_draws_df.spbp(fit_bayes)
head(dr[, c(".chain", ".iteration", ".draw", "beta[karno]")])
```

With **tidybayes** loaded, `spread_draws()`, `gather_draws()`, and
`tidy_draws()` dispatch on `spbp` objects. Draw-level survival curves:

```{r surv-draws}
long <- spread_surv_draws.spbp(
  fit_bayes,
  times = c(50, 100, 150),
  newdata = veteran[1, , drop = FALSE]
)
head(long)
```

See the *Bayesian analysis with Stan* vignette for priors and convergence.
