Summarize N-1 survival curves for an N-state partitioned survival model.

Format

An R6::R6Class object.

See also

PsmCurves are conveniently created from either fitted models or parameter objects with create_PsmCurves(). A complete economic model can be implemented with the Psm class. A longer example is provided in vignette("psm").

Public fields

params

An object of class params_surv_list.

input_data

An object of class input_mats. Each row in X must be a unique treatment strategy and patient.

Methods


Method new()

Create a new PsmCurves object.

Usage

PsmCurves$new(params, input_data)

Arguments

params

The params field.

input_data

The input_data field.

Returns

A new PsmCurves object.


Method hazard()

Predict the hazard function for each survival curve as a function of time.

Usage

PsmCurves$hazard(t)

Arguments

t

A numeric vector of times.

Returns

A data.table with columns sample, strategy_id, patient_id, grp_id, curve (the curve number), t, and hazard.


Method cumhazard()

Predict the cumulative hazard function for each survival curve as a function of time.

Usage

PsmCurves$cumhazard(t)

Arguments

t

A numeric vector of times.

Returns

A data.table with columns sample, strategy_id, patient_id, grp_id, curve, t, and cumhazard.


Method survival()

Predict survival probabilities for each survival curve as a function of time.

Usage

PsmCurves$survival(t)

Arguments

t

A numeric vector of times.

Returns

An object of class survival.


Method rmst()

Predict the restricted mean survival time up until time points t for each survival curve.

Usage

PsmCurves$rmst(t, dr = 0)

Arguments

t

A numeric vector of times.

dr

Discount rate.

Returns

A data.table with columns sample, strategy_id, patient_id, grp_id, curve, t, and rmst.


Method quantile()

Predict quantiles of the survival distribution for each survival curve.

Usage

PsmCurves$quantile(p)

Arguments

p

A numeric vector of probabilities for computing quantiles.

Returns

A data.table with columns sample, strategy_id, patient_id, grp_id, curve, p and quantile.


Method check()

Input validation for class. Checks that fields are the correct type.

Usage

PsmCurves$check()


Method clone()

The objects of this class are cloneable with this method.

Usage

PsmCurves$clone(deep = FALSE)

Arguments

deep

Whether to make a deep clone.

Examples

library("flexsurv")
N_SAMPLES <- 5 # Number of parameter samples for PSA

# Consider a 3-state model where there is a 
# progression-free survival (PFS) and an
# overall survival (OS) endpoint

# (0) Model setup
hesim_dat <- hesim_data(
  strategies = data.frame(
    strategy_id = c(1, 2),
    strategy_name = c("SOC", "New 1")
  ),
  patients = data.frame(
    patient_id = 1
  )
)

# (1) Parameterize survival models
## (1.1) If patient-level data is available, 
## we can fit survival models

### (1.1.1) Data for estimation (for simplicity, only use 2 strategies)
surv_est_data <- as_pfs_os(
  onc3[strategy_name != "New 2"], 
  patient_vars = c("patient_id", "strategy_name")
)
surv_est_data$strategy_name <- droplevels(surv_est_data$strategy_name)

### (1.1.2) Fit models
fit_pfs <- flexsurvreg(Surv(pfs_time, pfs_status) ~ strategy_name,
                       data = surv_est_data, dist = "exp")
fit_os <- flexsurvreg(Surv(os_time, os_status) ~ strategy_name,
                      data = surv_est_data, dist = "exp")
fits <- flexsurvreg_list(pfs = fit_pfs, os = fit_os)

## (1.2) If patient-level data is NOT available, 
## we can construct the parameter objects "manually"

### (1.2.1) Baseline hazard:
### Assume that we know the (log) rate parameters for both PFS and OS 
### for SOC (i.e., the intercept) and their standard error
logint_pfs_est <- -1.7470900
logint_pfs_se <-  0.03866223
logint_os_est <- -2.7487675
logint_os_se <- 0.04845015

### (1.2.2) Relative treatment effect:
### Assume we know the log hazard ratios (and their standard errors) 
### for comparing the new interventions to the SOC
loghr_pfs_est_new1 <- -0.1772028 
loghr_pfs_se_new1 <- 0.05420119
loghr_os_est_new1 <- -0.1603632
loghr_os_se_new1 <- 0.06948962

### (1.2.3) Create "params_surv_list" object by combining the baseline hazard 
### and relative treatment effects
params <- params_surv_list(
  #### Model for PFS
  pfs = params_surv(
    coefs = list( 
      rate = data.frame( # coefficients predict log rate
        intercept = rnorm(N_SAMPLES, logint_pfs_est, logint_pfs_se),
        new1 = rnorm(N_SAMPLES, loghr_pfs_est_new1, loghr_pfs_se_new1)
      )
    ),
    dist = "exp"
  ),
  
  #### Model for OS
  os = params_surv(
    coefs = list(
      rate = data.frame(
        intercept = rnorm(N_SAMPLES, logint_os_est, logint_os_se),
        new1 = rnorm(N_SAMPLES, loghr_os_est_new1, loghr_os_se_new1)
      )
    ),
    dist = "exp"
  )
)

#### The print (and summary) methods for the "params_surv_list" object will 
#### summarize each of the model terms, which is a good way to check
#### if it's been setup correctly
params 
#> A "params_surv_list" object 
#> 
#> Summary of coefficients:
#>    model parameter      term       mean         sd       2.5%       97.5%
#> 1:   pfs      rate intercept -1.7485021 0.03947666 -1.7864545 -1.69543149
#> 2:   pfs      rate      new1 -0.1283063 0.05808532 -0.2164273 -0.08005826
#> 3:    os      rate intercept -2.7452407 0.03625975 -2.7783701 -2.69718181
#> 4:    os      rate      new1 -0.1333935 0.04073142 -0.1598637 -0.06980461
#> 
#> Number of parameter samples: 5
#> Distributions: 
#>   pfs    os 
#> "exp" "exp" 

# (2) Simulation
## (2.1) Construct the model
### (2.1.1) Case where patient-level data was available
### Use create_PsmCurves.params_flexsurvreg_list() method
surv_input_data <- expand(hesim_dat, by = c("strategies", "patients"))
psm_curves1 <- create_PsmCurves(fits, input_data = surv_input_data, 
                                n = N_SAMPLES,
                                uncertainty = "normal",
                                est_data = surv_est_data)

### (2.1.2) Case where patient-level data was NOT available
### Use create_PsmCurves.params_surv_list() method
surv_input_data$intercept <- 1
surv_input_data$new1 <- ifelse(surv_input_data$strategy_name == "New 1", 
                               1, 0)
psm_curves2 <- create_PsmCurves(params, input_data = surv_input_data)

## (2.2) Summarize survival models
## There are minor discrepancies between the case where models were fit
## with flexsurvreg() and the case where the "params_surv_list" object
## was constructed manually due to differences in the random draws
## of the parameter samples. These differences are decreasing in the size 
## of N_SAMPLES
times <- seq(0, 10, 1/12) # Monthly times

### Quantiles
head(psm_curves1$quantile(p = c(.25, .5, .75)))
#>    sample strategy_id patient_id grp_id curve    p  quantile
#> 1:      1           1          1      1     1 0.25  1.576211
#> 2:      1           1          1      1     1 0.50  3.797756
#> 3:      1           1          1      1     1 0.75  7.595513
#> 4:      1           1          1      1     2 0.25  4.644797
#> 5:      1           1          1      1     2 0.50 11.191271
#> 6:      1           1          1      1     2 0.75 22.382543
head(psm_curves2$quantile(p = c(.25, .5, .75)))
#>    sample strategy_id patient_id grp_id curve    p  quantile
#> 1:      1           1          1      1     1 0.25  1.701678
#> 2:      1           1          1      1     1 0.50  4.100060
#> 3:      1           1          1      1     1 0.75  8.200119
#> 4:      1           1          1      1     2 0.25  4.629897
#> 5:      1           1          1      1     2 0.50 11.155370
#> 6:      1           1          1      1     2 0.75 22.310739

### Survival curves
head(psm_curves1$survival(t = times))
#>    sample strategy_id patient_id grp_id curve          t  survival
#> 1:      1           1          1      1     1 0.00000000 1.0000000
#> 2:      1           1          1      1     1 0.08333333 0.9849055
#> 3:      1           1          1      1     1 0.16666667 0.9700389
#> 4:      1           1          1      1     1 0.25000000 0.9553966
#> 5:      1           1          1      1     1 0.33333333 0.9409754
#> 6:      1           1          1      1     1 0.41666667 0.9267718
head(psm_curves2$survival(t = times))
#>    sample strategy_id patient_id grp_id curve          t  survival
#> 1:      1           1          1      1     1 0.00000000 1.0000000
#> 2:      1           1          1      1     1 0.08333333 0.9860106
#> 3:      1           1          1      1     1 0.16666667 0.9722169
#> 4:      1           1          1      1     1 0.25000000 0.9586162
#> 5:      1           1          1      1     1 0.33333333 0.9452058
#> 6:      1           1          1      1     1 0.41666667 0.9319829

### Restricted mean survival
head(psm_curves1$rmst(t = c(2, 5)))
#>    sample strategy_id patient_id grp_id curve t     rmst
#> 1:      1           1          1      1     1 2 1.675611
#> 2:      1           1          1      1     1 5 3.279243
#> 3:      1           1          1      1     2 2 1.881087
#> 4:      1           1          1      1     2 5 4.299891
#> 5:      1           2          1      1     1 2 1.731940
#> 6:      1           2          1      1     1 5 3.536659
head(psm_curves2$rmst(t = c(2, 5)))
#>    sample strategy_id patient_id grp_id curve t     rmst
#> 1:      1           1          1      1     1 2 1.696977
#> 2:      1           1          1      1     1 5 3.374980
#> 3:      1           1          1      1     2 2 1.880720
#> 4:      1           1          1      1     2 5 4.297859
#> 5:      1           2          1      1     1 2 1.752854
#> 6:      1           2          1      1     1 5 3.636406