| Title: | Health Economic Simulation Modeling and Decision Analysis |
|---|---|
| Description: | A modular and computationally efficient R package for parameterizing, simulating, and analyzing health economic simulation models. The package supports cohort discrete time state transition models (Briggs et al. 1998) <doi:10.2165/00019053-199813040-00003>, N-state partitioned survival models (Glasziou et al. 1990) <doi:10.1002/sim.4780091106>, and individual-level continuous time state transition models (Siebert et al. 2012) <doi:10.1016/j.jval.2012.06.014>, encompassing both Markov (time-homogeneous and time-inhomogeneous) and semi-Markov processes. Decision uncertainty from a cost-effectiveness analysis is quantified with standard graphical and tabular summaries of a probabilistic sensitivity analysis (Claxton et al. 2005, Barton et al. 2008) <doi:10.1002/hec.985>, <doi:10.1111/j.1524-4733.2008.00358.x>. Use of C++ and data.table make individual-patient simulation, probabilistic sensitivity analysis, and incorporation of patient heterogeneity fast. |
| Authors: | Devin Incerti [aut, cre], Jeroen P. Jansen [aut], Mark Clements [aut], R Core Team [ctb] (hesim uses some slightly modified C functions from base R) |
| Maintainer: | Devin Incerti <[email protected]> |
| License: | GPL-3 |
| Version: | 0.5.8 |
| Built: | 2026-05-17 05:47:16 UTC |
| Source: | https://github.com/hesim-dev/hesim |
Elements of transition probability matrices are multiplied by relative risks and the transition probability matrices are adjusted so that rows sum to 1. Operations are vectorized and each relative risk is multiplied by every transition matrix (stored in 3-dimensional arrays).
apply_rr(x, rr, index, complement = NULL)apply_rr(x, rr, index, complement = NULL)
x |
A 3-dimensional array where each slice is a square transition probability matrix. |
rr |
A 2-dimensional tabular object such as a matrix or data frame where each
column is a vector of relative risks to apply to each transition matrix in |
index |
The indices of the transition probability matrices that |
complement |
Denotes indices of transition probability matrices that are
"complements" (i.e., computed as |
This function is useful for applying relative treatment effects measured
using relative risks to an existing transition probability matrix. For example,
a transition probability matrix for the reference treatment strategy may exist or
have been estimated from the data. Relative risks estimated from a meta-analysis
or network meta-analysis can then be applied to the reference transition probability
matrix. If the number of rows in rr exceeds x, then the arrays in x are
recycled to the number of rows in rr, which facilitates the application of
relative risks from multiple treatment strategies to a reference treatment.
A 3-dimensional array where each slice contains matrices of the same
dimension as each matrix in x and the number of slices is equal to the number
of rows in rr.
p_12 <- c(.7, .5) p_23 <- c(.1, .2) x <- as_array3(tpmatrix( C, p_12, .1, 0, C, p_23, 0, 0, 1 )) # There are the same number of relative risk rows and transition probability matrices rr_12 <- runif(2, .8, 1) rr_13 <- runif(2, .9, 1) rr <- cbind(rr_12, rr_13) apply_rr(x, rr, index = list(c(1, 2), c(1, 3)), complement = list(c(1, 1), c(2, 2))) # There are more relative risk rows than transition probability matrices rr_12 <- runif(4, .8, 1) rr_13 <- runif(4, .9, 1) rr <- cbind(rr_12, rr_13) apply_rr(x, rr, index = list(c(1, 2), c(1, 3)), complement = list(c(1, 1), c(2, 2)))p_12 <- c(.7, .5) p_23 <- c(.1, .2) x <- as_array3(tpmatrix( C, p_12, .1, 0, C, p_23, 0, 0, 1 )) # There are the same number of relative risk rows and transition probability matrices rr_12 <- runif(2, .8, 1) rr_13 <- runif(2, .9, 1) rr <- cbind(rr_12, rr_13) apply_rr(x, rr, index = list(c(1, 2), c(1, 3)), complement = list(c(1, 1), c(2, 2))) # There are more relative risk rows than transition probability matrices rr_12 <- runif(4, .8, 1) rr_13 <- runif(4, .9, 1) rr <- cbind(rr_12, rr_13) apply_rr(x, rr, index = list(c(1, 2), c(1, 3)), complement = list(c(1, 1), c(2, 2)))
Convert a 2-dimensional tabular object where each row stores a flattened square matrix to a 3-dimensional array of square matrices and vice versa. This allows multiple transition matrices to be stored as either tabular objects (e.g., matrices, data frames, etc) or as arrays.
as_array3(x) as_tbl2( x, output = c("data.table", "data.frame", "matrix", "tpmatrix"), prefix = "", sep = "_" )as_array3(x) as_tbl2( x, output = c("data.table", "data.frame", "matrix", "tpmatrix"), prefix = "", sep = "_" )
x |
For |
output |
The class of the object returned by the function. Either
a |
prefix, sep
|
Arguments passed to |
For as_array3() a 3-dimensional array of square matrices;
for as_tbl2() a 2-dimensional tabular object as specified by output.
p_12 <- c(.7, .6) pmat <- tpmatrix( C, p_12, 0, 1 ) pmat as_array3(pmat) as_array3(as.matrix(pmat)) as_tbl2(as_array3(pmat)) as_tbl2(as_array3(pmat), prefix = "p_", sep = ".")p_12 <- c(.7, .6) pmat <- tpmatrix( C, p_12, 0, 1 ) pmat as_array3(pmat) as_array3(as.matrix(pmat)) as_tbl2(as_array3(pmat)) as_tbl2(as_array3(pmat), prefix = "p_", sep = ".")
Convert a multi-state dataset with irreversible transitions containing 3 health states to a dataset with one row per patient and progression-free survival (PFS) and overall survival (OS) time-to-event outcomes.
as_pfs_os( data, patient_vars, status = "status", time_stop = "time_stop", transition = "transition_id" )as_pfs_os( data, patient_vars, status = "status", time_stop = "time_stop", transition = "transition_id" )
data |
A multi-state dataset. |
patient_vars |
Character vector of the names of patient specific variables. |
status |
Character string with the name of the status variable (1 = event, 0 = censored). |
time_stop |
Character string with the name of the stopping time variable
(i.e., time patient transitions from state |
transition |
Character string with the name of the variable identifying a transition. The transition variable should be integer valued with values 1, 2, and 3 for the Stable -> Progression, Stable -> Death, and Progression -> Death transitions, respectively. |
A data.table with one row per patient containing each variable in
patient_vars as well as a time variable and status indicator for both
PFS (pfs_status, pfs_time) and OS (os_time, os_status).
as_pfs_os(onc3, patient_vars = c("patient_id", "strategy_name", "female", "age"))as_pfs_os(onc3, patient_vars = c("patient_id", "strategy_name", "female", "age"))
data.table
Creates a data.table that combines the transition probability matrices
and ID variables from a tparams_transprobs object. This is often useful for
debugging.
## S3 method for class 'tparams_transprobs' as.data.table(x, ..., prefix = "prob_", sep = "_", long = FALSE)## S3 method for class 'tparams_transprobs' as.data.table(x, ..., prefix = "prob_", sep = "_", long = FALSE)
x |
A |
... |
Currently unused. |
prefix, sep
|
Arguments passed to |
long |
If |
The output always contains columns for the ID variables and the
transition probabilities, but the form depends on on the long argument.
If FALSE, then a data.table with one row for each transition probability
matrix is returned; otherwise, the data.table contains one row for each
transition and columns from (the state being transitioned from) and
to (the state being transitioned to) are added.
# Create tparams_transprobs object hesim_dat <- hesim_data(strategies = data.frame(strategy_id = 1:2), patients = data.frame(patient_id = 1:3)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- runif(nrow(tpmat_id), .6, .7) + .05 * (tpmat_id$strategy_id == 2) tpmat <- tpmatrix( C, p_12, 0, 1 ) tprobs <- tparams_transprobs(tpmat, tpmat_id) # Convert to data.table in "wide" format as.data.table(tprobs) as.data.table(tprobs, prefix = "") as.data.table(tprobs, prefix = "", sep = ".") # Convert to data.table in "long: format as.data.table(tprobs, long = TRUE)# Create tparams_transprobs object hesim_dat <- hesim_data(strategies = data.frame(strategy_id = 1:2), patients = data.frame(patient_id = 1:3)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- runif(nrow(tpmat_id), .6, .7) + .05 * (tpmat_id$strategy_id == 2) tpmat <- tpmatrix( C, p_12, 0, 1 ) tprobs <- tparams_transprobs(tpmat, tpmat_id) # Convert to data.table in "wide" format as.data.table(tprobs) as.data.table(tprobs, prefix = "") as.data.table(tprobs, prefix = "", sep = ".") # Convert to data.table in "long: format as.data.table(tprobs, long = TRUE)
Quickly plot state probabilities stored in a stateprobs object.
## S3 method for class 'stateprobs' autoplot( object, labels = NULL, ci = FALSE, prob = 0.95, ci_style = c("ribbon", "line"), geom_alpha = 0.3, ... )## S3 method for class 'stateprobs' autoplot( object, labels = NULL, ci = FALSE, prob = 0.95, ci_style = c("ribbon", "line"), geom_alpha = 0.3, ... )
object |
A |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
ci |
A logical value indicating whether confidence intervals should be
plotted. Default is |
prob |
A numeric scalar in the interval |
ci_style |
Style to use for the confidence interval if |
geom_alpha |
The opacity for the shaded confidence bands when
|
... |
Further arguments passed to and from methods. Currently unused. |
A ggplot object.
If there are multiple patients/groups, then state probabilities are
averaged across patients/groups (using the weights in patient_wt if available)
prior to plotting.
Psm for an example.
Quickly plot survival curves stored in a survival object.
## S3 method for class 'survival' autoplot( object, labels = NULL, ci = FALSE, prob = 0.95, ci_style = c("ribbon", "line"), geom_alpha = 0.3, ... )## S3 method for class 'survival' autoplot( object, labels = NULL, ci = FALSE, prob = 0.95, ci_style = c("ribbon", "line"), geom_alpha = 0.3, ... )
object |
A |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
ci |
A logical value indicating whether confidence intervals should be
plotted. Default is |
prob |
A numeric scalar in the interval |
ci_style |
Style to use for the confidence interval if |
geom_alpha |
The opacity for the shaded confidence bands when
|
... |
Further arguments passed to and from methods. Currently unused. |
A ggplot object.
If there are multiple patients, then survival probabilities are
averaged across patients (using the weights in patient_wt if available)
prior to plotting.
Psm for an example.
An object that summarizes simulated measures of clinical effectiveness and costs from a simulation model for use in a cost-effectiveness analysis.
A list containing two elements:
costsTotal (discounted) costs by category.
qalys(Discounted) quality-adjusted life-years.
The costs data.table contains the following columns:
The cost category.
The discount rate.
A randomly sampled parameter set from the probabilistic sensitivity analysis (PSA)
The treatment strategy ID.
An optional column denoting a subgroup. If not included, it is assumed that a single subgroup is being analyzed.
Costs.
The qalys data.table contains the following columns:
The discount rate.
A randomly sampled parameter set from the probabilistic sensitivity analysis (PSA)
The treatment strategy ID.
An optional column denoting a subgroup. If not included, it is assumed that a single subgroup is being analyzed.
Quality-adjusted life-years
Conduct cost-effectiveness analysis (CEA) given output of an economic model; that is, summarize a probabilistic sensitivity analysis (PSA), possibly by subgroup.
cea() computes the probability that
each treatment is most cost-effective, output for a cost-effectiveness acceptability frontier,
the expected value of perfect information, and the net monetary benefit for each treatment.
cea_pw() conducts pairwise CEA by comparing strategies to a comparator. Computed
quantities include the incremental cost-effectiveness ratio, the
incremental net monetary benefit, output for a cost-effectiveness plane,
and output for a cost-effectiveness acceptability curve.
cea(x, ...) cea_pw(x, ...) ## Default S3 method: cea(x, k = seq(0, 2e+05, 500), sample, strategy, grp = NULL, e, c, ...) ## Default S3 method: cea_pw( x, k = seq(0, 2e+05, 500), comparator, sample, strategy, grp = NULL, e, c, ... ) ## S3 method for class 'ce' cea(x, k = seq(0, 2e+05, 500), dr_qalys, dr_costs, ...) ## S3 method for class 'ce' cea_pw(x, k = seq(0, 2e+05, 500), comparator, dr_qalys, dr_costs, ...)cea(x, ...) cea_pw(x, ...) ## Default S3 method: cea(x, k = seq(0, 2e+05, 500), sample, strategy, grp = NULL, e, c, ...) ## Default S3 method: cea_pw( x, k = seq(0, 2e+05, 500), comparator, sample, strategy, grp = NULL, e, c, ... ) ## S3 method for class 'ce' cea(x, k = seq(0, 2e+05, 500), dr_qalys, dr_costs, ...) ## S3 method for class 'ce' cea_pw(x, k = seq(0, 2e+05, 500), comparator, dr_qalys, dr_costs, ...)
x |
An object of simulation output characterizing the probability distribution
of clinical effectiveness and costs. If the default method is used, then |
... |
Further arguments passed to or from other methods. Currently unused. |
k |
Vector of willingness to pay values. |
sample |
Character name of column from |
strategy |
Character name of column from |
grp |
Character name of column from |
e |
Character name of column from |
c |
Character name of column from |
comparator |
Name of the comparator strategy in |
dr_qalys |
Discount rate for quality-adjusted life-years (QALYs). |
dr_costs |
Discount rate for costs. |
cea() returns a list of four data.table elements.
A data.table of the mean, 2.5% quantile, and 97.5%
quantile by strategy and group for clinical effectiveness and costs.
The probability that each strategy is the most effective treatment
for each group for the range of specified willingness to pay values. In addition,
the column best denotes the optimal strategy (i.e., the strategy with the
highest expected net monetary benefit), which can be used to plot the
cost-effectiveness acceptability frontier (CEAF).
The expected value of perfect information (EVPI) by group for the range of specified willingness to pay values. The EVPI is computed by subtracting the expected net monetary benefit given current information (i.e., the strategy with the highest expected net monetary benefit) from the expected net monetary benefit given perfect information.
The mean, 2.5% quantile, and 97.5% quantile of net monetary benefits for the range of specified willingness to pay values.
cea_pw also returns a list of four data.table elements:
A data.table of the mean, 2.5% quantile, and 97.5% quantile by strategy and group for incremental clinical effectiveness and costs.
Incremental effectiveness and incremental cost for each simulated parameter set by strategy and group. Can be used to plot a cost-effectiveness plane.
Values needed to plot a cost-effectiveness acceptability curve by group. The CEAC plots the probability that each strategy is more cost-effective than the comparator for the specified willingness to pay values.
The mean, 2.5% quantile, and 97.5% quantile of incremental net monetary benefits for the range of specified willingness to pay values.
library("data.table") library("ggplot2") theme_set(theme_bw()) # Simulation output n_samples <- 30 sim <- data.table(sample = rep(seq(n_samples), 4), c = c(rlnorm(n_samples, 5, .1), rlnorm(n_samples, 5, .1), rlnorm(n_samples, 11, .1), rlnorm(n_samples, 11, .1)), e = c(rnorm(n_samples, 8, .2), rnorm(n_samples, 8.5, .1), rnorm(n_samples, 11, .6), rnorm(n_samples, 11.5, .6)), strategy_id = rep(1:2, each = n_samples * 2), grp_id = rep(rep(1:2, each = n_samples), 2) ) # Cost-effectiveness analysis cea_out <- cea(sim, k = seq(0, 200000, 500), sample = "sample", strategy = "strategy_id", grp = "grp_id", e = "e", c = "c") names(cea_out) ## Some sample output ## The probability that each strategy is the most cost-effective ## in each group with a willingness to pay of 20,000 cea_out$mce[k == 20000] # Pairwise cost-effectiveness analysis cea_pw_out <- cea_pw(sim, k = seq(0, 200000, 500), comparator = 1, sample = "sample", strategy = "strategy_id", grp = "grp_id", e = "e", c = "c") names(cea_pw_out) ## Some sample output ## The cost-effectiveness acceptability curve head(cea_pw_out$ceac[k >= 20000]) # Summarize the incremental cost-effectiveness ratio labs <- list(strategy_id = c("Strategy 1" = 1, "Strategy 2" = 2), grp_id = c("Group 1" = 1, "Group 2" = 2)) format(icer(cea_pw_out, labels = labs)) # Plots plot_ceplane(cea_pw_out, label = labs) plot_ceac(cea_out, label = labs) plot_ceac(cea_pw_out, label = labs) plot_ceaf(cea_out, label = labs) plot_evpi(cea_out, label = labs)library("data.table") library("ggplot2") theme_set(theme_bw()) # Simulation output n_samples <- 30 sim <- data.table(sample = rep(seq(n_samples), 4), c = c(rlnorm(n_samples, 5, .1), rlnorm(n_samples, 5, .1), rlnorm(n_samples, 11, .1), rlnorm(n_samples, 11, .1)), e = c(rnorm(n_samples, 8, .2), rnorm(n_samples, 8.5, .1), rnorm(n_samples, 11, .6), rnorm(n_samples, 11.5, .6)), strategy_id = rep(1:2, each = n_samples * 2), grp_id = rep(rep(1:2, each = n_samples), 2) ) # Cost-effectiveness analysis cea_out <- cea(sim, k = seq(0, 200000, 500), sample = "sample", strategy = "strategy_id", grp = "grp_id", e = "e", c = "c") names(cea_out) ## Some sample output ## The probability that each strategy is the most cost-effective ## in each group with a willingness to pay of 20,000 cea_out$mce[k == 20000] # Pairwise cost-effectiveness analysis cea_pw_out <- cea_pw(sim, k = seq(0, 200000, 500), comparator = 1, sample = "sample", strategy = "strategy_id", grp = "grp_id", e = "e", c = "c") names(cea_pw_out) ## Some sample output ## The cost-effectiveness acceptability curve head(cea_pw_out$ceac[k >= 20000]) # Summarize the incremental cost-effectiveness ratio labs <- list(strategy_id = c("Strategy 1" = 1, "Strategy 2" = 2), grp_id = c("Group 1" = 1, "Group 2" = 2)) format(icer(cea_pw_out, labels = labs)) # Plots plot_ceplane(cea_pw_out, label = labs) plot_ceac(cea_out, label = labs) plot_ceac(cea_pw_out, label = labs) plot_ceaf(cea_out, label = labs) plot_evpi(cea_out, label = labs)
Simulate outcomes from a cohort discrete time state transition model.
An R6::R6Class object.
trans_modelThe model for health state transitions. Must be an object
of class CohortDtstmTrans.
utility_modelThe model for health state utility. Must be an object of
class StateVals.
cost_modelsThe models used to predict costs by health state.
Must be a list of objects of class StateVals, where each element of the
list represents a different cost category.
stateprobs_An object of class stateprobs simulated using $sim_stateprobs().
qalys_An object of class qalys simulated using $sim_qalys().
costs_An object of class costs simulated using $sim_costs().
new()
Create a new CohortDtstm object.
CohortDtstm$new(trans_model = NULL, utility_model = NULL, cost_models = NULL)
trans_modelThe trans_model field.
utility_modelThe utility_model field.
cost_modelsThe cost_models field.
A new CohortDtstm object.
sim_stateprobs()
Simulate health state probabilities using CohortDtstmTrans$sim_stateprobs().
CohortDtstm$sim_stateprobs(n_cycles)
n_cyclesThe number of model cycles to simulate the model for.
An instance of self with simulated output of class stateprobs
stored in stateprobs_.
sim_qalys()
Simulate quality-adjusted life-years (QALYs) as a function of stateprobs_ and
utility_model. See sim_qalys() for details.
CohortDtstm$sim_qalys(
dr = 0.03,
integrate_method = c("trapz", "riemann_left", "riemann_right"),
lys = TRUE
)drDiscount rate.
integrate_methodMethod used to integrate state values when computing
costs or QALYs. Options are trapz for the trapezoid rule,
riemann_left for a left Riemann sum, and
riemann_right for a right Riemann sum.
lysIf TRUE, then life-years are simulated in addition to QALYs.
An instance of self with simulated output of class qalys stored
in qalys_.
sim_costs()
Simulate costs as a function of stateprobs_ and cost_models.
See sim_costs() for details.
CohortDtstm$sim_costs(
dr = 0.03,
integrate_method = c("trapz", "riemann_left", "riemann_right")
)drDiscount rate.
integrate_methodMethod used to integrate state values when computing
costs or QALYs. Options are trapz for the trapezoid rule,
riemann_left for a left Riemann sum, and
riemann_right for a right Riemann sum.
An instance of self with simulated output of class costs stored
in costs_.
summarize()
Summarize costs and QALYs so that cost-effectiveness analysis can be performed.
See summarize_ce().
CohortDtstm$summarize(by_grp = FALSE)
by_grpIf TRUE, then costs and QALYs are computed by subgroup. If
FALSE, then costs and QALYs are aggregated across all patients (and subgroups).
clone()
The objects of this class are cloneable with this method.
CohortDtstm$clone(deep = FALSE)
deepWhether to make a deep clone.
Incerti and Jansen (2021). See Section 2.1 for a description of a cohort DTSTM and details on simulating costs and QALYs from state probabilities. An example in oncology is provided in Section 4.3.
CohortDtstm objects can be created from model objects as
documented in create_CohortDtstm(). The CohortDtstmTrans documentation
describes the class for the transition model and the StateVals documentation
describes the class for the cost and utility models. A CohortDtstmTrans
object is typically created using create_CohortDtstmTrans().
There are currently three relevant vignettes. vignette("markov-cohort")
details a relatively simple Markov model and
vignette("markov-inhomogeneous-cohort") describes a more complex time
inhomogeneous model in which transition probabilities vary in every model
cycle. The vignette("mlogit") shows how a transition model can be parameterized
using a multinomial logistic regression model when transition data is collected
at evenly spaced intervals.
library("data.table") library("ggplot2") theme_set(theme_bw()) set.seed(102) # NOTE: This example replicates the "Simple Markov cohort model" # vignette using a different approach. Here, we explicitly construct # the transition probabilities "by hand". In the vignette, the transition # probabilities are defined using expressions (i.e., by using # `define_model()`). The `define_model()` approach does (more or less) what # is done here under the hood. # (0) Model setup hesim_dat <- hesim_data( strategies = data.table( strategy_id = 1:2, strategy_name = c("Monotherapy", "Combination therapy") ), patients <- data.table(patient_id = 1), states = data.table( state_id = 1:3, state_name = c("State A", "State B", "State C") ) ) n_states <- nrow(hesim_dat$states) + 1 labs <- get_labels(hesim_dat) # (1) Parameters n_samples <- 10 # Number of samples for PSA ## Transition matrix ### Input data (one transition matrix for each parameter sample, ### treatment strategy, patient, and time interval) p_id <- tpmatrix_id(expand(hesim_dat, times = c(0, 2)), n_samples) N <- nrow(p_id) ### Transition matrices (one for each row in p_id) p <- array(NA, dim = c(n_states, n_states, nrow(p_id))) #### Baseline risk trans_mono <- rbind( c(1251, 350, 116, 17), c(0, 731, 512, 15), c(0, 0, 1312, 437), c(0, 0, 0, 469) ) mono_ind <- which(p_id$strategy_id == 1 | p_id$time_id == 2) p[,, mono_ind] <- rdirichlet_mat(n = 2, trans_mono) #### Apply relative risks combo_ind <- setdiff(1:nrow(p_id), mono_ind) lrr_se <- (log(.710) - log(.365))/(2 * qnorm(.975)) rr <- rlnorm(n_samples, meanlog = log(.509), sdlog = lrr_se) rr_indices <- list( # Indices of transition matrix to apply RR to c(1, 2), c(1, 3), c(1, 4), c(2, 3), c(2, 4), c(3, 4) ) rr_mat <- matrix(rr, nrow = n_samples, ncol = length(rr_indices)) p[,, combo_ind] <- apply_rr(p[, , mono_ind], rr = rr_mat, index = rr_indices) tp <- tparams_transprobs(p, p_id) ## Utility utility_tbl <- stateval_tbl( data.table( state_id = 1:3, est = c(1, 1, 1) ), dist = "fixed" ) ## Costs drugcost_tbl <- stateval_tbl( data.table( strategy_id = c(1, 1, 2, 2), time_start = c(0, 2, 0, 2), est = c(2278, 2278, 2278 + 2086.50, 2278) ), dist = "fixed" ) dmedcost_tbl <- stateval_tbl( data.table( state_id = 1:3, mean = c(A = 1701, B = 1774, C = 6948), se = c(A = 1701, B = 1774, C = 6948) ), dist = "gamma" ) cmedcost_tbl <- stateval_tbl( data.table( state_id = 1:3, mean = c(A = 1055, B = 1278, C = 2059), se = c(A = 1055, B = 1278, C = 2059) ), dist = "gamma" ) # (2) Simulation ## Constructing the economic model ### Transition probabilities transmod <- CohortDtstmTrans$new(params = tp) ### Utility utilitymod <- create_StateVals(utility_tbl, hesim_data = hesim_dat, n = n_samples) ### Costs drugcostmod <- create_StateVals(drugcost_tbl, hesim_data = hesim_dat, n = n_samples) dmedcostmod <- create_StateVals(dmedcost_tbl, hesim_data = hesim_dat, n = n_samples) cmedcostmod <- create_StateVals(cmedcost_tbl, hesim_data = hesim_dat, n = n_samples) costmods <- list(drug = drugcostmod, direct_medical = dmedcostmod, community_medical = cmedcostmod) ### Economic model econmod <- CohortDtstm$new(trans_model = transmod, utility_model = utilitymod, cost_models = costmods) ## Simulating outcomes econmod$sim_stateprobs(n_cycles = 20) autoplot(econmod$stateprobs_, ci = TRUE, ci_style = "ribbon", labels = labs) econmod$sim_qalys(dr = 0, integrate_method = "riemann_right") econmod$sim_costs(dr = 0.06, integrate_method = "riemann_right") # (3) Decision analysis ce_sim <- econmod$summarize() wtp <- seq(0, 25000, 500) cea_pw_out <- cea_pw(ce_sim, comparator = 1, dr_qalys = 0, dr_costs = .06, k = wtp) format(icer(cea_pw_out))library("data.table") library("ggplot2") theme_set(theme_bw()) set.seed(102) # NOTE: This example replicates the "Simple Markov cohort model" # vignette using a different approach. Here, we explicitly construct # the transition probabilities "by hand". In the vignette, the transition # probabilities are defined using expressions (i.e., by using # `define_model()`). The `define_model()` approach does (more or less) what # is done here under the hood. # (0) Model setup hesim_dat <- hesim_data( strategies = data.table( strategy_id = 1:2, strategy_name = c("Monotherapy", "Combination therapy") ), patients <- data.table(patient_id = 1), states = data.table( state_id = 1:3, state_name = c("State A", "State B", "State C") ) ) n_states <- nrow(hesim_dat$states) + 1 labs <- get_labels(hesim_dat) # (1) Parameters n_samples <- 10 # Number of samples for PSA ## Transition matrix ### Input data (one transition matrix for each parameter sample, ### treatment strategy, patient, and time interval) p_id <- tpmatrix_id(expand(hesim_dat, times = c(0, 2)), n_samples) N <- nrow(p_id) ### Transition matrices (one for each row in p_id) p <- array(NA, dim = c(n_states, n_states, nrow(p_id))) #### Baseline risk trans_mono <- rbind( c(1251, 350, 116, 17), c(0, 731, 512, 15), c(0, 0, 1312, 437), c(0, 0, 0, 469) ) mono_ind <- which(p_id$strategy_id == 1 | p_id$time_id == 2) p[,, mono_ind] <- rdirichlet_mat(n = 2, trans_mono) #### Apply relative risks combo_ind <- setdiff(1:nrow(p_id), mono_ind) lrr_se <- (log(.710) - log(.365))/(2 * qnorm(.975)) rr <- rlnorm(n_samples, meanlog = log(.509), sdlog = lrr_se) rr_indices <- list( # Indices of transition matrix to apply RR to c(1, 2), c(1, 3), c(1, 4), c(2, 3), c(2, 4), c(3, 4) ) rr_mat <- matrix(rr, nrow = n_samples, ncol = length(rr_indices)) p[,, combo_ind] <- apply_rr(p[, , mono_ind], rr = rr_mat, index = rr_indices) tp <- tparams_transprobs(p, p_id) ## Utility utility_tbl <- stateval_tbl( data.table( state_id = 1:3, est = c(1, 1, 1) ), dist = "fixed" ) ## Costs drugcost_tbl <- stateval_tbl( data.table( strategy_id = c(1, 1, 2, 2), time_start = c(0, 2, 0, 2), est = c(2278, 2278, 2278 + 2086.50, 2278) ), dist = "fixed" ) dmedcost_tbl <- stateval_tbl( data.table( state_id = 1:3, mean = c(A = 1701, B = 1774, C = 6948), se = c(A = 1701, B = 1774, C = 6948) ), dist = "gamma" ) cmedcost_tbl <- stateval_tbl( data.table( state_id = 1:3, mean = c(A = 1055, B = 1278, C = 2059), se = c(A = 1055, B = 1278, C = 2059) ), dist = "gamma" ) # (2) Simulation ## Constructing the economic model ### Transition probabilities transmod <- CohortDtstmTrans$new(params = tp) ### Utility utilitymod <- create_StateVals(utility_tbl, hesim_data = hesim_dat, n = n_samples) ### Costs drugcostmod <- create_StateVals(drugcost_tbl, hesim_data = hesim_dat, n = n_samples) dmedcostmod <- create_StateVals(dmedcost_tbl, hesim_data = hesim_dat, n = n_samples) cmedcostmod <- create_StateVals(cmedcost_tbl, hesim_data = hesim_dat, n = n_samples) costmods <- list(drug = drugcostmod, direct_medical = dmedcostmod, community_medical = cmedcostmod) ### Economic model econmod <- CohortDtstm$new(trans_model = transmod, utility_model = utilitymod, cost_models = costmods) ## Simulating outcomes econmod$sim_stateprobs(n_cycles = 20) autoplot(econmod$stateprobs_, ci = TRUE, ci_style = "ribbon", labels = labs) econmod$sim_qalys(dr = 0, integrate_method = "riemann_right") econmod$sim_costs(dr = 0.06, integrate_method = "riemann_right") # (3) Decision analysis ce_sim <- econmod$summarize() wtp <- seq(0, 25000, 500) cea_pw_out <- cea_pw(ce_sim, comparator = 1, dr_qalys = 0, dr_costs = .06, k = wtp) format(icer(cea_pw_out))
Simulate health state transitions in a cohort discrete time state transition model.
An R6::R6Class object.
paramsParameters for simulating health state transitions.
Supports objects of class tparams_transprobs or params_mlogit_list.
input_dataAn object of class input_mats.
cycle_lengthThe length of a model cycle in terms of years.
The default is 1 meaning that model cycles are 1 year long.
absorbingA numeric vector denoting the states that are
absorbing states; i.e., states that cannot be transitioned from.
Each element should correspond to a state_id,
which should, in turn, be the index of the health state.
start_stateprobsA non-negative vector with length equal to the number of
health states containing the probability that the cohort is in each health
state at the start of the simulation. For example,
if there were three states and the cohort began the simulation in state 1,
then start_stateprobs = c(1, 0, 0). Automatically normalized to sum to 1.
If NULL, then a vector with the first element equal to 1 and
all remaining elements equal to 0.
trans_matA transition matrix describing the states and transitions
in a discrete-time multi-state model. Only required if the model is
parameterized using multinomial logistic regression. The (i,j) element
represents a transition from state i to state j. Each possible transition
from row i should be based on a separate multinomial logistic regression
and ordered from 0 to K - 1 where K is the number of
possible transitions. Transitions that are not possible should be NA.
and the reference category for each row should be 0.
new()
Create a new CohortDtstmTrans object.
CohortDtstmTrans$new( params, input_data = NULL, trans_mat = NULL, start_stateprobs = NULL, cycle_length = 1, absorbing = NULL )
paramsThe params field.
input_dataThe input_data field.
trans_matThe trans_mat field.
start_stateprobsThe start_stateprobs field.
cycle_lengthThe cycle_length field.
absorbingThe absorbing field. If NULL, then the constructor
will determine which states are absorbing automatically; non NULL values
will override this behavior.
A new CohortDtstmTrans object.
sim_stateprobs()
Simulate probability of being in each health state during each model cycle.
CohortDtstmTrans$sim_stateprobs(n_cycles)
n_cyclesThe number of model cycles to simulate the model for.
An object of class stateprobs.
clone()
The objects of this class are cloneable with this method.
CohortDtstmTrans$clone(deep = FALSE)
deepWhether to make a deep clone.
create_CohortDtstmTrans() creates a CohortDtstmTrans object from either
a fitted statistical model or a parameter object. A complete economic model can be implemented
with the CohortDtstm class.
library("msm") library("data.table") set.seed(101) # We consider two examples that have the same treatment strategies and patients. # One model is parameterized by fitting a multi-state model with the "msm" # package; in the second model, the parameters are entered "manually" with # a "params_mlogit_list" object. # MODEL SETUP strategies <- data.table( strategy_id = c(1, 2, 3), strategy_name = c("SOC", "New 1", "New 2") ) patients <- data.table(patient_id = 1:2) hesim_dat <- hesim_data( strategies = strategies, patients = patients ) # EXAMPLE #1: msm ## Fit multi-state model with panel data via msm qinit <- rbind( c(0, 0.28163, 0.01239), c(0, 0, 0.10204), c(0, 0, 0) ) fit <- msm(state_id ~ time, subject = patient_id, data = onc3p[patient_id %in% sample(patient_id, 100)], covariates = list("1-2" =~ strategy_name), qmatrix = qinit) ## Simulation model transmod_data <- expand(hesim_dat) transmod <- create_CohortDtstmTrans(fit, input_data = transmod_data, cycle_length = 1/2, fixedpars = 2, n = 2) transmod$sim_stateprobs(n_cycles = 2) # EXAMPLE #2: params_mlogit_list ## Input data transmod_data[, intercept := 1] transmod_data[, new1 := ifelse(strategy_name == "New 1", 1, 0)] transmod_data[, new2 := ifelse(strategy_name == "New 2", 1, 0)] ## Parameters n <- 10 transmod_params <- params_mlogit_list( ## Transitions from stable state (stable -> progression, stable -> death) stable = params_mlogit( coefs = list( progression = data.frame( intercept = rnorm(n, -0.65, .1), new1 = rnorm(n, log(.8), .02), new2 = rnorm(n, log(.7, .02)) ), death = data.frame( intercept = rnorm(n, -3.75, .1), new1 = rep(0, n), new2 = rep(0, n) ) ) ), ## Transition from progression state (progression -> death) progression = params_mlogit( coefs = list( death = data.frame( intercept = rnorm(n, 2.45, .1), new1 = rep(0, n), new2 = rep(0, n) ) ) ) ) transmod_params ## Simulation model tmat <- rbind(c(0, 1, 2), c(NA, 0, 1), c(NA, NA, NA)) transmod <- create_CohortDtstmTrans(transmod_params, input_data = transmod_data, trans_mat = tmat, cycle_length = 1) transmod$sim_stateprobs(n_cycles = 2)library("msm") library("data.table") set.seed(101) # We consider two examples that have the same treatment strategies and patients. # One model is parameterized by fitting a multi-state model with the "msm" # package; in the second model, the parameters are entered "manually" with # a "params_mlogit_list" object. # MODEL SETUP strategies <- data.table( strategy_id = c(1, 2, 3), strategy_name = c("SOC", "New 1", "New 2") ) patients <- data.table(patient_id = 1:2) hesim_dat <- hesim_data( strategies = strategies, patients = patients ) # EXAMPLE #1: msm ## Fit multi-state model with panel data via msm qinit <- rbind( c(0, 0.28163, 0.01239), c(0, 0, 0.10204), c(0, 0, 0) ) fit <- msm(state_id ~ time, subject = patient_id, data = onc3p[patient_id %in% sample(patient_id, 100)], covariates = list("1-2" =~ strategy_name), qmatrix = qinit) ## Simulation model transmod_data <- expand(hesim_dat) transmod <- create_CohortDtstmTrans(fit, input_data = transmod_data, cycle_length = 1/2, fixedpars = 2, n = 2) transmod$sim_stateprobs(n_cycles = 2) # EXAMPLE #2: params_mlogit_list ## Input data transmod_data[, intercept := 1] transmod_data[, new1 := ifelse(strategy_name == "New 1", 1, 0)] transmod_data[, new2 := ifelse(strategy_name == "New 2", 1, 0)] ## Parameters n <- 10 transmod_params <- params_mlogit_list( ## Transitions from stable state (stable -> progression, stable -> death) stable = params_mlogit( coefs = list( progression = data.frame( intercept = rnorm(n, -0.65, .1), new1 = rnorm(n, log(.8), .02), new2 = rnorm(n, log(.7, .02)) ), death = data.frame( intercept = rnorm(n, -3.75, .1), new1 = rep(0, n), new2 = rep(0, n) ) ) ), ## Transition from progression state (progression -> death) progression = params_mlogit( coefs = list( death = data.frame( intercept = rnorm(n, 2.45, .1), new1 = rep(0, n), new2 = rep(0, n) ) ) ) ) transmod_params ## Simulation model tmat <- rbind(c(0, 1, 2), c(NA, 0, 1), c(NA, NA, NA)) transmod <- create_CohortDtstmTrans(transmod_params, input_data = transmod_data, trans_mat = tmat, cycle_length = 1) transmod$sim_stateprobs(n_cycles = 2)
An object of class costs returned from methods
$sim_costs() in model classes that store simulated costs.
A costs object inherits from data.table and contains
the following columns:
A random sample from the PSA.
The treatment strategy ID.
The patient ID.
The subgroup ID.
The health state ID.
The rate used to discount costs.
The cost category (e.g., drug costs, medical costs, etc).
The simulated cost values.
CohortDtstm objectA generic function for creating an object of class CohortDtstm.
create_CohortDtstm(object, ...) ## S3 method for class 'model_def' create_CohortDtstm( object, input_data, cost_args = NULL, utility_args = NULL, ... )create_CohortDtstm(object, ...) ## S3 method for class 'model_def' create_CohortDtstm( object, input_data, cost_args = NULL, utility_args = NULL, ... )
object |
An object of the appropriate class. |
... |
Further arguments passed to |
input_data |
An object of class |
cost_args |
A list of further arguments passed to |
utility_args |
A list of further arguments passed to |
CohortDtstmTrans objectA generic function for creating an object of class CohortDtstmTrans.
create_CohortDtstmTrans(object, ...) ## S3 method for class 'multinom_list' create_CohortDtstmTrans( object, input_data, trans_mat, n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'msm' create_CohortDtstmTrans( object, input_data, cycle_length, n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'params_mlogit_list' create_CohortDtstmTrans(object, input_data, trans_mat, ...)create_CohortDtstmTrans(object, ...) ## S3 method for class 'multinom_list' create_CohortDtstmTrans( object, input_data, trans_mat, n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'msm' create_CohortDtstmTrans( object, input_data, cycle_length, n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'params_mlogit_list' create_CohortDtstmTrans(object, input_data, trans_mat, ...)
object |
An object of the appropriate class containing either a fitted statistical model or model parameters. |
... |
Further arguments passed to |
input_data |
An object of class |
trans_mat |
A transition matrix describing the states and transitions
in a discrete-time multi-state model. See |
n |
Number of random observations to draw. Not used if |
uncertainty |
Method determining how parameter uncertainty should be handled.
If |
cycle_length |
The length of a model cycle in terms of years. The default is 1 meaning that model cycles are 1 year long. |
Disease models may either be created from a fitted statistical
model or from a parameter object. In the case of the former, input_data
is a data frame like object that is used to look for variables from
the statistical model that are required for simulation. In this sense,
input_data is very similar to the newdata argument in most predict()
methods (e.g., see predict.lm()). In other words, variables used in the
formula of the statistical model must also be in input_data.
In the case of the latter, the columns of input_data must be named in a
manner that is consistent with the parameter object. In the typical case
(e.g., with params_surv or params_mlogit), the parameter object
contains coefficients from a regression model, usually stored as matrix
where rows index parameter samples (i.e., for a probabilistic sensitivity
analysis) and columns index model terms. In such instances, there must
be one column from input_data with the same name as each model term in the
coefficient matrix; that is, the columns in input_data are matched with
the columns of the coefficient matrices by name. If there are model terms
in the coefficient matrices that are not contained in input_data, then
an error will be thrown.
See CohortDtstmTrans for examples.
IndivCtstmTrans objectA generic function for creating an object of class IndivCtstmTrans.
create_IndivCtstmTrans(object, ...) ## S3 method for class 'flexsurvreg_list' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward"), n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'flexsurvreg' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward"), n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'params_surv' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward", "mix", "mixt"), reset_states = NULL, transition_types = NULL, ... ) ## S3 method for class 'params_surv_list' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward", "mix", "mixt"), reset_states = NULL, transition_types = NULL, ... )create_IndivCtstmTrans(object, ...) ## S3 method for class 'flexsurvreg_list' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward"), n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'flexsurvreg' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward"), n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'params_surv' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward", "mix", "mixt"), reset_states = NULL, transition_types = NULL, ... ) ## S3 method for class 'params_surv_list' create_IndivCtstmTrans( object, input_data, trans_mat, clock = c("reset", "forward", "mix", "mixt"), reset_states = NULL, transition_types = NULL, ... )
object |
An object of the appropriate class containing either a fitted multi-state model or parameters of a multi-state model. |
... |
Further arguments passed to |
input_data |
An object of class |
trans_mat |
The transition matrix describing the states and transitions in a
multi-state model in the format from the |
clock |
"reset" for a clock-reset model, "forward" for a clock-forward model,
"mix" for a mixture by state, and "mixt" for a mixture by transition
of clock-reset and clock-forward models. See the field |
n |
Number of random observations to draw. Not used if |
uncertainty |
Method determining how parameter uncertainty should be handled.
If |
reset_states |
A vector denoting the states in which time resets. See the field
|
transition_types |
A vector denoting the type for each transition. See the field
|
Disease models may either be created from a fitted statistical
model or from a parameter object. In the case of the former, input_data
is a data frame like object that is used to look for variables from
the statistical model that are required for simulation. In this sense,
input_data is very similar to the newdata argument in most predict()
methods (e.g., see predict.lm()). In other words, variables used in the
formula of the statistical model must also be in input_data.
In the case of the latter, the columns of input_data must be named in a
manner that is consistent with the parameter object. In the typical case
(e.g., with params_surv or params_mlogit), the parameter object
contains coefficients from a regression model, usually stored as matrix
where rows index parameter samples (i.e., for a probabilistic sensitivity
analysis) and columns index model terms. In such instances, there must
be one column from input_data with the same name as each model term in the
coefficient matrix; that is, the columns in input_data are matched with
the columns of the coefficient matrices by name. If there are model terms
in the coefficient matrices that are not contained in input_data, then
an error will be thrown.
Returns an R6::R6Class object of class IndivCtstmTrans.
See IndivCtstmTrans and IndivCtstm for examples.
create_params is a generic function for creating an object containing
parameters from a fitted statistical model. If uncertainty != "none",
then random samples from suitable probability distributions are returned.
create_params(object, ...) ## S3 method for class 'lm' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'multinom' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'multinom_list' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'flexsurvreg' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'flexsurvreg_list' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'partsurvfit' create_params( object, n = 1000, uncertainty = c("normal", "bootstrap", "none"), max_errors = 0, silent = FALSE, ... )create_params(object, ...) ## S3 method for class 'lm' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'multinom' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'multinom_list' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'flexsurvreg' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'flexsurvreg_list' create_params(object, n = 1000, uncertainty = c("normal", "none"), ...) ## S3 method for class 'partsurvfit' create_params( object, n = 1000, uncertainty = c("normal", "bootstrap", "none"), max_errors = 0, silent = FALSE, ... )
object |
A statistical model to randomly sample parameters from. |
... |
Currently unused. |
n |
Number of random observations to draw. Not used if |
uncertainty |
Method determining how parameter uncertainty should be handled.
If |
max_errors |
Maximum number of errors that are allowed when fitting statistical models during the bootstrap procedure. This argument may be useful if, for instance, the model fails to converge during some bootstrap replications. Default is 0. |
silent |
Logical indicating whether error messages should be suppressed. Passed to
the |
An object prefixed by params_. Mapping between create_params
and the classes of the returned objects are:
create_params.lm -> params_lm
create_params.multinom -> params_mlogit
create_params.multinom_list -> params_mlogit_list
create_params.flexsurvreg -> params_surv
create_params.flexsurvreg_list -> params_surv_list
create_params.partsurvfit -> params_surv_list
These methods are typically used alongside create_input_mats()
to create model objects as a function of input data and a
fitted statistical model. For instance,
create_PsmCurves() creates the survival model for a partitioned survival model,
create_IndivCtstmTrans() creates the transition model for an individual
continuous time state transition model,
create_CohortDtstmTrans() creates the transition model for a cohort discrete
time state transition model, and
create_StateVals() creates a health state values model.
# create_params.lm fit <- lm(costs ~ female, data = psm4_exdata$costs$medical) n <- 5 params_lm <- create_params(fit, n = n) head(params_lm$coefs) head(params_lm$sigma) # create_params.flexsurvreg library("flexsurv") fit <- flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist = "weibull") n <- 5 params_surv_wei <- create_params(fit, n = n) print(params_surv_wei$dist) head(params_surv_wei$coefs)# create_params.lm fit <- lm(costs ~ female, data = psm4_exdata$costs$medical) n <- 5 params_lm <- create_params(fit, n = n) head(params_lm$coefs) head(params_lm$sigma) # create_params.flexsurvreg library("flexsurv") fit <- flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist = "weibull") n <- 5 params_surv_wei <- create_params(fit, n = n) print(params_surv_wei$dist) head(params_surv_wei$coefs)
PsmCurves objectA generic function for creating a PsmCurves object.
create_PsmCurves(object, ...) ## S3 method for class 'flexsurvreg_list' create_PsmCurves( object, input_data, n = 1000, uncertainty = c("normal", "bootstrap", "none"), est_data = NULL, ... ) ## S3 method for class 'params_surv_list' create_PsmCurves(object, input_data, ...)create_PsmCurves(object, ...) ## S3 method for class 'flexsurvreg_list' create_PsmCurves( object, input_data, n = 1000, uncertainty = c("normal", "bootstrap", "none"), est_data = NULL, ... ) ## S3 method for class 'params_surv_list' create_PsmCurves(object, input_data, ...)
object |
An object of the appropriate class containing either fitted survival models or parameters of survival models. |
... |
Further arguments passed to or from other methods. Passed to |
input_data |
An object of class |
n |
Number of random observations to draw. Not used if |
uncertainty |
Method determining how parameter uncertainty should be handled.
If |
est_data |
A |
Disease models may either be created from a fitted statistical
model or from a parameter object. In the case of the former, input_data
is a data frame like object that is used to look for variables from
the statistical model that are required for simulation. In this sense,
input_data is very similar to the newdata argument in most predict()
methods (e.g., see predict.lm()). In other words, variables used in the
formula of the statistical model must also be in input_data.
In the case of the latter, the columns of input_data must be named in a
manner that is consistent with the parameter object. In the typical case
(e.g., with params_surv or params_mlogit), the parameter object
contains coefficients from a regression model, usually stored as matrix
where rows index parameter samples (i.e., for a probabilistic sensitivity
analysis) and columns index model terms. In such instances, there must
be one column from input_data with the same name as each model term in the
coefficient matrix; that is, the columns in input_data are matched with
the columns of the coefficient matrices by name. If there are model terms
in the coefficient matrices that are not contained in input_data, then
an error will be thrown.
Returns an R6Class object of class PsmCurves.
See PsmCurves and Psm for examples. PsmCurves provides
an example in which a model is parameterized both with
(via create_PsmCurves.flexsurvreg_list()) and without (via
create_PsmCurves.params_surv_list()) access to patient-level data.
The Psm example shows how state probabilities, costs, and utilities can
be computed from predicted survival curves.
StateVals objectcreate_StateVals() is a generic function for creating an object of class
StateVals from a fitted statistical model or a stateval_tbl
object.
create_StateVals(object, ...) ## S3 method for class 'lm' create_StateVals( object, input_data = NULL, n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'stateval_tbl' create_StateVals(object, hesim_data = NULL, n = 1000, ...)create_StateVals(object, ...) ## S3 method for class 'lm' create_StateVals( object, input_data = NULL, n = 1000, uncertainty = c("normal", "none"), ... ) ## S3 method for class 'stateval_tbl' create_StateVals(object, hesim_data = NULL, n = 1000, ...)
object |
A model object of the appropriate class. |
... |
Further arguments ( |
input_data |
An object of class |
n |
Number of random observations of the parameters to draw when parameters are fit using a statistical model. |
uncertainty |
Method determining how parameter uncertainty should be handled. See
documentation in |
hesim_data |
A |
If object is a stateval_tbl, then a hesim_data object is used
to specify treatment strategies, patients, and/or health states not included as
columns in the table, or, to match patients in the table to groups. Not required if
the table includes one row for each treatment strategy, patient, and health state
combination. Patients are matched to groups by specifying both a patient_id
and a grp_var column in the patients table.
A StateVals object.
See StateVals for documentation of the class and additional examples.
An example use case for create_StateVals.stateval_tbl() is provided in
the stateval_tbl() documentation.
set.seed(10) # EXAMPLE FOR `create_statevals.lm()` ## Simple example comparing two treatment strategies where ## medical costs vary by sex and health state ## Setup model hesim_dat <- hesim_data( strategies = data.frame(strategy_id = c(1, 2)), patients = data.frame( patient_id = c(1, 2), female = c(1, 0) ), states = data.frame( state_id = c(1, 2, 3), state_name = c("state1", "state2", "state3") ) ) ## Fit model medcost_estimation_data <- psm4_exdata$costs$medical medcost_estimation_data$time5 <- rbinom(nrow(medcost_estimation_data), 1, .5) # Illustrative time dummy medcost_fit <- lm(costs ~ female + state_name + time5, data = medcost_estimation_data) ## Create medical cost model ### Allow medical costs to vary across time in addition to by patient and ### health state medcost_times <- time_intervals( data.frame(time_start = c(0, 3, 5), time5 = c(0, 0, 1)) # Time dummy corresponds to time > 5 ) medcost_input_data <- expand(hesim_dat, by = c("strategies", "patients", "states"), times = medcost_times) medcost_model <- create_StateVals(medcost_fit, medcost_input_data, n = 1) ## Explore predictions from medical cost model ### We can assess predictions at multiple time points medcost_model$sim(t = c(1, 6), type = "predict")set.seed(10) # EXAMPLE FOR `create_statevals.lm()` ## Simple example comparing two treatment strategies where ## medical costs vary by sex and health state ## Setup model hesim_dat <- hesim_data( strategies = data.frame(strategy_id = c(1, 2)), patients = data.frame( patient_id = c(1, 2), female = c(1, 0) ), states = data.frame( state_id = c(1, 2, 3), state_name = c("state1", "state2", "state3") ) ) ## Fit model medcost_estimation_data <- psm4_exdata$costs$medical medcost_estimation_data$time5 <- rbinom(nrow(medcost_estimation_data), 1, .5) # Illustrative time dummy medcost_fit <- lm(costs ~ female + state_name + time5, data = medcost_estimation_data) ## Create medical cost model ### Allow medical costs to vary across time in addition to by patient and ### health state medcost_times <- time_intervals( data.frame(time_start = c(0, 3, 5), time5 = c(0, 0, 1)) # Time dummy corresponds to time > 5 ) medcost_input_data <- expand(hesim_dat, by = c("strategies", "patients", "states"), times = medcost_times) medcost_model <- create_StateVals(medcost_fit, medcost_input_data, n = 1) ## Explore predictions from medical cost model ### We can assess predictions at multiple time points medcost_model$sim(t = c(1, 6), type = "predict")
Create a data table of health state transitions from a transition matrix describing
the states and transitions in a multi-state model suitable for use with hesim_data.
create_trans_dt(trans_mat)create_trans_dt(trans_mat)
trans_mat |
A transition matrix in the format from the |
Returns a data.table::data.table in tidy format with three columns:
Health state transition ID.
The starting health state.
The health state that will be transitions to.
tmat <- rbind(c(NA, 1, 2), c(NA, NA, 3), c(NA, NA, NA)) create_trans_dt(tmat)tmat <- rbind(c(NA, 1, 2), c(NA, NA, 3), c(NA, NA, NA)) create_trans_dt(tmat)
A model expression is defined by specifying random number generation functions
for a probabilistic sensitivity analysis (PSA) and transformations of the sampled
parameters as a function of input_data. The unevaluated expressions
are evaluated with eval_model() and used to generate the model inputs needed to
create an economic model.
define_model(tparams_def, rng_def, params = NULL, n_states = NULL) eval_model(x, input_data)define_model(tparams_def, rng_def, params = NULL, n_states = NULL) eval_model(x, input_data)
tparams_def |
A tparams_def object or a list of
tparams_def objects. A list might be considered if time intervals
specified with the |
rng_def |
A rng_def object used to randomly draw samples of the parameters from suitable probability distributions. |
params |
Either (i) a list containing the values of parameters for random
number generation or (ii) parameter samples that have already been randomly
generated using |
n_states |
The number of health states (inclusive of all health states
including the the death state) in the model. If |
x |
An object of class |
input_data |
An object of class expanded_hesim_data expanded by patients and treatment strategies. |
eval_model() evaluates the expressions in an object of class
model_def returned by define_model() and is, in turn, used within
functions that instantiate economic models (e.g., create_CohortDtstm()).
The direct output of eval_model() can also be useful for understanding and debugging
model definitions, but it is not used directly for simulation.
Economic models are constructed as a function of input data and parameters:
Input data: Objects of class expanded_hesim_data consisting of the treatment strategies and patient population.
Parameters: The underlying parameter estimates from the literature
are first stored in a list (params argument). Random number generation
is then used to sample the parameters from suitable probability distributions
for the PSA (rng_def argument). Finally, the sampled parameters are
transformed as a function of the input data into values (e.g., elements of a
transition probability matrix) used for the simulation (tparams_def argument).
The params argument can be omitted if the underlying parameters values are
defined inside a define_rng() block.
define_model() returns an object of class model_def,
which is a list containing the arguments to the function. eval_model() returns
a list containing ID variables
identifying parameter samples, treatment strategies, patient cohorts, and time
intervals; the values of parameters of the transition probability matrix,
utilities, and/or cost categories; the number of health states; and the number
of random number generation samples for the PSA.
define_tparams(), define_rng()
# Data library("data.table") strategies <- data.table(strategy_id = 1:2, strategy_name = c("Monotherapy", "Combination therapy")) patients <- data.table(patient_id = 1) hesim_dat <- hesim_data(strategies = strategies, patients = patients) data <- expand(hesim_dat) # Model parameters rng_def <- define_rng({ alpha <- matrix(c(1251, 350, 116, 17, 0, 731, 512, 15, 0, 0, 1312, 437, 0, 0, 0, 469), nrow = 4, byrow = TRUE) rownames(alpha) <- colnames(alpha) <- c("A", "B", "C", "D") lrr_mean <- log(.509) lrr_se <- (log(.710) - log(.365))/(2 * qnorm(.975)) list( p_mono = dirichlet_rng(alpha), rr_comb = lognormal_rng(lrr_mean, lrr_se), u = 1, c_zido = 2278, c_lam = 2086.50, c_med = gamma_rng(mean = c(A = 2756, B = 3052, C = 9007), sd = c(A = 2756, B = 3052, C = 9007)) ) }, n = 2) tparams_def <- define_tparams({ rr = ifelse(strategy_name == "Monotherapy", 1, rr_comb) list( tpmatrix = tpmatrix( C, p_mono$A_B * rr, p_mono$A_C * rr, p_mono$A_D * rr, 0, C, p_mono$B_C * rr, p_mono$B_D * rr, 0, 0, C, p_mono$C_D * rr, 0, 0, 0, 1), utility = u, costs = list( drug = ifelse(strategy_name == "Monotherapy", c_zido, c_zido + c_lam), medical = c_med ) ) }) # Simulation ## Define the economic model model_def <- define_model( tparams_def = tparams_def, rng_def = rng_def) ### Evaluate the model expression to generate model inputs ### This can be useful for understanding the output of a model expression eval_model(model_def, data) ## Create an economic model with a factory function econmod <- create_CohortDtstm(model_def, data)# Data library("data.table") strategies <- data.table(strategy_id = 1:2, strategy_name = c("Monotherapy", "Combination therapy")) patients <- data.table(patient_id = 1) hesim_dat <- hesim_data(strategies = strategies, patients = patients) data <- expand(hesim_dat) # Model parameters rng_def <- define_rng({ alpha <- matrix(c(1251, 350, 116, 17, 0, 731, 512, 15, 0, 0, 1312, 437, 0, 0, 0, 469), nrow = 4, byrow = TRUE) rownames(alpha) <- colnames(alpha) <- c("A", "B", "C", "D") lrr_mean <- log(.509) lrr_se <- (log(.710) - log(.365))/(2 * qnorm(.975)) list( p_mono = dirichlet_rng(alpha), rr_comb = lognormal_rng(lrr_mean, lrr_se), u = 1, c_zido = 2278, c_lam = 2086.50, c_med = gamma_rng(mean = c(A = 2756, B = 3052, C = 9007), sd = c(A = 2756, B = 3052, C = 9007)) ) }, n = 2) tparams_def <- define_tparams({ rr = ifelse(strategy_name == "Monotherapy", 1, rr_comb) list( tpmatrix = tpmatrix( C, p_mono$A_B * rr, p_mono$A_C * rr, p_mono$A_D * rr, 0, C, p_mono$B_C * rr, p_mono$B_D * rr, 0, 0, C, p_mono$C_D * rr, 0, 0, 0, 1), utility = u, costs = list( drug = ifelse(strategy_name == "Monotherapy", c_zido, c_zido + c_lam), medical = c_med ) ) }) # Simulation ## Define the economic model model_def <- define_model( tparams_def = tparams_def, rng_def = rng_def) ### Evaluate the model expression to generate model inputs ### This can be useful for understanding the output of a model expression eval_model(model_def, data) ## Create an economic model with a factory function econmod <- create_CohortDtstm(model_def, data)
Random number generation expressions are used to
randomly sample model parameters from suitable distributions for probabilistic
sensitivity analysis. These functions are typically used when evaluating
an object of class model_def defined using define_model().
define_rng(expr, n = 1, ...) eval_rng(x, params = NULL, check = TRUE)define_rng(expr, n = 1, ...) eval_rng(x, params = NULL, check = TRUE)
expr |
An expression used to randomly draw variates for each parameter of
interest in the model. Braces should be used so that the result
of the last expression within the braces is evaluated. The expression must
return a list where each element is either a |
n |
Number of samples of the parameters to draw. |
... |
Additional arguments to pass to the environment used to evaluate
|
x |
An object of class |
params |
A list containing the values of parameters for random number
generation. Each element of the list should either be a |
check |
Whether to check the returned output so that (i) it returns a list
and (ii) each element has the correct length or number of rows. Default is |
hesim contains a number of random number generation functions
that return parameter samples in convenient formats
and do not typically require the number of samples, n, as arguments
(see rng_distributions). The random number generation expressions
are evaluated using eval_rng() and used within expr
in define_rng(). If a multivariate object is returned by eval_rng(),
then the rows are random samples and columns are
distinct parameters (e.g., costs for each health state, elements of a
transition probability matrix).
define_rng() returns an object of class rng_def,
which is a list containing the unevaluated random number generation
expressions passed to expr, n, and any additional arguments passed to
... . eval_rng() evaluates the rng_def object and
returns an eval_rng object containing the evaluated expression.
Parameters can be conveniently sampled from probability distributions
using a number of random number generation functions (see rng_distributions).
An economic model can be created with create_CohortDtstm() by using
define_rng() (or a previously evaluated eval_rng object)
alongside define_tparams() to define a model with define_model().
It can be useful to summarize an evaluated expression with summary.eval_rng().
params <- list( alpha = matrix(c(75, 25, 33, 67), byrow = TRUE, ncol = 2), inptcost_mean = c(A = 900, B = 1500, C = 2000), outptcost_mean = matrix(c(300, 600, 800, 400, 700, 700), ncol = 3, byrow = TRUE) ) rng_def <- define_rng({ aecost_mean <- c(500, 800, 1000) # Local object not # not returned by eval_rng() list( # Sampled values of parameters returned by eval_rng() p = dirichlet_rng(alpha), # Default column names inptcost = gamma_rng(mean = inptcost_mean, # Column names based on sd = inptcost_mean), # named vector outptcost = outptcost_mean, # No column names because # outptcost_mean has none. aecost = gamma_rng(mean = aecost_mean, # Explicit naming of columns sd = aecost_mean, names = aecost_colnames) ) }, n = 2, aecost_colnames = c("A", "B", "C")) # Add aecost_colnames to environment params_sample <- eval_rng(x = rng_def, params) summary(params_sample) params_sampleparams <- list( alpha = matrix(c(75, 25, 33, 67), byrow = TRUE, ncol = 2), inptcost_mean = c(A = 900, B = 1500, C = 2000), outptcost_mean = matrix(c(300, 600, 800, 400, 700, 700), ncol = 3, byrow = TRUE) ) rng_def <- define_rng({ aecost_mean <- c(500, 800, 1000) # Local object not # not returned by eval_rng() list( # Sampled values of parameters returned by eval_rng() p = dirichlet_rng(alpha), # Default column names inptcost = gamma_rng(mean = inptcost_mean, # Column names based on sd = inptcost_mean), # named vector outptcost = outptcost_mean, # No column names because # outptcost_mean has none. aecost = gamma_rng(mean = aecost_mean, # Explicit naming of columns sd = aecost_mean, names = aecost_colnames) ) }, n = 2, aecost_colnames = c("A", "B", "C")) # Add aecost_colnames to environment params_sample <- eval_rng(x = rng_def, params) summary(params_sample) params_sample
Transformed parameter expressions are used to transform the parameter
values sampled with eval_rng() as a function of input data
(treatment strategies and patients) and time
intervals. These functions are used when evaluating an object of class
model_def defined using define_model(). The transformed parameters
are ultimately converted into tparams objects and used to simulate outcomes with an
economic model.
define_tparams(expr, times = NULL, ...) eval_tparams(x, input_data, rng_params)define_tparams(expr, times = NULL, ...) eval_tparams(x, input_data, rng_params)
expr |
Expressions used to transform parameters. As with
|
times |
Distinct times denoting the stopping time of time intervals. |
... |
Additional arguments to pass to the environment used to evaluate
|
x |
An object of class |
input_data |
An object of class expanded_hesim_data (as
in |
rng_params |
Random samples of the parameters returned by |
define_tparams() is evaluated when creating economic models as a
function of model_def objects defined with define_model(). Operations
are "vectorized" in the sense that they are performed for each unique combination
of input_data and params. expr is evaluated in an environment including
each variable from input_data, all elements of rng_params, and a variable
time containing the values from times. The time variable can be used
to create models where parameters vary as a function of time.
eval_tparams() is not exported and is only meant for use within eval_model().
define_tparams() returns an object of class tparams_def,
which is a list containing the unevaluated "transformation" expressions
passed to expr, times, and any additional arguments passed to
... . eval_tparams() evaluates the tparams_def object
and should return a list of transformed parameter objects.
An object of class disprog returned from methods
$sim_disease() in model classes. It contains simulated trajectories
through a multi-state model.
A disprog object inherits from data.table and contains
the following columns:
A random sample from the PSA.
The treatment strategy ID.
The patient ID.
The health state ID transitioned from.
The health state ID transitioned to.
An indicator equal to 1 if a patient is in their final health state during the simulation and 0 otherwise.
The time at the start of the interval.
The time at the end of the interval.
The object also contains size and absorbing attributes.
The size attribute is a numeric vector with the elements n_samples,
n_strategies, n_patients, and n_states denoting the number of samples,
treatment strategies, patients, and health states The absorbing attribute
is a numeric vector containing the absorbing health states; i.e., the
health states that cannot be transitioned from. Operationally, an
absorbing state is a row in a transition matrix (as in the trans_mat field
of the IndivCtstmTrans class) with all NAs.
A disease progression object can be simulated with either the
IndivCtstm or IndivCtstmTrans classes.
Create a data table in long format from all combinations of specified tables from an object of class hesim_data and optionally time intervals. See "Details" for an explanation of how the expansion is done.
## S3 method for class 'hesim_data' expand(object, by = c("strategies", "patients"), times = NULL)## S3 method for class 'hesim_data' expand(object, by = c("strategies", "patients"), times = NULL)
object |
An object of class |
by |
A character vector of the names of the data tables in |
times |
Either a numeric vector of distinct times denoting the start of time intervals or a time_intervals object. |
This function is similar to expand.grid(), but works for data frames or data tables.
Specifically, it creates a data.table from all combinations of the supplied tables in object
and optionally the start of times intervals in times.
The supplied tables are determined using the by argument. The resulting dataset is sorted by
prioritizing ID variables as follows: (i) strategy_id, (ii) patient_id,
(iii) the health-related ID variable (either state_id or transition_id, and
(iv) the time intervals from times.
An object of class expanded_hesim_data, which is a data.table with an "id_vars"
attribute containing the names of the ID variables in the data table and, if times is
not NULL, a time_intervals object derived from times.
strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(65, 50, 75), gender = c("Female", "Female", "Male")) states <- data.frame(state_id = seq(1, 3), state_var = c(2, 1, 9)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) expand(hesim_dat, by = c("strategies", "patients")) expand(hesim_dat, by = c("strategies", "patients"), times = c(0, 2, 10))strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(65, 50, 75), gender = c("Female", "Female", "Male")) states <- data.frame(state_id = seq(1, 3), state_var = c(2, 1, 9)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) expand(hesim_dat, by = c("strategies", "patients")) expand(hesim_dat, by = c("strategies", "patients"), times = c(0, 2, 10))
This is a wrapper around msm::MatrixExp() that computes the exponential
of multiple square matrices.
expmat(x, t = 1, ...)expmat(x, t = 1, ...)
x |
An array of matrices. |
t |
An optional scaling factor for |
... |
Arguments to pass to |
This function is most useful when exponentiating transition intensity
matrices to produce transition probability matrices. To create transition
probability matrices for discrete time state transition models with annual
cycles, set t=1. An array of matrices is returned which can be used
to create the value element of a tparams_transprobs object. See
qmatrix() for an example.
Returns an array of exponentiated matrices. If length(t) > 1, then
length(t) arrays are returned for each element in x.
qmatrix.msm(), qmatrix.data.table()
Draw random samples from a generalized gamma distribution using the
parameterization from flexsurv. Written in C++
for speed. Equivalent to flexsurv::rgengamma.
fast_rgengamma(n, mu = 0, sigma = 1, Q)fast_rgengamma(n, mu = 0, sigma = 1, Q)
n |
Number of random observations to draw. |
mu |
Vector of location parameters. and columns correspond to rates during specified time intervals. |
sigma |
Vector of scale parameters as described in |
Q |
Vector of shape parameters. |
A vector of random samples from the generalized gamma distribution. The length of the sample is determined by n. The numerical arguments other than n are recycled so that the number of samples is equal to n.
n <- 1000 m <- 2 ; s <- 1.7; q <- 1 ptm <- proc.time() r1 <- fast_rgengamma(n, mu = m, sigma = s, Q = q) proc.time() - ptm ptm <- proc.time() library("flexsurv") r2 <- flexsurv::rgengamma(n, mu = m, sigma = s, Q = q) proc.time() - ptm summary(r1) summary(r2)n <- 1000 m <- 2 ; s <- 1.7; q <- 1 ptm <- proc.time() r1 <- fast_rgengamma(n, mu = m, sigma = s, Q = q) proc.time() - ptm ptm <- proc.time() library("flexsurv") r2 <- flexsurv::rgengamma(n, mu = m, sigma = s, Q = q) proc.time() - ptm summary(r1) summary(r2)
flexsurvreg objectsCombine flexsurvreg objects into a list.
flexsurvreg_list(...)flexsurvreg_list(...)
... |
Objects of class |
An object of class flexsurvreg_list.
library("flexsurv") fit1 <- flexsurv::flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist = "weibull") fit2 <- flexsurv::flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist = "exp") fsreg_list <- flexsurvreg_list(wei = fit1, exp = fit2) class(fsreg_list)library("flexsurv") fit1 <- flexsurv::flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist = "weibull") fit2 <- flexsurv::flexsurvreg(formula = Surv(futime, fustat) ~ 1, data = ovarian, dist = "exp") fsreg_list <- flexsurvreg_list(wei = fit1, exp = fit2) class(fsreg_list)
Get value labels for the ID variables in a hesim_data object and create a list
of named vectors that can be passed to formatting and plotting functions. This
lets users create nice labels for treatment strategies, subgroups, health states,
and/or transitions when presenting results.
get_labels( object, strategy = "strategy_name", grp = "grp_name", state = "state_name", transition = "transition_name", death_label = "Death" )get_labels( object, strategy = "strategy_name", grp = "grp_name", state = "state_name", transition = "transition_name", death_label = "Death" )
object |
An object of class |
strategy |
The name of the column in the |
grp |
The name of the column in the |
state |
The name of the column in the |
transition |
The name of the column in the |
death_label |
The label to use for the death health state. By default a
label named "Death" will be concatenated to the labels for the non-death health
states. The death state can be omitted from labels for the health states by setting
|
A list of named vectors containing the values and labels of variables. The elements of each vector are the values of a variable and the names are the labels. The names of the list are the names of the ID variables.
library("data.table") strategies <- data.table( strategy_id = c(1, 2), strategy_name = c("Strategy 1", "Strategy 2") ) patients <- data.table( patient_id = seq(1, 4), age = c(50, 55, 60, 65), grp_id = c(1, 1, 2, 2), grp_name = rep(c("Age 50-59", "Age 60-69"), each = 2) ) states <- data.table( state_id = seq(1, 2), state_name = c("State 1", "State 2") ) hesim_dat <- hesim_data( strategies = strategies, patients = patients, states = states ) labs <- get_labels(hesim_dat) labs # Pass to set_labels() d <- data.table(strategy_id = c(1, 1, 2, 2), grp_id = c(1, 2, 1, 2)) set_labels(d, labs, new_name = c("strategy_name", "grp_name")) dlibrary("data.table") strategies <- data.table( strategy_id = c(1, 2), strategy_name = c("Strategy 1", "Strategy 2") ) patients <- data.table( patient_id = seq(1, 4), age = c(50, 55, 60, 65), grp_id = c(1, 1, 2, 2), grp_name = rep(c("Age 50-59", "Age 60-69"), each = 2) ) states <- data.table( state_id = seq(1, 2), state_name = c("State 1", "State 2") ) hesim_dat <- hesim_data( strategies = strategies, patients = patients, states = states ) labs <- get_labels(hesim_dat) labs # Pass to set_labels() d <- data.table(strategy_id = c(1, 1, 2, 2), grp_id = c(1, 2, 1, 2)) set_labels(d, labs, new_name = c("strategy_name", "grp_name")) d
A list of tables required for health economic simulation modeling. This object is used to setup models by defining the treatment strategies, target population, and model structure.
hesim_data(strategies, patients, states = NULL, transitions = NULL)hesim_data(strategies, patients, states = NULL, transitions = NULL)
strategies |
A table of treatment strategies. Must contain the column
|
patients |
A table of patients. Must contain the column |
states |
A table of health states. Must contain the column
|
transitions |
A table of health state transitions. Must contain the column
|
Returns an object of class hesim_data, which is a list of data tables for
health economic simulation modeling.
Each table must either be a data.frame or data.table. All ID variables
within each table must be numeric vectors of integers and should be of the form
1,2,...N where N is the number of unique values of the ID variable.
expand.hesim_data(), get_labels()
strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(65, 50, 75), gender = c("Female", "Female", "Male")) states <- data.frame(state_id = seq(1, 3), state_var = c(2, 1, 9)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states)strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(65, 50, 75), gender = c("Female", "Female", "Male")) states <- data.frame(state_id = seq(1, 3), state_var = c(2, 1, 9)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states)
Generate a tidy table of incremental cost-effectiveness ratios (ICERs) given output from
cea_pw() with icer() and format for pretty printing with format.icer().
icer(x, prob = 0.95, k = 50000, labels = NULL, ...) ## S3 method for class 'icer' format( x, digits_qalys = 2, digits_costs = 0, pivot_from = "strategy", drop_grp = TRUE, pretty_names = TRUE, ... )icer(x, prob = 0.95, k = 50000, labels = NULL, ...) ## S3 method for class 'icer' format( x, digits_qalys = 2, digits_costs = 0, pivot_from = "strategy", drop_grp = TRUE, pretty_names = TRUE, ... )
x |
An object of class |
prob |
A numeric scalar in the interval |
k |
Willingness to pay per quality-adjusted life-year. |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
... |
Further arguments passed to and from methods. Currently unused. |
digits_qalys |
Number of digits to use to report QALYs. |
digits_costs |
Number of digits to use to report costs. |
pivot_from |
Character vector denoting a column or columns used to
"widen" the data. Should either be |
drop_grp |
If |
pretty_names |
Logical. If |
Note that icer() will report negative ICERs; however, format() will
correctly note whether a treatment strategy is dominated by or dominates the
reference treatment.
icer() returns an object of class icer that is a tidy
data.table with the following columns:
The treatment strategy.
The subgroup.
The outcome metric.
The point estimate computed as the average across the PSA samples.
The lower limit of the confidence interval.
The upper limit of the confidence interval.
format.icer() formats the table according to the arguments passed.
Computes incremental effect for all treatment strategies on outcome variables from a probabilistic sensitivity analysis relative to a comparator.
incr_effect(x, comparator, sample, strategy, grp = NULL, outcomes)incr_effect(x, comparator, sample, strategy, grp = NULL, outcomes)
x |
A |
comparator |
The comparator strategy. If the strategy column is a character variable, then must be a character; if the strategy column is an integer variable, then must be an integer. |
sample |
Character name of column denoting a randomly sampled parameter set. |
strategy |
Character name of column denoting treatment strategy. |
grp |
Character name of column denoting subgroup. If |
outcomes |
Name of columns to compute incremental changes for. |
A data.table containing the differences in the values of each variable
specified in outcomes between each treatment strategy and the
comparator.
# simulation output n_samples <- 100 sim <- data.frame(sample = rep(seq(n_samples), 4), c = c(rlnorm(n_samples, 5, .1), rlnorm(n_samples, 5, .1), rlnorm(n_samples, 11, .1), rlnorm(n_samples, 11, .1)), e = c(rnorm(n_samples, 8, .2), rnorm(n_samples, 8.5, .1), rnorm(n_samples, 11, .6), rnorm(n_samples, 11.5, .6)), strategy = rep(paste0("Strategy ", seq(1, 2)), each = n_samples * 2), grp = rep(rep(c("Group 1", "Group 2"), each = n_samples), 2) ) # calculate incremental effect of Strategy 2 relative to Strategy 1 by group ie <- incr_effect(sim, comparator = "Strategy 1", sample = "sample", strategy = "strategy", grp = "grp", outcomes = c("c", "e")) head(ie)# simulation output n_samples <- 100 sim <- data.frame(sample = rep(seq(n_samples), 4), c = c(rlnorm(n_samples, 5, .1), rlnorm(n_samples, 5, .1), rlnorm(n_samples, 11, .1), rlnorm(n_samples, 11, .1)), e = c(rnorm(n_samples, 8, .2), rnorm(n_samples, 8.5, .1), rnorm(n_samples, 11, .6), rnorm(n_samples, 11.5, .6)), strategy = rep(paste0("Strategy ", seq(1, 2)), each = n_samples * 2), grp = rep(rep(c("Group 1", "Group 2"), each = n_samples), 2) ) # calculate incremental effect of Strategy 2 relative to Strategy 1 by group ie <- incr_effect(sim, comparator = "Strategy 1", sample = "sample", strategy = "strategy", grp = "grp", outcomes = c("c", "e")) head(ie)
Simulate outcomes from an individual-level continuous time state transition
model (CTSTM). The class supports "clock-reset"
(i.e., semi-Markov), "clock-forward" (i.e., Markov), and mixtures of
clock-reset and clock-forward multi-state models as described in
IndivCtstmTrans.
An R6::R6Class object.
trans_modelThe model for health state transitions. Must be an object
of class IndivCtstmTrans.
utility_modelThe model for health state utility. Must be an object of
class StateVals.
cost_modelsThe models used to predict costs by health state.
Must be a list of objects of class StateVals, where each element of the
list represents a different cost category.
disprog_An object of class disprog.
stateprobs_An object of class stateprobs simulated using $sim_stateprobs().
qalys_An object of class qalys simulated using $sim_qalys().
costs_An object of class costs simulated using $sim_costs().
new()
Create a new IndivCtstm object.
IndivCtstm$new(trans_model = NULL, utility_model = NULL, cost_models = NULL)
trans_modelThe trans_model field.
utility_modelThe utility_model field.
cost_modelsThe cost_models field.
A new IndivCtstm object.
sim_disease()
Simulate disease progression (i.e., individual trajectories through a multi-state
model) using IndivCtstmTrans$sim_disease().
IndivCtstm$sim_disease(max_t = 100, max_age = 100, progress = NULL)
max_tA scalar or vector denoting the length of time to simulate the model. If a vector, must be equal to the number of simulated patients.
max_ageA scalar or vector denoting the maximum age to simulate each patient until. If a vector, must be equal to the number of simulated patients.
progressAn integer, specifying the PSA iteration (i.e., sample) that should be
printed every progress PSA iterations. For example, if progress = 2,
then every second PSA iteration is printed. Default is NULL,
in which case no output is printed.
An instance of self with simulated output stored in disprog_.
sim_stateprobs()
Simulate health state probabilities as a function of time using the
simulation output stored in disprog.
IndivCtstm$sim_stateprobs(t)
tA numeric vector of times.
An instance of self with simulated output of class stateprobs
stored in stateprobs_.
sim_qalys()
Simulate quality-adjusted life-years (QALYs) as a function of disprog_ and
utility_model.
IndivCtstm$sim_qalys(
dr = 0.03,
type = c("predict", "random"),
lys = TRUE,
by_patient = FALSE
)drDiscount rate.
type"predict" for mean values or "random" for random samples
as in $sim() in StateVals.
lysIf TRUE, then life-years are simulated in addition to QALYs.
by_patientIf TRUE, then QALYs and/or costs are computed at the patient level.
If FALSE, then they are averaged across patients by health state.
An instance of self with simulated output of
class qalys stored in qalys_.
sim_costs()
Simulate costs as a function of disprog_ and cost_models.
IndivCtstm$sim_costs(
dr = 0.03,
type = c("predict", "random"),
by_patient = FALSE,
max_t = Inf
)drDiscount rate.
type"predict" for mean values or "random" for random samples
as in $sim() in StateVals.
by_patientIf TRUE, then QALYs and/or costs are computed at the patient level.
If FALSE, then they are averaged across patients by health state.
max_tMaximum time duration to compute costs once a patient has
entered a (new) health state. By default, equal to Inf,
so that costs are computed over the entire duration that a patient is in
a given health state. If time varies by each cost category, then time
can also be passed as a numeric vector of length equal to the number of
cost categories (e.g., c(1, 2, Inf, 3) for a model with four cost categories).
An instance of self with simulated output of class costs
stored in costs_.
summarize()
Summarize costs and QALYs so that cost-effectiveness analysis can be performed.
See summarize_ce().
IndivCtstm$summarize(by_grp = FALSE)
by_grpIf TRUE, then costs and QALYs are computed by subgroup. If
FALSE, then costs and QALYs are aggregated across all patients (and subgroups).
clone()
The objects of this class are cloneable with this method.
IndivCtstm$clone(deep = FALSE)
deepWhether to make a deep clone.
Incerti and Jansen (2021). See Section 2.2 for a mathematical description of an individual-level CTSTM and Section 4.1 for an example in oncology.
The IndivCtstmTrans documentation
describes the class for the transition model and the StateVals documentation
describes the class for the cost and utility models. An IndivCtstmTrans
object is typically created using create_IndivCtstmTrans().
There are currently two relevant vignettes. vignette("mstate") shows how to
parameterize IndivCtstmTrans objects in cases where patient-level data is
available by fitting a multi-state models. vignette("markov-inhomogeneous-indiv")
shows how the time inhomogeneous Markov cohort model in
vignette("markov-inhomogeneous-cohort") can be developed as an individual
patient simulation; in doing so, it shows how IndivCtstm models can be
used even without access to patient-level data.
library("flexsurv") # Treatment strategies, target population, and model structure strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 50, 60), female = c(0, 0, 1)) states <- data.frame(state_id = c(1, 2)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) # Parameter estimation ## Multi-state model tmat <- rbind(c(NA, 1, 2), c(3, NA, 4), c(NA, NA, NA)) fits <- vector(length = max(tmat, na.rm = TRUE), mode = "list") surv_dat <- data.frame(mstate3_exdata$transitions) for (i in 1:length(fits)){ fits[[i]] <- flexsurvreg(Surv(years, status) ~ factor(strategy_id), data = surv_dat, subset = (trans == i), dist = "weibull") } fits <- flexsurvreg_list(fits) ## Utility utility_tbl <- stateval_tbl(data.frame(state_id = states$state_id, mean = mstate3_exdata$utility$mean, se = mstate3_exdata$utility$se), dist = "beta") ## Costs drugcost_tbl <- stateval_tbl(data.frame(strategy_id = strategies$strategy_id, est = mstate3_exdata$costs$drugs$costs), dist = "fixed") medcost_tbl <- stateval_tbl(data.frame(state_id = states$state_id, mean = mstate3_exdata$costs$medical$mean, se = mstate3_exdata$costs$medical$se), dist = "gamma") # Economic model n_samples = 2 ## Construct model ### Transitions transmod_data <- expand(hesim_dat) transmod <- create_IndivCtstmTrans(fits, input_data = transmod_data, trans_mat = tmat, n = n_samples) ### Utility utilitymod <- create_StateVals(utility_tbl, n = n_samples, hesim_data = hesim_dat) ### Costs drugcostmod <- create_StateVals(drugcost_tbl, n = n_samples, hesim_data = hesim_dat) medcostmod <- create_StateVals(medcost_tbl, n = n_samples, hesim_data = hesim_dat) costmods <- list(drugs = drugcostmod, medical = medcostmod) ### Combine ictstm <- IndivCtstm$new(trans_model = transmod, utility_model = utilitymod, cost_models = costmods) ## Simulate outcomes head(ictstm$sim_disease()$disprog_) head(ictstm$sim_stateprobs(t = c(0, 5, 10))$stateprobs_[t == 5]) ictstm$sim_qalys(dr = .03) ictstm$sim_costs(dr = .03) ### Summarize cost-effectiveness ce <- ictstm$summarize() head(ce) format(summary(ce), pivot_from = "strategy")library("flexsurv") # Treatment strategies, target population, and model structure strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 50, 60), female = c(0, 0, 1)) states <- data.frame(state_id = c(1, 2)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) # Parameter estimation ## Multi-state model tmat <- rbind(c(NA, 1, 2), c(3, NA, 4), c(NA, NA, NA)) fits <- vector(length = max(tmat, na.rm = TRUE), mode = "list") surv_dat <- data.frame(mstate3_exdata$transitions) for (i in 1:length(fits)){ fits[[i]] <- flexsurvreg(Surv(years, status) ~ factor(strategy_id), data = surv_dat, subset = (trans == i), dist = "weibull") } fits <- flexsurvreg_list(fits) ## Utility utility_tbl <- stateval_tbl(data.frame(state_id = states$state_id, mean = mstate3_exdata$utility$mean, se = mstate3_exdata$utility$se), dist = "beta") ## Costs drugcost_tbl <- stateval_tbl(data.frame(strategy_id = strategies$strategy_id, est = mstate3_exdata$costs$drugs$costs), dist = "fixed") medcost_tbl <- stateval_tbl(data.frame(state_id = states$state_id, mean = mstate3_exdata$costs$medical$mean, se = mstate3_exdata$costs$medical$se), dist = "gamma") # Economic model n_samples = 2 ## Construct model ### Transitions transmod_data <- expand(hesim_dat) transmod <- create_IndivCtstmTrans(fits, input_data = transmod_data, trans_mat = tmat, n = n_samples) ### Utility utilitymod <- create_StateVals(utility_tbl, n = n_samples, hesim_data = hesim_dat) ### Costs drugcostmod <- create_StateVals(drugcost_tbl, n = n_samples, hesim_data = hesim_dat) medcostmod <- create_StateVals(medcost_tbl, n = n_samples, hesim_data = hesim_dat) costmods <- list(drugs = drugcostmod, medical = medcostmod) ### Combine ictstm <- IndivCtstm$new(trans_model = transmod, utility_model = utilitymod, cost_models = costmods) ## Simulate outcomes head(ictstm$sim_disease()$disprog_) head(ictstm$sim_stateprobs(t = c(0, 5, 10))$stateprobs_[t == 5]) ictstm$sim_qalys(dr = .03) ictstm$sim_costs(dr = .03) ### Summarize cost-effectiveness ce <- ictstm$summarize() head(ce) format(summary(ce), pivot_from = "strategy")
Simulate health state transitions in an individual-level continuous time state transition model using parameters from a multi-state model.
An R6::R6Class object.
hesim::CtstmTrans -> IndivCtstmTrans
paramsAn object of class params_surv or params_surv_list.
input_dataInput data used to simulate health state transitions
by sample from the probabilistic sensitivity analysis (PSA), treatment strategy and patient.
Must be an object of class input_mats. If params contains parameters from
a list of models (i.e., of class params_surv_list), then input_data
must contain a unique row for each treatment strategy
and patient; if params contains parameters from a joint model
(i.e., of class params_surv), then input_data must contain a unique
row for each treatment strategy, patient, and transition.
trans_matA transition matrix describing the states and transitions
in a multi-state model in the format from the mstate package.
See the documentation for the argument "trans" in mstate::msprep.
start_stateA scalar or vector denoting the starting health state. Default is the first health state. If a vector, must be equal to the number of simulated patients.
start_ageA scalar or vector denoting the starting age of each patient in the simulation. Default is 38. If a vector, must be equal to the number of simulated patients.
death_stateThe death state in trans_mat. Used with max_age
in sim_disease as patients transition to this state upon reaching maximum age.
By default, it is set to the final absorbing state (i.e., a row in trans_mat with all NAs).
clock"reset" for a clock-reset model, "forward" for a clock-forward model,
"mix" for a mixture of clock-reset and clock-forward models by state, and
"mixt" for a mixture of clock-reset and clock-forward models by transition. A clock-reset model
is a semi-Markov model in which transition rates depend on time since entering a state.
A clock-forward model is a Markov model in which transition rates depend on time
since entering the initial state. If "mix" is used, then
reset_states must be specified. If "mixt" is used, then transition_types must
be specified.
reset_statesA vector denoting the states in which time resets.
Hazard functions are always a function of elapsed time since either the
start of the model or from when time was previously reset. Only used if
clock = "mix".
transition_typesA vector denoting the type of transition.
The vector is of the same length as the number of transitions
and takes values "reset", "time" or "age" for hazards that are functions of
reset time, time since study entry or age, respectively. Only used if
clock = "mixt".
new()
Create a new IndivCtstmTrans object.
IndivCtstmTrans$new(
params,
input_data,
trans_mat,
start_state = 1,
start_age = 38,
death_state = NULL,
clock = c("reset", "forward", "mix", "mixt"),
reset_states = NULL,
transition_types = NULL
)paramsThe params field.
input_dataThe input_data field.
trans_matThe trans_mat field.
start_stateThe start_state field.
start_ageThe start_age field.
death_stateThe death_state field.
clockThe clock field.
reset_statesThe reset_states field.
transition_typesThe transition_types field.
A new IndivCtstmTrans object.
sim_disease()
Simulate disease progression (i.e., individual trajectories through a multi-state model using an individual patient simulation).
IndivCtstmTrans$sim_disease(max_t = 100, max_age = 100, progress = NULL)
max_tA scalar or vector denoting the length of time to simulate the model. If a vector, must be equal to the number of simulated patients.
max_ageA scalar or vector denoting the maximum age to simulate each patient until. If a vector, must be equal to the number of simulated patients.
progressAn integer, specifying the PSA iteration (i.e., sample) that should be printed every progress PSA iterations. For example, if progress = 2, then every second PSA iteration is printed. Default is NULL, in which case no output is printed.
An object of class disprog.
sim_stateprobs()
Simulate health state probabilities from a disprog object.
IndivCtstmTrans$sim_stateprobs(t, disprog = NULL, ...)
tA numeric vector of times.
disprogA disprog object. If
NULL, then this will be simulated prior to computing state probabilities
using IndivCtstm$sim_disease().
...Additional arguments to pass to IndivCtstm$sim_disease() if
disprog = NULL.
An object of class stateprobs.
check()
Input validation for class. Checks that fields are the correct type.
IndivCtstmTrans$check()
clone()
The objects of this class are cloneable with this method.
IndivCtstmTrans$clone(deep = FALSE)
deepWhether to make a deep clone.
IndivCtstmTrans objects are conveniently created from either
fitted models or parameter objects with create_IndivCtstmTrans().
A complete economic model can be implemented with the IndivCtstm class.
library("flexsurv") # Simulation data strategies <- data.frame(strategy_id = c(1, 2, 3)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 50, 60), female = c(0, 0, 1)) # Multi-state model with transition specific models tmat <- rbind(c(NA, 1, 2), c(NA, NA, 3), c(NA, NA, NA)) fits <- vector(length = max(tmat, na.rm = TRUE), mode = "list") for (i in 1:length(fits)){ fits[[i]] <- flexsurvreg(Surv(years, status) ~ 1, data = bosms3[bosms3$trans == i, ], dist = "exp") } fits <- flexsurvreg_list(fits) # Simulation model hesim_dat <- hesim_data(strategies = strategies, patients = patients) fits_data <- expand(hesim_dat) transmod <- create_IndivCtstmTrans(fits, input_data = fits_data, trans_mat = tmat, n = 2) head(transmod$hazard(c(1, 2, 3))) head(transmod$cumhazard(c(1, 2, 3))) ## Simulate disease progression and state probabilities together transmod$sim_stateprobs(t = c(0, 5, 10))[t == 5] ## Simulate disease progression and state probabilities separately disprog <- transmod$sim_disease(max_t = 10) transmod$sim_stateprobs(t = c(0, 5, 10), disprog = disprog)[t == 5]library("flexsurv") # Simulation data strategies <- data.frame(strategy_id = c(1, 2, 3)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 50, 60), female = c(0, 0, 1)) # Multi-state model with transition specific models tmat <- rbind(c(NA, 1, 2), c(NA, NA, 3), c(NA, NA, NA)) fits <- vector(length = max(tmat, na.rm = TRUE), mode = "list") for (i in 1:length(fits)){ fits[[i]] <- flexsurvreg(Surv(years, status) ~ 1, data = bosms3[bosms3$trans == i, ], dist = "exp") } fits <- flexsurvreg_list(fits) # Simulation model hesim_dat <- hesim_data(strategies = strategies, patients = patients) fits_data <- expand(hesim_dat) transmod <- create_IndivCtstmTrans(fits, input_data = fits_data, trans_mat = tmat, n = 2) head(transmod$hazard(c(1, 2, 3))) head(transmod$cumhazard(c(1, 2, 3))) ## Simulate disease progression and state probabilities together transmod$sim_stateprobs(t = c(0, 5, 10))[t == 5] ## Simulate disease progression and state probabilities separately disprog <- transmod$sim_disease(max_t = 10) transmod$sim_stateprobs(t = c(0, 5, 10), disprog = disprog)[t == 5]
An object of class input_mats contains input matrices
for simulating a statistical model. Consists of (i) input matrices, X, and
(ii) metadata used to index each matrix in X.
Once created, an input_mats object can be converted
to a data.table::data.table with as.data.table(), which is a helpful way to check that
the object is as expected. The print() method summarizes the object and
prints it to the console.
More details are provided under "Details" below.
input_mats(X, ...) ## S3 method for class 'input_mats' as.data.table(x, ...) ## S3 method for class 'input_mats' print(x, ...)input_mats(X, ...) ## S3 method for class 'input_mats' as.data.table(x, ...) ## S3 method for class 'input_mats' print(x, ...)
X |
A list of input matrices for predicting the values of each parameter
in a statistical model. May also be a list of lists of input matrices when a
list of separate models is fit (e.g., with |
... |
For |
x |
An |
input_mats objects are used with params objects to simulate
disease models, cost models, and/or utility models. Each column of $X contains
variables from the params object and a given row corresponds to a combination
of the ID variables. An input matrix must always have rows for the treatment
strategies (strategy_id) and patients (patient_id); it may optionally
have rows for health variables (state_id or transition_id) and time
intervals (time_id). The rows must be sorted by prioritizing (i) strategy_id,
(ii) patient_id, (iii) the health related ID variable
(either state_id or transition_id) and (iv) time_id.
While input_mats objects can be created directly with input_mats(), it
is rarely a good idea to do so. They are typically created as the
input_data field when creating model objects (e.g., with
create_IndivCtstmTrans(), create_CohortDtstmTrans(), and
create_PsmCurves()). Internally, these functions
create the input matrices using create_input_mats() methods, which ensure
that they are in the correct format. Users may also use create_input_mats()
methods, but there is not usually a good reason to do so.
as.data.table.input_mats() will convert input matrices into a single
data.table() that column binds the ID variables and the unique combinations
of variables contained in the elements of $X. print.input_mats() prints
a call to as.data.table() and provides additional information about the
ID variables.
See IndivCtstmTrans() and PsmCurves() for examples in which the
input_data field of an instance of a model class is an input_mats object.
library("data.table") # Input matrices are typically created as part of model objects # Let's illustrate with a partitioned survival model (PSM) ## Model setup strategies <- data.frame(strategy_id = c(1, 2), new_strategy = c(0, 1)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 47, 60), female = c(1, 0, 0), group = factor(c("Good", "Medium", "Poor"))) hesim_dat <- hesim_data(strategies = strategies, patients = patients) ## Create survival models for PSM ### Parameters n <- 2 survmod_params <- params_surv_list( # Progression free survival (PFS) pfs = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(1/5), 1), new_strategy = rnorm(n, log(.8), 1)) ), dist = "exp" ), # Overall survival (OS) os = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(1/10), 1)) ), dist = "exp" ) ) ### Input data survmod_input_data <- expand(hesim_dat)[, intercept := 1] ### Model object survmod <- create_PsmCurves(survmod_params, input_data = survmod_input_data) ## Inspect input data survmod$input_data # Print "input_mats" object to console as.data.table(survmod$input_data) # Convert "input_mats" object to data.tablelibrary("data.table") # Input matrices are typically created as part of model objects # Let's illustrate with a partitioned survival model (PSM) ## Model setup strategies <- data.frame(strategy_id = c(1, 2), new_strategy = c(0, 1)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 47, 60), female = c(1, 0, 0), group = factor(c("Good", "Medium", "Poor"))) hesim_dat <- hesim_data(strategies = strategies, patients = patients) ## Create survival models for PSM ### Parameters n <- 2 survmod_params <- params_surv_list( # Progression free survival (PFS) pfs = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(1/5), 1), new_strategy = rnorm(n, log(.8), 1)) ), dist = "exp" ), # Overall survival (OS) os = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(1/10), 1)) ), dist = "exp" ) ) ### Input data survmod_input_data <- expand(hesim_dat)[, intercept := 1] ### Model object survmod <- create_PsmCurves(survmod_params, input_data = survmod_input_data) ## Inspect input data survmod$input_data # Print "input_mats" object to console as.data.table(survmod$input_data) # Convert "input_mats" object to data.table
Compute the parameters shape1 and shape2 of the beta distribution
using method of moments given the mean and standard
deviation of the random variable of interest.
mom_beta(mean, sd)mom_beta(mean, sd)
mean |
Mean of the random variable. |
sd |
Standard deviation of the random variable. |
If is the mean and
is the standard deviation of the random variable, then the method
of moments estimates of the parameters shape1 = and
shape2 = are:
and
A list containing the parameters shape1 and shape2.
mom_beta(mean = .8, sd = .1) # The function is vectorized. mom_beta(mean = c(.6, .8), sd = c(.08, .1))mom_beta(mean = .8, sd = .1) # The function is vectorized. mom_beta(mean = c(.6, .8), sd = c(.08, .1))
Compute the shape and scale (or rate) parameters of the gamma distribution using method of moments for the random variable of interest.
mom_gamma(mean, sd, scale = TRUE)mom_gamma(mean, sd, scale = TRUE)
mean |
Mean of the random variable. |
sd |
Standard deviation of the random variable. |
scale |
Logical. If TRUE (default), then the scale parameter is returned; otherwise, the rate parameter is returned. |
If is the mean and
is the standard deviation of the random variable, then the method
of moments estimates of the parameters shape = and
scale = are:
and
The inverse of the scale parameter, , is the rate parameter.
If scale = TRUE, then a list containing the parameters shape and scale; otherwise,
if scale = FALSE, then a list containing the parameters shape and rate.
mom_gamma(mean = 10000, sd = 2000) # The function is vectorized. mom_gamma(mean = c(8000, 10000), sd = c(1500, 2000))mom_gamma(mean = 10000, sd = 2000) # The function is vectorized. mom_gamma(mean = c(8000, 10000), sd = c(1500, 2000))
Example multi-state data for parameterizing a continuous time state transition model. Costs and utility are also included to facilitate cost-effectiveness analysis.
mstate3_exdatamstate3_exdata
A list containing the following elements:
A data frame containing the times at which patient transitions between health states based on the prothr dataset from the mstate package.
A list of data frames. The first data frame contains summary medical cost estimates and the second data frame contains drug cost data.
A data frame of summary utility estimates.
The data frame has the following columns:
Treatment strategy identification number.
Patient identification number.
Patient age (in years).
1 if a patient is female; 0 if male.
Starting state.
Receiving state.
Transition number.
Starting time.
Transition time.
Elapsed years between Tstart and Tstop.
Status variable; 1=transition, 0=censored.
The cost list contains two data frames. The first data frame contains data on the drug costs associated with each treatment strategy.
The treatment strategy identification number.
Annualized drug costs.
The second data frame contains summary data on medical costs by health state, and contains the following columns:
The health state identification number.
Mean costs.
Standard error of medical costs.
The data frame has the following columns:
The health state identification number.
Mean utility
Standard error of utility
multinom objectsCombine multinom objects into a list.
multinom_list(...)multinom_list(...)
... |
Objects of class |
An object of class multinom_list.
library("nnet") library("data.table") trans_data <- data.table(multinom3_exdata$transitions) dat_healthy <- trans_data[state_from == "Healthy"] fit_healthy <- multinom(state_to ~ strategy_name + female + age_cat + year_cat, data = dat_healthy) dat_sick <- trans_data[state_from == "Sick"] dat_sick$state_to <- droplevels(dat_sick$state_to) fit_sick <- multinom(state_to ~ strategy_name + female + age_cat + year_cat, data = dat_sick) fits <- multinom_list(healthy = fit_healthy, sick = fit_sick) class(fits)library("nnet") library("data.table") trans_data <- data.table(multinom3_exdata$transitions) dat_healthy <- trans_data[state_from == "Healthy"] fit_healthy <- multinom(state_to ~ strategy_name + female + age_cat + year_cat, data = dat_healthy) dat_sick <- trans_data[state_from == "Sick"] dat_sick$state_to <- droplevels(dat_sick$state_to) fit_sick <- multinom(state_to ~ strategy_name + female + age_cat + year_cat, data = dat_sick) fits <- multinom_list(healthy = fit_healthy, sick = fit_sick) class(fits)
Example discrete time health state transitions data simulated using multinomial logistic regression. Costs and utility are also included to facilitate cost-effectiveness analysis.
multinom3_exdatamultinom3_exdata
A list containing the following elements:
A data frame containing patient transitions between health states at discrete time intervals (i.e., on a yearly basis).
A list of data frames. The first data frame contains drug cost data and the second contains summary medical cost estimates.
A data frame of summary utility estimates.
The data frame has the following columns:
Patient identification number.
Treatment strategy identification number.
Treatment strategy name.
Patient age (in years).
A factor variable with 3 age groups: (i) age less than 40, (ii) age at least 40 and less than 60, and (iii) age at least 60.
1 if a patient is female; 0 if male.
The year since the start of data collection with the first year equal to 1.
State making a transition from.
State making a transition to.
Factor variable for year with 3 categories: (i) year 3 and below, (ii) year between 3 and 6, and (iii) year 7 and above.
The cost list contains two data frames. The first data frame contains data on the drug costs associated with each treatment strategy.
The treatment strategy identification number.
The treatment strategy name.
Annualized drug costs.
The second data frame contains summary data on medical costs by health state, and contains the following columns:
The health state identification number.
The name of the health state.
Mean medical costs.
Standard error of medical costs.
The data frame has the following columns:
The health state identification number.
The name of the health state.
Mean utility
Standard error of utility.
Simulated 3-state dataset in oncology with three health states (Stable, Progression, and Death) and three possible transitions (Stable -> Progression, Stable -> Death, and Progression -> Death).
onc3onc3
A data.table with the following columns:
Health state making a transition from.
Health state making a transition to.
Standard of care (SOC), new treatment 1 (New 1), or new treatment 2 (New 2).
1 if a patient is female; 0 if male.
Patient age (in years).
Patient identification number.
Starting time.
Stopping time.
Status indicator: 1=transition, 0=censored.
Integer denoting transition: 1 = Stable -> Progression, 2 = Stable -> Death, 3 = Progression -> Death.
Strategy identification number.
Elapsed years between time_start and time_stop.
head(onc3)head(onc3)
The same dataset as onc3 converted into a panel data format in which health states are recorded at a finite series of times.
onc3ponc3p
A data.table with the following columns:
The name of the health state (Stable, Progression, and Death).
Standard of care (SOC), new treatment 1 (New 1), or new treatment 2 (New 2).
1 if a patient is female; 0 if male.
Patient age (in years).
Patient identification number.
Time that state was recorded.
Strategy identification number.
The health state identification number.
head(onc3p)head(onc3p)
Objects prefixed by "params_" are lists containing the parameters of a statistical model used for simulation modeling. The parameters are used to simulate outcomes as a function of covariates contained in input matrices (input_mats).
Create a list containing the parameters of a fitted linear regression model.
params_lm(coefs, sigma = 1)params_lm(coefs, sigma = 1)
coefs |
Samples of the coefficients under sampling uncertainty.
Must be a matrix or any object coercible to a matrix such as |
sigma |
A vector of samples of the standard error of the regression model. Default value is 1 for all samples. Only used if the model is used to randomly simulate values (rather than to predict means). |
Fitted linear models are used to predict values, ,
as a function of covariates, ,
Predicted means are given by where
is the vector of estimated regression coefficients. Random samples are obtained by
sampling the error term from a normal distribution,
.
An object of class params_lm, which is a list containing coefs,
sigma, and n_samples. n_samples is equal to the
number of rows in coefs. The coefs element is always converted into a
matrix.
This parameter object is useful for modeling health state values
when values can vary across patients and/or health states as a function of
covariates. In many cases it will, however, be simpler, and more flexible to
use a stateval_tbl. For an example use case see the documentation for
create_StateVals.lm().
library("MASS") n <- 2 params <- params_lm( coefs = mvrnorm(n, mu = c(.5,.6), Sigma = matrix(c(.05, .01, .01, .05), nrow = 2)), sigma <- rgamma(n, shape = .5, rate = 4) ) summary(params) paramslibrary("MASS") n <- 2 params <- params_lm( coefs = mvrnorm(n, mu = c(.5,.6), Sigma = matrix(c(.05, .01, .01, .05), nrow = 2)), sigma <- rgamma(n, shape = .5, rate = 4) ) summary(params) params
Store the parameters of a fitted multinomial logistic
regression model. The model is used to predict probabilities of
classes, which represent the probability of transitioning to particular health
state in a discrete time state transition model. Can be used as an element of a
params_mlogit_list to parameterize a CohortDtstmTrans object.
params_mlogit(coefs)params_mlogit(coefs)
coefs |
A 3D array of stacked matrices containing samples of the regression
coefficients under sampling uncertainty. May also be a
list of objects (e.g., data frames) that can be coerced into matrices with
|
Multinomial logit models are used to predict the probability of
membership for subject in each of classes as a function of covariates:
An object of class params_mlogit, which is a list containing coefs
and n_samples, where n_samples is equal to the number of rows in each
element of coefs. The coefs element is always converted into
a 3D array of stacked matrices.
summary.params_mlogit(), params_mlogit_list(), CohortDtstmTrans
# Consider a sick-sicker model and model transitions from the sick state ## We can instantiate from a list of data frames params <- params_mlogit( coefs = list( ### Transition from sick to sicker sicker = data.frame( intercept = c(-0.33, -.2, -.15), treat = c(log(.75), log(.8), log(.9)) ), ### Transition from sick to death death = data.frame( intercept = c(-1, -1.2, -.5), treat = c(log(.6), log(.65), log(.55)) ) ) ) summary(params) params ## We can also instantiate from an array coefs_sicker <- data.frame( intercept = c(-0.33, -.2, -.15), treat = c(log(.75), log(.8), log(.9)) ) coefs_death <- data.frame( intercept = c(-1, -1.2, -.5), treat = c(log(.6), log(.65), log(.55)) ) params2 <- params_mlogit( coefs <- array( data = c(as.matrix(coefs_sicker), as.matrix(coefs_death)), dim = c(3, 2, 2), dimnames = list(NULL, c("intercept", "treat"), c("sicker", "death")) ) ) params2# Consider a sick-sicker model and model transitions from the sick state ## We can instantiate from a list of data frames params <- params_mlogit( coefs = list( ### Transition from sick to sicker sicker = data.frame( intercept = c(-0.33, -.2, -.15), treat = c(log(.75), log(.8), log(.9)) ), ### Transition from sick to death death = data.frame( intercept = c(-1, -1.2, -.5), treat = c(log(.6), log(.65), log(.55)) ) ) ) summary(params) params ## We can also instantiate from an array coefs_sicker <- data.frame( intercept = c(-0.33, -.2, -.15), treat = c(log(.75), log(.8), log(.9)) ) coefs_death <- data.frame( intercept = c(-1, -1.2, -.5), treat = c(log(.6), log(.65), log(.55)) ) params2 <- params_mlogit( coefs <- array( data = c(as.matrix(coefs_sicker), as.matrix(coefs_death)), dim = c(3, 2, 2), dimnames = list(NULL, c("intercept", "treat"), c("sicker", "death")) ) ) params2
Create a list containing the parameters of multiple fitted multinomial logit models.
Can be used to parameterize state transitions in a discrete time transition model
by passing to the params field of a CohortDtstmTrans object.
params_mlogit_list(...)params_mlogit_list(...)
... |
Objects of class |
An object of class params_mlogit_list, which is a list containing
params_mlogit objects.
summary.params_mlogit_list(), params_mlogit(), CohortDtstmTrans
# Consider a sick-sicker model params <- params_mlogit_list( ## Transitions from sick state (sick -> sicker, sick -> death) sick = params_mlogit( coefs = list( sicker = data.frame( intercept = c(-0.33, -.2), treat = c(log(.75), log(.8)) ), death = data.frame( intercept = c(-1, -1.2), treat = c(log(.6), log(.65)) ) ) ), ## Transitions from sicker state (sicker -> death) sicker = params_mlogit( coefs = list( death = data.frame( intercept = c(-1.5, -1.4), treat = c(log(.5), log(.55)) ) ) ) ) summary(params) params# Consider a sick-sicker model params <- params_mlogit_list( ## Transitions from sick state (sick -> sicker, sick -> death) sick = params_mlogit( coefs = list( sicker = data.frame( intercept = c(-0.33, -.2), treat = c(log(.75), log(.8)) ), death = data.frame( intercept = c(-1, -1.2), treat = c(log(.6), log(.65)) ) ) ), ## Transitions from sicker state (sicker -> death) sicker = params_mlogit( coefs = list( death = data.frame( intercept = c(-1.5, -1.4), treat = c(log(.5), log(.55)) ) ) ) ) summary(params) params
Create a list containing the parameters of a single fitted parametric or flexible parametric survival model.
params_surv(coefs, dist, aux = NULL)params_surv(coefs, dist, aux = NULL)
coefs |
A list of length equal to the number of parameters in the
survival distribution. Each element of the list is a matrix of samples
of the regression coefficients under sampling uncertainty used to predict
a given parameter. All parameters are expressed on the real line (e.g.,
after log transformation if they are defined as positive). Each element
of the list may also be an object coercible to a matrix such as a
|
dist |
Character vector denoting the parametric distribution. See "Details". |
aux |
Auxiliary arguments used with splines, fractional polynomial, or piecewise exponential models. See "Details". |
Survival is modeled as a function of parameters .
Letting be the cumulative distribution function, survival at time
is given by
The parameters are modeled as a function of covariates, , with an
inverse transformation function ,
is typically if a parameter is strictly positive
and the identity function if the parameter space is unrestricted.
The types of distributions that can be specified are:
exponential or exp
Exponential distribution. coef
must contain the rate parameter on the log scale and the same parameterization as in
stats::Exponential.
weibull or weibull.quiet
Weibull distribution. The first
element of coef is the shape parameter (on the log scale) and the second
element is the scale parameter (also on the log scale). The parameterization is
that same as in stats::Weibull.
weibullPH Weibull distribution with a proportional hazards
parameterization. The first element of coef is the shape parameter
(on the log scale) and the second element is the scale parameter
(also on the log scale). The parameterization is
that same as in flexsurv::WeibullPH.
gamma Gamma distribution. The first
element of coef is the shape parameter (on the log scale) and the second
element is the rate parameter (also on the log scale). The parameterization is
that same as in stats::GammaDist.
lnorm Lognormal distribution. The first
element of coef is the meanlog parameter (i.e., the mean of survival on
the log scale) and the second element is the sdlog parameter (i.e.,
the standard deviation of survival on the log scale). The parameterization is
that same as in stats::Lognormal. The coefficients predicting the meanlog
parameter are untransformed whereas the coefficients predicting the sdlog
parameter are defined on the log scale.
gompertz Gompertz distribution. The first
element of coef is the shape parameter and the second
element is the rate parameter (on the log scale). The parameterization is
that same as in flexsurv::Gompertz.
llogis Log-logistic distribution. The first
element of coef is the shape parameter (on the log scale) and the second
element is the scale parameter (also on the log scale). The parameterization is
that same as in flexsurv::Llogis.
gengamma Generalized gamma distribution. The first
element of coef is the location parameter mu, the second
element is the scale parameter sigma (on the log scale), and the
third element is the shape parameter Q. The parameterization is
that same as in flexsurv::GenGamma.
survspline Survival splines. Each element of coef is a parameter of the
spline model (i.e. gamma_0, gamma_1, ) with length equal
to the number of knots (including the boundary knots). See below for details on the
auxiliary arguments. The parameterization is that same as in flexsurv::Survspline.
fracpoly Fractional polynomials. Each element of coef is a parameter of the
fractional polynomial model (i.e. gamma_0, gamma_1, ) with length equal
to the number of powers plus 1. See below for details on the auxiliary arguments
(i.e., powers).
pwexp Piecewise exponential distribution. Each element of coef is
rate parameter for a distinct time interval. The times at which the rates
change should be specified with the auxiliary argument time (see below
for more details)
.
fixed A fixed survival time. Can be used for "non-random" number
generation. coef should contain a single parameter, est, of the fixed
survival times.
Auxiliary arguments for spline models should be specified as a list containing the elements:
knotsA numeric vector of knots.
scaleThe survival outcome to be modeled
as a spline function. Options are "log_cumhazard" for the log cumulative hazard;
"log_hazard" for the log hazard rate; "log_cumodds" for the log cumulative odds;
and "inv_normal" for the inverse normal distribution function.
timescaleIf "log" (the default), then survival is modeled as a spline function
of log time; if "identity", then it is modeled as a spline function of time.
Auxiliary arguments for fractional polynomial models should be specified as a list containing the elements:
powersA vector of the powers of the fractional polynomial with each element chosen from the following set: -2. -1, -0.5, 0, 0.5, 1, 2, 3.
Auxiliary arguments for piecewise exponential models should be specified as a list containing the element:
timeA vector equal to the number of rate parameters giving the times at which the rate changes.
Furthermore, when splines (with scale = "log_hazard") or fractional
polynomials are used, numerical methods must be used to compute the cumulative
hazard and for random number generation. The following additional auxiliary arguments
can therefore be specified:
cumhaz_methodNumerical method used to compute cumulative hazard
(i.e., to integrate the hazard function). Always used for fractional polynomials
but only used for splines if scale = "log_hazard".
Options are "quad" for adaptive quadrature and "riemann" for Riemann sum.
random_methodMethod used to randomly draw from
an arbitrary survival function. Options are "invcdf" for the inverse CDF and
"discrete" for a discrete time approximation that randomly samples
events from a Bernoulli distribution at discrete times.
stepStep size for computation of cumulative hazard with
numerical integration. Only required when using "riemann" to compute the
cumulative hazard or using "discrete" for random number generation.
An object of class params_surv, which is a list containing coefs,
dist, and n_samples. n_samples is equal to the
number of rows in each element of coefs, which must be the same. The coefs
element is always converted into a list of matrices. The list may also contain
aux if a spline, fractional polynomial, or piecewise exponential model is
used.
n <- 10 params <- params_surv( coefs = list( shape = data.frame( intercept = rnorm(n, .5, .23) ), scale = data.frame( intercept = rnorm(n, 12.39, 1.49), age = rnorm(n, -.09, .023) ) ), dist = "weibull" ) summary(params) paramsn <- 10 params <- params_surv( coefs = list( shape = data.frame( intercept = rnorm(n, .5, .23) ), scale = data.frame( intercept = rnorm(n, 12.39, 1.49), age = rnorm(n, -.09, .023) ) ), dist = "weibull" ) summary(params) params
Create a list containing the parameters of multiple fitted parametric survival models.
params_surv_list(...)params_surv_list(...)
... |
Objects of class |
An object of class params_surv_list, which is a list containing params_surv
objects.
n <- 5 params <- params_surv_list( # Model for progression free survival pfs = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(.5), .5), new_strategy = rnorm(n, log(.8), .1)) ), dist = "exp" ), # Model for overall survival os = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(.3) , .5)) ), dist = "exp" ) ) summary(params) paramsn <- 5 params <- params_surv_list( # Model for progression free survival pfs = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(.5), .5), new_strategy = rnorm(n, log(.8), .1)) ), dist = "exp" ), # Model for overall survival os = params_surv( coefs = list( rate = data.frame(intercept = rnorm(n, log(.3) , .5)) ), dist = "exp" ) ) summary(params) params
Plot a cost-effectiveness curve from either the output of cea() or
cea_pw() using ggplot2::ggplot. The former compares all treatment strategies
simultaneously and uses the probabilistic sensitivity analysis (PSA) to compute
the probability that each strategy is the most cost-effective at a given
willingness to pay value, while the latter uses the PSA to compute the probability
that each treatment is cost-effective relative to a comparator.
plot_ceac(x, ...) ## S3 method for class 'cea_pw' plot_ceac(x, labels = NULL, ...) ## S3 method for class 'cea' plot_ceac(x, labels = NULL, ...)plot_ceac(x, ...) ## S3 method for class 'cea_pw' plot_ceac(x, labels = NULL, ...) ## S3 method for class 'cea' plot_ceac(x, labels = NULL, ...)
x |
An object of the appropriate class. |
... |
Further arguments passed to and from methods. Currently unused. |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
See the cea() documentation for an example. If there are multiple subgroups,
then a faceted plot is produced with one plot for each subgroup.
Plot a cost-effectiveness acceptability frontier (CEAF) from the output of
cea using ggplot2::ggplot. The CEAF plots the probability
that the optimal treatment strategy (i.e., the strategy with the highest
expected net monetary benefit) is cost-effective.
plot_ceaf(x, labels = NULL)plot_ceaf(x, labels = NULL)
x |
A |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
See the cea() documentation for an example. If there are multiple subgroups,
then a faceted plot is produced with one plot for each subgroup.
A ggplot object.
Plot a cost-effectiveness plane from the output of cea_pw() using ggplot2::ggplot.
Each point is a random draw of incremental costs (y-axis) and incremental QALYs (x-axis)
from a probabilistic sensitivity analysis.
plot_ceplane(x, k = 50000, labels = NULL)plot_ceplane(x, k = 50000, labels = NULL)
x |
A |
k |
Willingness to pay per QALY. |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
See the cea_pw() documentation for an example. If there are multiple subgroups,
then a faceted plot is produced with one plot for each subgroup.
A ggplot object.
Plot the expected value of perfect information (EVPI) from the output of
cea() using ggplot2::ggplot. Intuitively, the EVPI provides an estimate of the
amount that a decision maker would be willing to pay to collect additional data
and completely eliminate uncertainty.
plot_evpi(x, labels = NULL)plot_evpi(x, labels = NULL)
x |
A |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
See the cea() documentation for an example. If there are multiple subgroups,
then a faceted plot is produced with one plot for each subgroup.
A ggplot object.
Simulate outcomes from an N-state partitioned survival model.
An R6::R6Class object.
survival_modelsThe survival models used to predict survival curves. Must be
an object of class PsmCurves.
utility_modelThe model for health state utility. Must be an object of
class StateVals.
cost_modelsThe models used to predict costs by health state.
Must be a list of objects of class StateVals, where each element of the
list represents a different cost category.
n_statesNumber of states in the partitioned survival model.
t_A numeric vector of times at which survival curves were predicted. Determined
by the argument t in $sim_curves().
survival_An object of class survival simulated using sim_survival().
stateprobs_An object of class stateprobs simulated using $sim_stateprobs().
qalys_An object of class qalys simulated using $sim_qalys().
costs_An object of class costs simulated using $sim_costs().
new()
Create a new Psm object.
Psm$new(survival_models = NULL, utility_model = NULL, cost_models = NULL)
survival_modelsThe survival_models field.
utility_modelThe utility_model field.
cost_modelsThe cost_models field.
n_states is set equal to the number of survival models plus one.
A new Psm object.
sim_survival()
Simulate survival curves as a function of time using PsmCurves$survival().
Psm$sim_survival(t)
tA numeric vector of times. The first element must be 0.
An instance of self with simulated output from PsmCurves$survival()
stored in survival_.
sim_stateprobs()
Simulate health state probabilities from survival_ using a partitioned
survival analysis.
Psm$sim_stateprobs()
An instance of self with simulated output of class stateprobs
stored in stateprobs_.
sim_qalys()
Simulate quality-adjusted life-years (QALYs) as a function of stateprobs_ and
utility_model. See sim_qalys() for details.
Psm$sim_qalys(
dr = 0.03,
integrate_method = c("trapz", "riemann_left", "riemann_right"),
lys = TRUE
)drDiscount rate.
integrate_methodMethod used to integrate state values when computing
costs or QALYs. Options are trapz for the trapezoid rule,
riemann_left for a left Riemann sum, and
riemann_right for a right Riemann sum.
lysIf TRUE, then life-years are simulated in addition to QALYs.
An instance of self with simulated output of class qalys stored
in qalys_.
sim_costs()
Simulate costs as a function of stateprobs_ and cost_models.
See sim_costs() for details.
Psm$sim_costs(
dr = 0.03,
integrate_method = c("trapz", "riemann_left", "riemann_right")
)drDiscount rate.
integrate_methodMethod used to integrate state values when computing
costs or QALYs. Options are trapz for the trapezoid rule,
riemann_left for a left Riemann sum, and
riemann_right for a right Riemann sum.
An instance of self with simulated output of class costs stored
in costs_.
summarize()
Summarize costs and QALYs so that cost-effectiveness analysis can be performed.
See summarize_ce().
Psm$summarize(by_grp = FALSE)
by_grpIf TRUE, then costs and QALYs are computed by subgroup. If
FALSE, then costs and QALYs are aggregated across all patients (and subgroups).
clone()
The objects of this class are cloneable with this method.
Psm$clone(deep = FALSE)
deepWhether to make a deep clone.
Incerti and Jansen (2021). See Section 2.3 for a mathematical description of a PSM and Section 4.2 for an example in oncology. The mathematical approach used to simulate costs and QALYs from state probabilities is described in Section 2.1.
The PsmCurves documentation
describes the class for the survival models and the StateVals documentation
describes the class for the cost and utility models. A PsmCurves
object is typically created using create_PsmCurves().
The PsmCurves documentation provides an example in which the model
is parameterized from parameter objects (i.e., without having the patient-level
data required to fit a model with R). A longer example is provided in
vignette("psm").
library("flexsurv") library("ggplot2") theme_set(theme_bw()) # Model setup strategies <- data.frame(strategy_id = c(1, 2, 3), strategy_name = paste0("Strategy ", 1:3)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 50, 60), female = c(0, 0, 1)) states <- data.frame(state_id = seq(1, 3), state_name = paste0("State ", seq(1, 3))) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) labs <- c( get_labels(hesim_dat), list(curve = c("Endpoint 1" = 1, "Endpoint 2" = 2, "Endpoint 3" = 3)) ) n_samples <- 2 # Survival models surv_est_data <- psm4_exdata$survival fit1 <- flexsurvreg(Surv(endpoint1_time, endpoint1_status) ~ factor(strategy_id), data = surv_est_data, dist = "exp") fit2 <- flexsurvreg(Surv(endpoint2_time, endpoint2_status) ~ factor(strategy_id), data = surv_est_data, dist = "exp") fit3 <- flexsurvreg(Surv(endpoint3_time, endpoint3_status) ~ factor(strategy_id), data = surv_est_data, dist = "exp") fits <- flexsurvreg_list(fit1, fit2, fit3) surv_input_data <- expand(hesim_dat, by = c("strategies", "patients")) psm_curves <- create_PsmCurves(fits, input_data = surv_input_data, uncertainty = "bootstrap", est_data = surv_est_data, n = n_samples) # Cost model(s) cost_input_data <- expand(hesim_dat, by = c("strategies", "patients", "states")) fit_costs_medical <- lm(costs ~ female + state_name, data = psm4_exdata$costs$medical) psm_costs_medical <- create_StateVals(fit_costs_medical, input_data = cost_input_data, n = n_samples) # Utility model utility_tbl <- stateval_tbl(tbl = data.frame(state_id = states$state_id, min = psm4_exdata$utility$lower, max = psm4_exdata$utility$upper), dist = "unif") psm_utility <- create_StateVals(utility_tbl, n = n_samples, hesim_data = hesim_dat) # Partitioned survival decision model psm <- Psm$new(survival_models = psm_curves, utility_model = psm_utility, cost_models = list(medical = psm_costs_medical)) psm$sim_survival(t = seq(0, 5, 1/12)) autoplot(psm$survival_, labels = labs, ci = FALSE, ci_style = "ribbon") psm$sim_stateprobs() autoplot(psm$stateprobs_, labels = labs) psm$sim_costs(dr = .03) head(psm$costs_) head(psm$sim_qalys(dr = .03)$qalys_)library("flexsurv") library("ggplot2") theme_set(theme_bw()) # Model setup strategies <- data.frame(strategy_id = c(1, 2, 3), strategy_name = paste0("Strategy ", 1:3)) patients <- data.frame(patient_id = seq(1, 3), age = c(45, 50, 60), female = c(0, 0, 1)) states <- data.frame(state_id = seq(1, 3), state_name = paste0("State ", seq(1, 3))) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) labs <- c( get_labels(hesim_dat), list(curve = c("Endpoint 1" = 1, "Endpoint 2" = 2, "Endpoint 3" = 3)) ) n_samples <- 2 # Survival models surv_est_data <- psm4_exdata$survival fit1 <- flexsurvreg(Surv(endpoint1_time, endpoint1_status) ~ factor(strategy_id), data = surv_est_data, dist = "exp") fit2 <- flexsurvreg(Surv(endpoint2_time, endpoint2_status) ~ factor(strategy_id), data = surv_est_data, dist = "exp") fit3 <- flexsurvreg(Surv(endpoint3_time, endpoint3_status) ~ factor(strategy_id), data = surv_est_data, dist = "exp") fits <- flexsurvreg_list(fit1, fit2, fit3) surv_input_data <- expand(hesim_dat, by = c("strategies", "patients")) psm_curves <- create_PsmCurves(fits, input_data = surv_input_data, uncertainty = "bootstrap", est_data = surv_est_data, n = n_samples) # Cost model(s) cost_input_data <- expand(hesim_dat, by = c("strategies", "patients", "states")) fit_costs_medical <- lm(costs ~ female + state_name, data = psm4_exdata$costs$medical) psm_costs_medical <- create_StateVals(fit_costs_medical, input_data = cost_input_data, n = n_samples) # Utility model utility_tbl <- stateval_tbl(tbl = data.frame(state_id = states$state_id, min = psm4_exdata$utility$lower, max = psm4_exdata$utility$upper), dist = "unif") psm_utility <- create_StateVals(utility_tbl, n = n_samples, hesim_data = hesim_dat) # Partitioned survival decision model psm <- Psm$new(survival_models = psm_curves, utility_model = psm_utility, cost_models = list(medical = psm_costs_medical)) psm$sim_survival(t = seq(0, 5, 1/12)) autoplot(psm$survival_, labels = labs, ci = FALSE, ci_style = "ribbon") psm$sim_stateprobs() autoplot(psm$stateprobs_, labels = labs) psm$sim_costs(dr = .03) head(psm$costs_) head(psm$sim_qalys(dr = .03)$qalys_)
A collection of example datasets containing simulated survival, costs, and utility data for a 4-state partitioned survival model.
psm4_exdatapsm4_exdata
A list containing the following elements:
A data frame containing patient information and time to 3 separate survival endpoints.
A list of data frames. The first data frame contains medical cost data and the second data frame contains drug cost data.
The survival data frame contains a list of 3 survival curves, each containing the following columns.
An indicator variable equal to 1 if the patient is female and 0 otherwise.
The age of the patient in years.
The id of the treatment strategy used.
Follow up time with right censored data to survival endpoint 1.
A status indicator for survival endpoint 1 equal to 0 if alive and 1 if dead.
Follow up time with right censored data to survival endpoint 2.
A status indicator for survival endpoint 2 equal to 0 if alive and 1 if dead.
Follow up time with right censored data to survival endpoint 3.
A status indicator for survival endpoint 3 equal to 0 if alive and 1 if dead.
The cost list contains two data frames.The first data frame contains data on the medical costs by patient and health state, and contains the following columns:
An integer denoting the id of the patient.
An indicator variable equal to 1 if the patient is female and 0 otherwise.
A categorical variable denoting the three possible health states.
Annualized medical costs.
The second data frame contains data on the drug costs associated with each treatment strategy.
The id of each treatment strategy.
Annualized drug costs.
Summarize N-1 survival curves for an N-state partitioned survival model.
An R6::R6Class object.
paramsAn object of class params_surv_list.
input_dataAn object of class input_mats. Each row in X must
be a unique treatment strategy and patient.
new()
Create a new PsmCurves object.
PsmCurves$new(params, input_data)
paramsThe params field.
input_dataThe input_data field.
A new PsmCurves object.
hazard()
Predict the hazard function for each survival curve as a function of time.
PsmCurves$hazard(t)
tA numeric vector of times.
A data.table with columns sample, strategy_id,
patient_id, grp_id, curve (the curve number), t, and hazard.
cumhazard()
Predict the cumulative hazard function for each survival curve as a function of time.
PsmCurves$cumhazard(t)
tA numeric vector of times.
A data.table with columns sample, strategy_id,
patient_id, grp_id, curve, t, and cumhazard.
survival()
Predict survival probabilities for each survival curve as a function of time.
PsmCurves$survival(t)
tA numeric vector of times.
An object of class survival.
rmst()
Predict the restricted mean survival time up until time points t
for each survival curve.
PsmCurves$rmst(t, dr = 0)
tA numeric vector of times.
drDiscount rate.
A data.table with columns sample, strategy_id,
patient_id, grp_id, curve, t, and rmst.
quantile()
Predict quantiles of the survival distribution for each survival curve.
PsmCurves$quantile(p)
pA numeric vector of probabilities for computing quantiles.
A data.table with columns sample, strategy_id,
patient_id, grp_id, curve, p and quantile.
check()
Input validation for class. Checks that fields are the correct type.
PsmCurves$check()
clone()
The objects of this class are cloneable with this method.
PsmCurves$clone(deep = FALSE)
deepWhether to make a deep clone.
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").
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 # (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))) head(psm_curves2$quantile(p = c(.25, .5, .75))) ### Survival curves head(psm_curves1$survival(t = times)) head(psm_curves2$survival(t = times)) ### Restricted mean survival head(psm_curves1$rmst(t = c(2, 5))) head(psm_curves2$rmst(t = c(2, 5)))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 # (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))) head(psm_curves2$quantile(p = c(.25, .5, .75))) ### Survival curves head(psm_curves1$survival(t = times)) head(psm_curves2$survival(t = times)) ### Restricted mean survival head(psm_curves1$rmst(t = c(2, 5))) head(psm_curves2$rmst(t = c(2, 5)))
An object of class qalys returned from methods
$sim_qalys() in model classes that store simulated
quality-adjusted life-years (QALYs).
A qalys object inherits from data.table and contains
the following columns:
A random sample from the PSA.
The treatment strategy ID.
The patient ID.
The subgroup ID.
The health state ID.
The rate used to discount QALYs.
A single category always equal to "qalys".
The simulated values of QALYs.
If the argument lys = TRUE, then the data.table also contains a column
lys containing simulated life-years.
Creates transition intensity matrices where elements represent the instantaneous risk of moving between health states.
## S3 method for class 'matrix' qmatrix(x, trans_mat, ...) ## S3 method for class 'data.table' qmatrix(x, trans_mat, ...) ## S3 method for class 'data.frame' qmatrix(x, trans_mat, ...)## S3 method for class 'matrix' qmatrix(x, trans_mat, ...) ## S3 method for class 'data.table' qmatrix(x, trans_mat, ...) ## S3 method for class 'data.frame' qmatrix(x, trans_mat, ...)
x |
A two-dimensional tabular object containing
elements of the transition intensity matrix. A column represents a transition
from state |
trans_mat |
Just as in |
... |
Further arguments passed to or from other methods. Currently unused. |
The object x must only contain non-zero and non-diagonal elements
of a transition intensity matrix. The diagonal elements are automatically computed
as the negative sum of the other rows.
An array of transition intensity matrices with the third dimension
equal to the number of rows in x.
# 3 state irreversible model tmat <- rbind(c(NA, 1, 2), c(NA, NA, 3), c(NA, NA, NA)) q12 <- c(.8, .7) q13 <- c(.2, .3) q23 <- c(1.1, 1.2) q <- data.frame(q12, q13, q23) qmat <- qmatrix(q, trans_mat = tmat) print(qmat) # Matrix exponential of each matrix in array expmat(qmat)# 3 state irreversible model tmat <- rbind(c(NA, 1, 2), c(NA, NA, 3), c(NA, NA, NA)) q12 <- c(.8, .7) q13 <- c(.2, .3) q23 <- c(1.1, 1.2) q <- data.frame(q12, q13, q23) qmat <- qmatrix(q, trans_mat = tmat) print(qmat) # Matrix exponential of each matrix in array expmat(qmat)
msm objectDraw transition intensity matrices for a probabilistic sensitivity analysis
from a fitted msm object.
## S3 method for class 'msm' qmatrix(x, newdata = NULL, uncertainty = c("normal", "none"), n = 1000, ...)## S3 method for class 'msm' qmatrix(x, newdata = NULL, uncertainty = c("normal", "none"), n = 1000, ...)
x |
A |
newdata |
A data frame to look for variables with which to predict. A
separate transition intensity matrix is predicted based on each row in
|
uncertainty |
Method used to draw transition intensity matrices. If |
n |
Number of random observations of the parameters to draw. |
... |
Further arguments passed to or from other methods. Currently unused. |
An array of transition intensity matrices with the third dimension
equal to the number of rows in newdata.
qmatrix.matrix()
library("msm") set.seed(101) qinit <- rbind( c(0, 0.28163, 0.01239), c(0, 0, 0.10204), c(0, 0, 0) ) fit <- msm(state_id ~ time, subject = patient_id, data = onc3p[patient_id %in% sample(patient_id, 100)], covariates = list("1-2" =~ age + strategy_name), qmatrix = qinit) qmatrix(fit, newdata = data.frame(age = 55, strategy_name = "New 1"), uncertainty = "none") qmatrix(fit, newdata = data.frame(age = 55, strategy_name = "New 1"), uncertainty = "normal", n = 3)library("msm") set.seed(101) qinit <- rbind( c(0, 0.28163, 0.01239), c(0, 0, 0.10204), c(0, 0, 0) ) fit <- msm(state_id ~ time, subject = patient_id, data = onc3p[patient_id %in% sample(patient_id, 100)], covariates = list("1-2" =~ age + strategy_name), qmatrix = qinit) qmatrix(fit, newdata = data.frame(age = 55, strategy_name = "New 1"), uncertainty = "none") qmatrix(fit, newdata = data.frame(age = 55, strategy_name = "New 1"), uncertainty = "normal", n = 3)
Draw random samples from a categorical distribution given a matrix of probabilities.
rcat is vectorized and written in C++ for speed.
rcat(n, prob)rcat(n, prob)
n |
Number of random observations to draw. |
prob |
A matrix of probabilities where rows correspond to observations and columns correspond to categories. |
A vector of random samples from the categorical distribution. The length of the sample is determined by n. The numerical arguments other than n are recycled so that the number of samples is equal to n.
p <- c(.2, .5, .3) n <- 10000 pmat <- matrix(rep(p, n), nrow = n, ncol = length(p), byrow = TRUE) # rcat set.seed(100) ptm <- proc.time() samp1 <- rcat(n, pmat) proc.time() - ptm prop.table(table(samp1)) # rmultinom from base R set.seed(100) ptm <- proc.time() samp2 <- t(apply(pmat, 1, rmultinom, n = 1, size = 1)) samp2 <- apply(samp2, 1, function(x) which(x == 1)) proc.time() - ptm prop.table(table(samp2))p <- c(.2, .5, .3) n <- 10000 pmat <- matrix(rep(p, n), nrow = n, ncol = length(p), byrow = TRUE) # rcat set.seed(100) ptm <- proc.time() samp1 <- rcat(n, pmat) proc.time() - ptm prop.table(table(samp1)) # rmultinom from base R set.seed(100) ptm <- proc.time() samp2 <- t(apply(pmat, 1, rmultinom, n = 1, size = 1)) samp2 <- apply(samp2, 1, function(x) which(x == 1)) proc.time() - ptm prop.table(table(samp2))
Draw random samples from multiple Dirichlet distributions for use in transition probability matrices.
rdirichlet_mat( n, alpha, output = c("array", "matrix", "data.frame", "data.table") )rdirichlet_mat( n, alpha, output = c("array", "matrix", "data.frame", "data.table") )
n |
Number of samples to draw. |
alpha |
A matrix where each row is a separate vector of shape parameters. |
output |
The class of the object returned by the function. Either an
|
This function is meant for representing the distribution of
transition probabilities in a transition matrix. The (i,j) element of
alpha is a transition from state i to state j. It is vectorized and
written in C++ for speed.
If output = "array", then an array of matrices is returned
where each row of each matrix is a sample from the Dirichlet distribution.
If output results in a two dimensional object (i.e., a matrix,
data.frame, or data.table, then each row contains
all elements of the sampled matrix from the Dirichlet distribution
ordered rowwise; that is, each matrix is flattened. In these cases,
the number of rows must be less than or equal to the number of columns.
alpha <- matrix(c(100, 200, 500, 50, 70, 75), ncol = 3, nrow = 2, byrow = TRUE) samp <- rdirichlet_mat(100, alpha) print(samp[, , 1:2])alpha <- matrix(c(100, 200, 500, 50, 70, 75), ncol = 3, nrow = 2, byrow = TRUE) samp <- rdirichlet_mat(100, alpha) print(samp[, , 1:2])
A collection of functions for randomly generating deviates from probability
distributions with define_rng().
beta_rng( shape1 = 1, shape2 = 1, mean = NULL, sd = NULL, names = NULL, n = parent.frame()$n ) dirichlet_rng(alpha, names = NULL, n = parent.frame()$n) fixed(est, names = NULL, n = parent.frame()$n) custom(x, names = NULL, n = parent.frame()$n) gamma_rng(mean, sd, names = NULL, n = parent.frame()$n) lognormal_rng(meanlog, sdlog, names = NULL, n = parent.frame()$n) multi_normal_rng(mu, Sigma, names = NULL, n = parent.frame()$n, ...) normal_rng(mean, sd, names = NULL, n = parent.frame()$n) uniform_rng(min, max, names = NULL, n = parent.frame()$n)beta_rng( shape1 = 1, shape2 = 1, mean = NULL, sd = NULL, names = NULL, n = parent.frame()$n ) dirichlet_rng(alpha, names = NULL, n = parent.frame()$n) fixed(est, names = NULL, n = parent.frame()$n) custom(x, names = NULL, n = parent.frame()$n) gamma_rng(mean, sd, names = NULL, n = parent.frame()$n) lognormal_rng(meanlog, sdlog, names = NULL, n = parent.frame()$n) multi_normal_rng(mu, Sigma, names = NULL, n = parent.frame()$n, ...) normal_rng(mean, sd, names = NULL, n = parent.frame()$n) uniform_rng(min, max, names = NULL, n = parent.frame()$n)
shape1, shape2
|
Non-negative parameters of the Beta distribution. |
mean, sd
|
Mean and standard deviation of the random variable. |
names |
Names for columns if an object with multiple columns is returned by the function. |
n |
The number of random samples of the parameters to draw. Default is
the value of |
alpha |
A matrix where each row is a separate vector of shape parameters. |
est |
A vector of estimates of the variable of interest. |
x |
A numeric |
meanlog, sdlog
|
Mean and standard deviation of the distribution on the log scale. |
mu, Sigma
|
|
... |
Additional arguments to pass to underlying random number generation functions. See "details". |
min, max
|
Lower and upper limits of the distribution. Must be finite. |
These functions are not exported and are meant for use with
define_rng(). They consequently assume that the number of samples to draw, n,
is defined in the parent environment. Convenience random number generation
functions include:
beta_rng()If mean and sd are both not NULL, then
parameters of the beta distribution are derived using
the methods of moments with mom_beta(). Beta variates are generated with
stats::rbeta().
custom()Use previously sampled values from a custom probability distribution.
There are three possibilities: (i) if n is equal to the number previously
sampled values (say n_samples), then x is returned as is; (ii) if
n < n_samples, then samples from x are sampled without replacement;
and (iii) if n > n_samples, then samples from x are sampled with replacement
and a warning is provided.
dirichlet_rng()Dirichlet variates for each row in the matrix are
generated with rdirichlet_mat(). The sampled values are stored in a data.table
where there is a column for each element of alpha
(with elements ordered rowwise).
fixed()This function should be used when values of the variable
of interest are fixed (i.e., they are known with certainty). If length(est) > 1,
an n by length(est) data.table is returned meaning that each element of est
is repeated n times; otherwise (if length(est) == 1), a vector is returned
where est is repeated n times.
gamma_rng()The parameters of the gamma distribution are derived using
the methods of moments with mom_gamma() and gamma variates are generated
with stats::rgamma().
lognormal_rng()Lognormal variates are generated with stats::rlnorm().
multi_normal_rng()Multivariate normal variates are generated with MASS::mvrnorm().
normal_rng()Normal variates are generated with stats::rnorm().
uniform_rng()Uniform variates are generated with stats::runif().
Functions either return a vector of length n or an n by k data.table.
Multivariate distributions always return a data.table. If a
univariate distribution is used, then a data.table is returned if each
parameter is specified as a vector with length greater than 1; otherwise, if
parameters are scalars, then a vector is returned. In the data.table case,
k is equal to the length of the parameter vectors
entered as arguments. For example, if the probability distribution contained
mean as an argument and mean were
of length 3, then an n by 3 matrix would be returned. The length of all
parameter vectors must be the same. For instance, if the vector mean
were of length 3 then all additional parameters (e.g., sd)
must also be of length 3.
If a data.table is returned by a distribution, then its column names are set
according to the following hierarchy:
With the names argument if it is not NULL
With the names of the parameter vectors if they are named vectors. If there
are multiple parameter vector arguments, then the names of the first parameter
vector with non NULL names is used. For instance, if mean and sd are
both arguments to a random number generation function and mean is a
named vector, then the names from the vector mean are used.
As v1, ..., vk if the names argument is NULL and there are no
named parameter vectors.
Draw random samples from an exponential distribution with piecewise rates.
rpwexp is vectorized and written in C++ for speed.
rpwexp(n, rate = 1, time = 0)rpwexp(n, rate = 1, time = 0)
n |
Number of random observations to draw. |
rate |
A matrix of rates where rows correspond to observations and columns correspond to rates during specified time intervals. |
time |
A vector equal to the number of columns in |
A vector of random samples from the piecewise exponential distribution. The length of the sample is determined by n. The numerical arguments other than n are recycled so that the number of samples is equal to n.
rate <- c(.6, 1.2, 1.3) n <- 100000 ratemat <- matrix(rep(rate, n/2), nrow = n, ncol = 3, byrow = TRUE) t <- c(0, 10, 15) ptm <- proc.time() samp <- rpwexp(n, ratemat, t) proc.time() - ptm summary(samp)rate <- c(.6, 1.2, 1.3) n <- 100000 ratemat <- matrix(rep(rate, n/2), nrow = n, ncol = 3, byrow = TRUE) t <- c(0, 10, 15) ptm <- proc.time() samp <- rpwexp(n, ratemat, t) proc.time() - ptm summary(samp)
Update existing variables or create new ones that replace existing values
with more informative labels as in factor(). All modifications are performed
by reference (see data.table::set() for more information about assignment by
reference).
set_labels(x, labels, new_names = NULL, as_factor = TRUE)set_labels(x, labels, new_names = NULL, as_factor = TRUE)
x |
A |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
new_names |
A character vector of the same length as |
as_factor |
If |
x is modified by reference and returned invisibly.
library("data.table") labs <- list("strategy_id" = c("s1" = 1, "s2" = 2), "grp_id" = c("g1" = 1, "g2" = 2)) d1 <- data.table(strategy_id = 1:2, grp_id = 1:2) d2 <- copy(d1); d3 <- copy(d2) set_labels(d2, labels = labs) set_labels(d3, labels = labs, new_names = c("strategy_name", "grp_name")) d1 d2 d3library("data.table") labs <- list("strategy_id" = c("s1" = 1, "s2" = 2), "grp_id" = c("g1" = 1, "g2" = 2)) d1 <- data.table(strategy_id = 1:2, grp_id = 1:2) d2 <- copy(d1); d3 <- copy(d2) set_labels(d2, labels = labs) set_labels(d3, labels = labs, new_names = c("strategy_name", "grp_name")) d1 d2 d3
Simulate expected values as a function of simulated state occupancy probabilities, with simulation of costs and quality-adjusted life-years (QALYs) as particular use cases.
## S3 method for class 'stateprobs' sim_ev( object, models = NULL, dr = 0.03, integrate_method = c("trapz", "riemann_left", "riemann_right"), value_name = "value", outcome_name = "outcome", ... ) sim_qalys( object, model, dr = 0.03, integrate_method = c("trapz", "riemann_left", "riemann_right"), lys = TRUE ) sim_costs( object, models, dr = 0.03, integrate_method = c("trapz", "riemann_left", "riemann_right") )## S3 method for class 'stateprobs' sim_ev( object, models = NULL, dr = 0.03, integrate_method = c("trapz", "riemann_left", "riemann_right"), value_name = "value", outcome_name = "outcome", ... ) sim_qalys( object, model, dr = 0.03, integrate_method = c("trapz", "riemann_left", "riemann_right"), lys = TRUE ) sim_costs( object, models, dr = 0.03, integrate_method = c("trapz", "riemann_left", "riemann_right") )
object |
A |
dr |
Discount rate. |
integrate_method |
Method used to integrate state values when computing
costs or QALYs. Options are |
value_name |
Name of the column containing values of the outcome. Default
is |
outcome_name |
Name of the column indicating the outcome corresponding
to each model. Only used if |
... |
Currently unused. |
model, models
|
An object or list of objects of class |
lys |
If |
Expected values in cohort models (i.e., those implemented with
the CohortDtstm and Psm classes) are mean outcomes for patients comprising
the cohort. The method used to simulate expected values depends on the
$method field in the StateVals object(s) stored in model(s). If
$method = "starting", then state values represent a one-time value that
occurs at time 0.
The more common use case is $method = "wlos", or a "weighted length of stay".
That is, expected values for each health state can be thought of as state values
weighted by the time a patient spends in each state (and discounted by a
discount factor that depends on the discount rate dr). The
precise computation proceeds in four steps. In the first step, the probability
of being in each health state at each discrete time point is simulated
(this is the output contained in the stateprobs object). Second, a
StateVals model is used to predict state values at each time point.
Third an expected value at each time point is computed by multiplying the
state probability, the state value, and the discount factor. Fourth, the
expected values at each time point are summed across all time points.
The summation in the fourth step can be thought of as a discrete approximation
of an integral. In particular, the limits of integration can be partitioned
into time intervals, with each interval containing a start and an end.
The integrate_method argument determines the approach used
for this approximation:
A left Riemann sum (integrate_method = "riemann_left") uses expected values
at the start of each time interval.
A right Riemann sum (integrate_method = "riemann_right") uses expected values
at the end of each time interval.
The trapezoid rule (integrate_method = "trapz") averages expected values
at the start and end of each time interval. (This will generally be the
most accurate and is recommended.)
Mathematical details are provided in the reference within the "References" section below.
sim_ev() returns a data.table with the following columns:
A random sample from the PSA.
The treatment strategy ID.
The patient ID.
The subgroup ID.
The health state ID.
The rate used to discount costs.
The outcome corresponding to each model in models.
Only included if models is a list.
The expected value.
The names of the outcome and value columns may be changed with the
value_name and outcome_name arguments. sim_costs() and sim_qalys()
return similar objects, that are of class costs and qalys, respectively.
The ID variables in the state value models in models must be
consistent with the ID variables contained in object. In particular,
the models should predict state values for each non-absorbing health state
in object; that is, the number of health states modeled with the
models should equal the number of health states in object less the number
of absorbing states.
The absorbing states are saved as an attribute named absorbing to
stateprobs objects. When simulating state probabilities with a
CohortDtstmTrans object, the absorbing state is determined by the
absorbing field in the class; in a Psm (or with
sim_stateprobs.survival()), the absorbing state is always equal to the
final health state.
Incerti and Jansen (2021). See Section 2.1 for mathematical details.
State probabilities can be simulated using the
$sim_stateprobs() methods from either the CohortDtstmTrans
(or CohortDtstm) or Psm classes. State probabilities can also be
computed directly from survival curves with the generic method
sim_stateprobs.survival().
Costs and QALYs are typically computed within the R6 model classes
using the $sim_costs() and $sim_qalys() methods. For instance, see the
documentation and examples for the CohortDtstm and Psm classes.
The sim_qalys() and sim_costs() functions are exported to give users
additional flexibility when creating their own modeling pipelines.
sim_ev() may be useful for computing outcomes other than costs or QALYs.
costs and qalys objects can be passed to summarize_ce() to
create a cost-effectiveness object for performing a cost-effectiveness analysis
with cea(). Although note that typically the $summarize() method
belonging to the CohortDtstm or Psm classes would be used instead.
Use the IndivCtstm class to simulate costs and QALYs with an individual
continuous-time state transition model.
# We need (i) a state probability object and (ii) a model for state values ## We should start by setting up our decision problem hesim_dat <- hesim_data(strategies = data.frame(strategy_id = 1:2), patients = data.frame(patient_id = 1:3), states = data.frame(state_id = 1)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) ## (i) Simulate a state probability object tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- ifelse(tpmat_id$strategy_id == 1, .15, .1) tpmat <- tpmatrix( C, p_12, 0, 1 ) transmod <- CohortDtstmTrans$new(params = tparams_transprobs(tpmat, tpmat_id)) stprobs <- transmod$sim_stateprobs(n_cycles = 3) ## Construct model for state values outcome_tbl <- stateval_tbl( data.frame( state_id = 1, est = 5000 ), dist = "fixed" ) outmod <- create_StateVals(outcome_tbl, n = 2, hesim_data = hesim_dat) # We can then simulate expected values ## The generic expected values function sim_ev(stprobs, models = outmod) ## We can also pass a list of models sim_ev(stprobs, models = list(`Outcome 1` = outmod)) ## Suppose the outcome were a cost category. Then we might ## prefer the following: sim_costs(stprobs, models = list(drug = outmod)) ## Length of stay is computed if there is no state value model sim_ev(stprobs)# We need (i) a state probability object and (ii) a model for state values ## We should start by setting up our decision problem hesim_dat <- hesim_data(strategies = data.frame(strategy_id = 1:2), patients = data.frame(patient_id = 1:3), states = data.frame(state_id = 1)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) ## (i) Simulate a state probability object tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- ifelse(tpmat_id$strategy_id == 1, .15, .1) tpmat <- tpmatrix( C, p_12, 0, 1 ) transmod <- CohortDtstmTrans$new(params = tparams_transprobs(tpmat, tpmat_id)) stprobs <- transmod$sim_stateprobs(n_cycles = 3) ## Construct model for state values outcome_tbl <- stateval_tbl( data.frame( state_id = 1, est = 5000 ), dist = "fixed" ) outmod <- create_StateVals(outcome_tbl, n = 2, hesim_data = hesim_dat) # We can then simulate expected values ## The generic expected values function sim_ev(stprobs, models = outmod) ## We can also pass a list of models sim_ev(stprobs, models = list(`Outcome 1` = outmod)) ## Suppose the outcome were a cost category. Then we might ## prefer the following: sim_costs(stprobs, models = list(drug = outmod)) ## Length of stay is computed if there is no state value model sim_ev(stprobs)
Simulate health state probabilities from a survival object using partitioned
survival analysis.
## S3 method for class 'survival' sim_stateprobs(x, ...)## S3 method for class 'survival' sim_stateprobs(x, ...)
x |
An object of class |
... |
Further arguments passed to or from other methods. |
In an -state partitioned survival model there are survival curves
and is the cumulative survival function denoting the probability of
survival to health state or a lower indexed state beyond time .
The probability that a patient is in health state 1 at time is simply
. State membership in health states is calculated
as . Finally, the probability of being in the final
health state (i.e., the death state) is , or
one minus the overall survival curve.
In some cases, the survival curves may cross. hesim will issue a warning
but the function will still run. Probabilities will be set to 0 in a health state
if the prior survival curve lies above the curve for state ;
that is, if , then the probability of being in state
is set to 0 and is adjusted to equal . The
probability of being in the final health state is also adjusted if necessary to
ensure that probabilities sum to 1.
A stateprobs object.
library("data.table") library("survival") # This example shows how to simulate a partitioned survival model by # manually constructing a "survival" object. We will consider a case in which # Cox proportional hazards models from the survival package---which are not # integrated with hesim---are used for parameter estimation. We will use # point estimates in the example, but bootstrapping, Bayesian modeling, # or other techniques could be used to draw samples for a probabilistic # sensitivity analysis. # (0) We first setup our model per usual by defining the treatment strategies, # target population, and health states hesim_dat <- hesim_data( strategies = data.table(strategy_id = 1:3, strategy_name = c("SOC", "New 1", "New 2")), patients = data.table(patient_id = 1:2, female = c(0, 1), grp_id = 1), states = data.table(state_id = 1:2, state_name = c("Stable", "Progression")) ) # (1) Next we will estimate Cox models with survival::coxph(). We illustrate # by predicting progression free survival (PFS) and overall survival (OS) ## Fit models onc3_pfs_os <- as_pfs_os(onc3, patient_vars = c("patient_id", "female", "strategy_name")) fit_pfs <- coxph(Surv(pfs_time, pfs_status) ~ strategy_name + female, data = onc3_pfs_os) fit_os <- coxph(Surv(os_time, pfs_status) ~ strategy_name + female, data = onc3_pfs_os) ## Predict survival on input data surv_input_data <- expand(hesim_dat) times <- seq(0, 14, 1/12) predict_survival <- function(object, newdata, times) { surv <- summary(survfit(object, newdata = newdata, se.fit = FALSE), t = times) pred <- newdata[rep(seq_len(nrow(newdata)), each = length(times)), ] pred[, sample := 1] # Point estimates only in this example pred[, time := rep(surv$time, times = nrow(newdata))] pred[, survival := c(surv$surv)] return(pred[, ]) } pfs <- predict_survival(fit_pfs, newdata = surv_input_data, times = times) os <- predict_survival(fit_os, newdata = surv_input_data, times = times) surv <- rbind( as.data.table(pfs)[, curve := 1L], as.data.table(os)[, curve := 2L] ) ## Convert predictions to a survival object surv <- survival(surv, t = "time") ## Not run: autoplot(surv) # (2) We can then compute state probabilities from the survival object stprobs <- sim_stateprobs(surv) # (3) Finally, we can use the state probabilities to compute QALYs and costs ## A dummy utility model to illustrate utility_tbl <- stateval_tbl( data.table(state_id = 1:2, est = c(1, 1) ), dist = "fixed" ) utilitymod <- create_StateVals(utility_tbl, hesim_data = hesim_dat, n = 1) ## Instantiate Psm class and compute QALYs psm <- Psm$new(utility_model = utilitymod) psm$stateprobs_ <- stprobs psm$sim_qalys() psm$qalys_library("data.table") library("survival") # This example shows how to simulate a partitioned survival model by # manually constructing a "survival" object. We will consider a case in which # Cox proportional hazards models from the survival package---which are not # integrated with hesim---are used for parameter estimation. We will use # point estimates in the example, but bootstrapping, Bayesian modeling, # or other techniques could be used to draw samples for a probabilistic # sensitivity analysis. # (0) We first setup our model per usual by defining the treatment strategies, # target population, and health states hesim_dat <- hesim_data( strategies = data.table(strategy_id = 1:3, strategy_name = c("SOC", "New 1", "New 2")), patients = data.table(patient_id = 1:2, female = c(0, 1), grp_id = 1), states = data.table(state_id = 1:2, state_name = c("Stable", "Progression")) ) # (1) Next we will estimate Cox models with survival::coxph(). We illustrate # by predicting progression free survival (PFS) and overall survival (OS) ## Fit models onc3_pfs_os <- as_pfs_os(onc3, patient_vars = c("patient_id", "female", "strategy_name")) fit_pfs <- coxph(Surv(pfs_time, pfs_status) ~ strategy_name + female, data = onc3_pfs_os) fit_os <- coxph(Surv(os_time, pfs_status) ~ strategy_name + female, data = onc3_pfs_os) ## Predict survival on input data surv_input_data <- expand(hesim_dat) times <- seq(0, 14, 1/12) predict_survival <- function(object, newdata, times) { surv <- summary(survfit(object, newdata = newdata, se.fit = FALSE), t = times) pred <- newdata[rep(seq_len(nrow(newdata)), each = length(times)), ] pred[, sample := 1] # Point estimates only in this example pred[, time := rep(surv$time, times = nrow(newdata))] pred[, survival := c(surv$surv)] return(pred[, ]) } pfs <- predict_survival(fit_pfs, newdata = surv_input_data, times = times) os <- predict_survival(fit_os, newdata = surv_input_data, times = times) surv <- rbind( as.data.table(pfs)[, curve := 1L], as.data.table(os)[, curve := 2L] ) ## Convert predictions to a survival object surv <- survival(surv, t = "time") ## Not run: autoplot(surv) # (2) We can then compute state probabilities from the survival object stprobs <- sim_stateprobs(surv) # (3) Finally, we can use the state probabilities to compute QALYs and costs ## A dummy utility model to illustrate utility_tbl <- stateval_tbl( data.table(state_id = 1:2, est = c(1, 1) ), dist = "fixed" ) utilitymod <- create_StateVals(utility_tbl, hesim_data = hesim_dat, n = 1) ## Instantiate Psm class and compute QALYs psm <- Psm$new(utility_model = utilitymod) psm$stateprobs_ <- stprobs psm$sim_qalys() psm$qalys_
An object of class stateprobs returned by sim_stateprobs() or from
$sim_stateprobs() methods in model classes.
A stateprobs object inherits from data.table and contains
the following columns:
A random sample from the PSA.
The treatment strategy ID.
The patient ID.
The subgroup ID.
The health state ID.
The time at which a state probability is computed.
The probability of being in a given health state.
When simulating individual-level models, the patient_id column is
not included as state probabilities are computed by averaging across patients.
In cohort models, the object also contains size and absorbing attributes.
The size attribute is a numeric vector with the elements n_samples,
n_strategies, n_patients, n_states, and
n_times denoting the number of samples, treatment strategies, patients,
health states, and times. The absorbing attribute is a numeric vector
containing the absorbing health states (see the absorbing field of the
CohortDtstmTrans class for more details).
Create a table for storing parameter estimates used to simulate costs or utility in an economic model by treatment strategy, patient, health state, and (optionally) time interval.
stateval_tbl( tbl, dist = c("norm", "beta", "gamma", "lnorm", "unif", "fixed", "custom"), hesim_data = NULL, grp_var = NULL )stateval_tbl( tbl, dist = c("norm", "beta", "gamma", "lnorm", "unif", "fixed", "custom"), hesim_data = NULL, grp_var = NULL )
tbl |
A |
dist |
Probability distribution used to sample parameters for a probabilistic sensitivity analysis (PSA). |
hesim_data |
A |
grp_var |
The name of the variable used to group patients. |
tbl is a tabular object containing columns for treatment
strategies (strategy_id), patients (patient_id),
health states (state_id), and/or the start of time intervals
(time_start). The table must contain at least one column
named strategy_id, patient_id, or state_id,
but does not need to contain all of them. Each row denotes a unique
treatment strategy, patient, health state, and/or time interval pair.
tbl may also contain a column with the name specified in grp_var
(rather than patient_id) so that state values are assigned to
groups of patients.
tbl must also contain columns summarizing the state values for each
row, which depend on the probability distribution selected with dist.
Available distributions include the normal (norm), beta (beta),
gamma (gamma), lognormal (lnorm), and uniform (unif)
distributions. In addition, the option fixed can be used if estimates
are known with certainty and custom can be used if
parameter values for a PSA have been previously
sampled from an arbitrary probability distribution.
The columns in tbl that must be included,
by distribution, are:
mean and sd
mean and se or shape1 and shape2
mean and se, shape and rate,
or shape and scale
meanlog or sdlog
min and max
est
sample and value
Note that if dist = "custom", then tbl must include a column
named sample (an integer vector denoting a unique random draw) and
value (denoting the value of the randomly sampled parameter). In this case,
there is a unique row in tbl for each random draw (sample) and
each combination of strategies, patients, health states, and/or time intervals.
Again, tbl must contain at least one column
named strategy_id, patient_id (or grp_var), or state_id,
but does not need to contain them all.
An object of class stateval_tbl, which is a data.table of
parameter values with attributes for dist and grp_var.
strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), grp = c(1, 1, 2), age = c(45, 50, 60), female = c(0, 0, 1)) states <- data.frame(state_id = c(1, 2)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) # Utility varies by health state and patient group utility_tbl <- stateval_tbl(data.frame(state_id = rep(states$state_id, 2), grp = rep(rep(c(1, 2)), each = nrow(states)), mean = c(.8, .7, .75, .55), se = c(.18, .12, .10, .06)), dist = "beta", grp_var = "grp") print(utility_tbl) utilmod <- create_StateVals(utility_tbl, n = 2, hesim_data = hesim_dat) # Costs vary by treatment strategy cost_tbl <- stateval_tbl(data.frame(strategy_id = strategies$strategy_id, mean = c(5000, 3000), se = c(200, 100)), dist = "gamma") print(cost_tbl) costmod <- create_StateVals(cost_tbl, n = 2, hesim_data = hesim_dat)strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), grp = c(1, 1, 2), age = c(45, 50, 60), female = c(0, 0, 1)) states <- data.frame(state_id = c(1, 2)) hesim_dat <- hesim_data(strategies = strategies, patients = patients, states = states) # Utility varies by health state and patient group utility_tbl <- stateval_tbl(data.frame(state_id = rep(states$state_id, 2), grp = rep(rep(c(1, 2)), each = nrow(states)), mean = c(.8, .7, .75, .55), se = c(.18, .12, .10, .06)), dist = "beta", grp_var = "grp") print(utility_tbl) utilmod <- create_StateVals(utility_tbl, n = 2, hesim_data = hesim_dat) # Costs vary by treatment strategy cost_tbl <- stateval_tbl(data.frame(strategy_id = strategies$strategy_id, mean = c(5000, 3000), se = c(200, 100)), dist = "gamma") print(cost_tbl) costmod <- create_StateVals(cost_tbl, n = 2, hesim_data = hesim_dat)
Simulate values (i.e., utility or costs) associated with health states in a state transition or partitioned survival model.
paramsParameters for simulating state values. Currently supports
objects of class tparams_mean or params_lm.
input_dataAn object of class input_mats. Only used for
params_lm objects.
methodThe method used to simulate costs and
quality-adjusted life-years (QALYs) as a function of state values.
If wlos, then costs and QALYs are
simulated by weighting state values by the length of stay in a health
state. If starting, then state values represent a one-time value
that occurs when a patient enters a health state. When starting is
used in a cohort model, the state values only accrue at time 0;
in contrast, in an individual-level model, state values
accrue each time a patient enters a new state and are discounted based on
time of entrance into that state.
time_resetIf FALSE then time intervals are based on time since
the start of the simulation. If TRUE, then time intervals reset each
time a patient enters a new health state. This is relevant if, for example,
costs vary over time within health states. Only used if method = wlos.
new()
Create a new StateVals object.
StateVals$new(
params,
input_data = NULL,
method = c("wlos", "starting"),
time_reset = FALSE
)paramsThe params field.
input_dataThe input_data field.
methodThe method field.
time_resetThe time_reset field.
A new StateVals object.
sim()
Simulate state values with either predicted means or random samples by
treatment strategy, patient, health state, and time t.
StateVals$sim(t, type = c("predict", "random"))tA numeric vector of times.
type"predict" for mean values or "random" for random samples.
A data.table of simulated state values with columns for sample,
strategy_id, patient_id, state_id, time, and value.
check()
Input validation for class. Checks that fields are the correct type.
StateVals$check()
clone()
The objects of this class are cloneable with this method.
StateVals$clone(deep = FALSE)
deepWhether to make a deep clone.
# Simple sick-sicker example where drug costs vary by treatment strategy # and over time. Prior to time = 5, costs are $10,000 for treatment strategy # 1 and $5,000 for treatment strategy 2. After time = 5, costs are $2,000 # for both treatment strategies ## Setup the model hesim_dat <- hesim_data( strategies = data.frame(strategy_id = c(1, 2)), patients = data.frame(patient_id = 1:3), states = data.frame(state_id = c(1, 2), # Non-death states state_name = c("sick", "sicker")) ) ## Drug costs vary by health state and time interval drugcost_tbl <- stateval_tbl( data.frame( strategy_id = c(1, 1, 2, 2), time_start = c(0, 5, 0, 5), est = c(10000, 2000, 5000, 2000) ), dist = "fixed" ) drugcost_tbl ## Create drug cost model drugcostmod <- create_StateVals(drugcost_tbl, n = 1, hesim_data = hesim_dat) ## Explore predictions from the drug cost model drugcostmod$sim(t = c(2, 6), type = "predict")# Simple sick-sicker example where drug costs vary by treatment strategy # and over time. Prior to time = 5, costs are $10,000 for treatment strategy # 1 and $5,000 for treatment strategy 2. After time = 5, costs are $2,000 # for both treatment strategies ## Setup the model hesim_dat <- hesim_data( strategies = data.frame(strategy_id = c(1, 2)), patients = data.frame(patient_id = 1:3), states = data.frame(state_id = c(1, 2), # Non-death states state_name = c("sick", "sicker")) ) ## Drug costs vary by health state and time interval drugcost_tbl <- stateval_tbl( data.frame( strategy_id = c(1, 1, 2, 2), time_start = c(0, 5, 0, 5), est = c(10000, 2000, 5000, 2000) ), dist = "fixed" ) drugcost_tbl ## Create drug cost model drugcostmod <- create_StateVals(drugcost_tbl, n = 1, hesim_data = hesim_dat) ## Explore predictions from the drug cost model drugcostmod$sim(t = c(2, 6), type = "predict")
Summarize a ce object by producing confidence intervals for quality-adjusted
life-years (QALYs) and each cost category with summary.ce() and format for
pretty printing with format.summary.ce().
## S3 method for class 'ce' summary(object, prob = 0.95, labels = NULL, ...) ## S3 method for class 'summary.ce' format( x, digits_qalys = 2, digits_costs = 0, dr_qalys = NULL, dr_costs = NULL, pivot_from = "strategy", drop_grp = TRUE, pretty_names = TRUE, ... )## S3 method for class 'ce' summary(object, prob = 0.95, labels = NULL, ...) ## S3 method for class 'summary.ce' format( x, digits_qalys = 2, digits_costs = 0, dr_qalys = NULL, dr_costs = NULL, pivot_from = "strategy", drop_grp = TRUE, pretty_names = TRUE, ... )
object |
A |
prob |
A numeric scalar in the interval |
labels |
A list of named vectors containing the values and labels of
variables. The elements of each vector are the values of a variable and the
names are the labels. The names of the list are the names of the variables.
See the output returned by |
... |
Further arguments passed to or from other methods. Currently unused. |
x |
A |
digits_qalys |
Number of digits to use to report QALYs. |
digits_costs |
Number of digits to use to report costs. |
dr_qalys |
Discount rate to subset to for quality-adjusted life-years (QALYs). |
dr_costs |
Discount rate to subset to for costs. |
pivot_from |
Character vector denoting a column or columns used to
"widen" the data. Should either be |
drop_grp |
If |
pretty_names |
Logical. If |
For an example, see IndivCtstm.
summary.ce() returns an object of class summary.ce that is a tidy
data.table with the following columns:
The discount rate.
The treatment strategy.
The patient subgroup.
Either "QALYs" or "Costs".
Category is always "QALYs" when type == "QALYs"; otherwise,
it is the cost category.
The point estimate computed as the average across the PSA samples.
The lower limit of the confidence interval.
The upper limit of the confidence interval.
format.summary.ce() formats the table according to the arguments passed.
eval_rng objectSummarize the model parameters randomly sampled for probabilistic sensitivity
analysis with eval_rng().
## S3 method for class 'eval_rng' summary(object, probs = c(0.025, 0.975), sep = "_", ...) ## S3 method for class 'eval_rng' print(x, ...)## S3 method for class 'eval_rng' summary(object, probs = c(0.025, 0.975), sep = "_", ...) ## S3 method for class 'eval_rng' print(x, ...)
object, x
|
An |
probs |
A numeric vector of probabilities with values in |
sep |
When a list element returned by |
... |
For the print method, arguments to pass to |
summary.eval_rng() returns a data.table::data.table with columns for
(i) the name of the parameter (param), (ii) the mean of the parameter
samples (mean), (iii) the standard deviation of the parameter samples (sd),
and (iv) quantiles of the parameter samples corresponding
to the probs argument. print.eval_rng() prints the output of
summary.eval_rng() to the console.
See eval_rng() for an example.
Summarize the coefficients of a parameter object by computing the mean, standard deviation, and quantiles for each model term. This is a convenient way to check whether a parameter object has been specified correctly and sampling distributions of the coefficients are as expected.
## S3 method for class 'params_lm' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_mlogit' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_mlogit_list' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_surv' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_surv_list' summary(object, probs = c(0.025, 0.975), ...)## S3 method for class 'params_lm' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_mlogit' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_mlogit_list' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_surv' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'params_surv_list' summary(object, probs = c(0.025, 0.975), ...)
object |
An object of the appropriate class. |
probs |
A numeric vector of probabilities with values in |
... |
Additional arguments affecting the summary. Currently unused. |
A data.table::data.table that always contains the following columns:
The regression term.
The mean value of the regression term.
The standard deviation of the values of the regression term.
In addition, the probs argument determines the quantiles that are computed.
By default, the columns 2.5% and 97.5% are returned corresponding to the
2.5th and 97.5th percentiles.
Finally, the following columns may also be present:
The name of the parameter of interest. This is relevant
for any parametric model in which the underlying probability distribution
has multiple parameters. For instance, both params_surv and params_surv_list
store regression coefficients that are used to model the underlying parameters
of the survival distribution (e.g., shape and scale for a Weibull model). Similarly,
there are two parameters (mean and sd) for params_lm objects.
The name of the statistical model. This is used for a
params_surv_list object, where each list element represents a separate model.
In a state transition model, each model is a unique health state transition and
in a partitioned survival model, there is a separate model for each curve.
The health state that is being transitioned to. In params_mlogit
and params_mlogit_list objects, there are coefficients for each health
state that can be transitioned to.
The health state that is being transitions from. This is used
for a params_mlogit_list objects where a different multinomial
logistic regression is used for each state that can be transitioned from.
For examples, see the the underlying parameter object functions:
params_lm(), params_surv(), params_surv_list(), params_mlogit(), and
params_mlogit_list().
tparams_mean objectThe summary() method summarizes a tparams_mean object containing
predicted means; summary statistics are computed for each
combination of the ID variables. The print() method
summarizes the object using summary.tparams_mean() and prints it to the
console.
## S3 method for class 'tparams_mean' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'tparams_mean' print(x, ...)## S3 method for class 'tparams_mean' summary(object, probs = c(0.025, 0.975), ...) ## S3 method for class 'tparams_mean' print(x, ...)
object, x
|
A |
probs |
A numeric vector of probabilities with values in |
... |
Currently unused. |
A data.table with columns for (i) the ID variables,
(ii) the mean of each parameter across parameter samples (mean),
(iii) the standard deviation of the parameter samples (sd), and
(iv) quantiles of the parameter samples corresponding to the probs argument.
See tparams_mean for an example use of the summary and
print methods.
tparams_transprobs objectThe summary() method summarizes a tparams_transprobs object containing
predicted transition probabilities; summary statistics are computed for each
possible transition by the relevant ID variables.
## S3 method for class 'tparams_transprobs' summary(object, probs = NULL, unflatten = FALSE, ...)## S3 method for class 'tparams_transprobs' summary(object, probs = NULL, unflatten = FALSE, ...)
object |
A |
probs |
A numeric vector of probabilities with values in |
unflatten |
If |
... |
Additional arguments affecting the summary. Currently unused. |
If unflatten = "FALSE" (the default), then a data.table::data.table
is returned with columns for (i) the health state that is being transitioned
from (from), (ii) the health state that is being transitioned to (to)
(iii) the mean of each parameter across parameter samples (mean),
(iv) the standard deviation of the parameter samples (sd), and
(v) quantiles of the parameter samples corresponding to the probs argument.
If, on the other hand, unflatten = "TRUE", then the parameters are unflattened
to form transition probability matrices; that is, the mean, sd, and
quantile columns are (lists of) matrices.
In both cases, the ID variables are also returned as columns.
See tparams_transprobs for an example use of the summary method.
Summarize a tpmatrix object storing transition probability matrices.
Summary statistics are computed for each possible transition.
## S3 method for class 'tpmatrix' summary(object, id = NULL, probs = NULL, unflatten = FALSE, ...)## S3 method for class 'tpmatrix' summary(object, id = NULL, probs = NULL, unflatten = FALSE, ...)
object |
A |
id |
A |
probs |
A numeric vector of probabilities with values in |
unflatten |
If |
... |
Additional arguments affecting the summary. Currently unused. |
If unflatten = "FALSE" (the default), then a data.table::data.table
is returned with columns for (i) the health state that is being transitioned
from (from), (ii) the health state that is being transitioned to (to)
(iii) the mean of each parameter across parameter samples (mean),
(iv) the standard deviation of the parameter samples (sd), and
(v) quantiles of the parameter samples corresponding to the probs argument.
If, on the other hand, unflatten = "TRUE", then the parameters are unflattened
to form transition probability matrices; that is, the mean, sd, and
quantile columns are (lists of) matrices.
In both cases, if id is not NULL, then the ID variables are also
returned as columns.
library("data.table") hesim_dat <- hesim_data(strategies = data.table(strategy_id = 1:2), patients = data.table(patient_id = 1:3)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) # Summarize across all rows in "input_data" p_12 <- ifelse(input_data$strategy_id == 1, .8, .6) p <- tpmatrix( C, p_12, 0, 1 ) ## Summary where each column is a vector summary(p) summary(p, probs = c(.025, .975)) ## Summary where each column is a matrix ps <- summary(p, probs = .5, unflatten = TRUE) ps ps$mean # Summarize by ID variables tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- ifelse(tpmat_id$strategy_id == 1, .8, .6) p <- tpmatrix( C, p_12, 0, 1 ) ## Summary where each column is a vector summary(p, id = tpmat_id) ## Summary where each column is a matrix ps <- summary(p, id = tpmat_id, unflatten = TRUE) ps ps$meanlibrary("data.table") hesim_dat <- hesim_data(strategies = data.table(strategy_id = 1:2), patients = data.table(patient_id = 1:3)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) # Summarize across all rows in "input_data" p_12 <- ifelse(input_data$strategy_id == 1, .8, .6) p <- tpmatrix( C, p_12, 0, 1 ) ## Summary where each column is a vector summary(p) summary(p, probs = c(.025, .975)) ## Summary where each column is a matrix ps <- summary(p, probs = .5, unflatten = TRUE) ps ps$mean # Summarize by ID variables tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- ifelse(tpmat_id$strategy_id == 1, .8, .6) p <- tpmatrix( C, p_12, 0, 1 ) ## Summary where each column is a vector summary(p, id = tpmat_id) ## Summary where each column is a matrix ps <- summary(p, id = tpmat_id, unflatten = TRUE) ps ps$mean
Compute quantiles from survival curves.
surv_quantile(x, probs = 0.5, t, surv_cols, by)surv_quantile(x, probs = 0.5, t, surv_cols, by)
x |
A |
probs |
A numeric vector of probabilities with values in |
t |
A character scalar of the name of the time column. |
surv_cols |
A character vector of the names of columns containing survival curves. |
by |
A character vector of the names of columns to group by. |
A data.table of quantiles of each survival curve in
surv_cols by each group in by.
library("data.table") t <- seq(0, 10, by = .01) surv1 <- seq(1, .3, length.out = length(t)) surv2 <- seq(1, .2, length.out = length(t)) strategies <- c("Strategy 1", "Strategy 2") surv <- data.table(strategy = rep(strategies, each = length(t)), t = rep(t, 2), surv = c(surv1, surv2)) surv_quantile(surv, probs = c(.4, .5), t = "t", surv_cols = "surv", by = "strategy")library("data.table") t <- seq(0, 10, by = .01) surv1 <- seq(1, .3, length.out = length(t)) surv2 <- seq(1, .2, length.out = length(t)) strategies <- c("Strategy 1", "Strategy 2") surv <- data.table(strategy = rep(strategies, each = length(t)), t = rep(t, 2), surv = c(surv1, surv2)) surv_quantile(surv, probs = c(.4, .5), t = "t", surv_cols = "surv", by = "strategy")
An object of class survival stores survival probabilities. It is typically
returned by Psm$sim_survival() or PsmCurves$survival(); however, it can also
be constructed "manually" from existing data using the survival()
function as described below. The latter option is useful if survival modeling
has been performed by an R package other than those that integrate with hesim (
currently flexsurv). In this case a simulation model can still be developed
by using sim_stateprobs.survival() to compute simulated state probabilities and
then simulating quality-adjusted life-years and costs in a typical fashion.
survival( data, sample = "sample", strategy_id = "strategy_id", patient_id = "patient_id", grp_id = "grp_id", curve = "curve", t = "t", survival = "survival" )survival( data, sample = "sample", strategy_id = "strategy_id", patient_id = "patient_id", grp_id = "grp_id", curve = "curve", t = "t", survival = "survival" )
data |
A tabular object that can be coerced to a |
sample |
The name of the column corresponding to |
strategy_id |
The name of the column corresponding to |
patient_id |
The name of the column corresponding to |
grp_id |
The name of the column corresponding to |
curve |
The name of the column corresponding to |
t |
The name of the column corresponding to |
survival |
The name of the column corresponding to |
An object of class survival that inherits from data.table and contains
the following columns:
A random sample from the PSA.
The treatment strategy ID.
The patient ID.
The subgroup ID.
One of the N-1 survival curves in an N-state partitioned
survival model. Each curve corresponds to unique endpoint.
The time at which a survival probability is computed.
The probability of surviving to time t.
The object also contains a size attribute that contains the elements
n_samples, n_strategies, n_patients, n_states, and n_times denoting
the number of samples, treatment strategies, patients, health states, and times.
survival objects are returned by methods in the Psm and PsmCurves
classes. An example in which a survival object is constructed "manually"
(presumably from a preexisting survival model fit using software other than flexsurv)
is provided in the documentation to sim_stateprobs.survival().
Create a table of time intervals given a vector or data frame of unique times. This would typically be passed to id_attributes.
time_intervals(times)time_intervals(times)
times |
Either a vector of starting times for each interval or a
|
An object of class time_intervals that inherits from
data.table in the same format as time_intervals as
described in id_attributes.
time_intervals(c(0, 3, 5)) time_intervals(data.frame(time_start = c(0, 3, 5), time_cat = c("Time <= 3", "3 < Time <= 5", "Time > 5")))time_intervals(c(0, 3, 5)) time_intervals(data.frame(time_start = c(0, 3, 5), time_cat = c("Time <= 3", "3 < Time <= 5", "Time > 5")))
Objects prefixed by "tparams_" are lists containing transformed parameters used to simulate outcomes. The parameters have presumably already been transformed as a function of input data and consequently do not need to be used alongside input matrices. In other words, transformed parameters are parameters that have already been predicted as a function of covariates.
Create a list containing means predicted from a statistical model.
tparams_mean(value, ...)tparams_mean(value, ...)
value |
Matrix of samples from the distribution of the mean. Columns denote random samples and rows denote means for different observations. |
... |
Arguments to pass to id_attributes. Each row in
|
An object of class tparams_mean, which is a list containing value,
n_samples, and the ID attributes passed to id_attributes.
The tparams_mean() constructor would not normally be used by users; instead,
a tparams_mean object is typically created automatically as part of the
StateVals class with create_StateVals().
A tparams_mean object is a type of transformed parameter
object and is a supported class type of the params field of the StateVals
class. See the documentation for create_StateVals() and stateval_tbl()
for examples of how to createStateVals objects. Predicted means can be
summarized across parameter samples using summary.tparams_mean().
# Setup model hesim_dat <- hesim_data( strategies = data.frame(strategy_id = c(1, 2)), patients = data.frame(patient_id = c(1, 2)), states = data.frame( state_id = c(1, 2, 3), state_name = c("state1", "state2", "state3") ) ) # Cost model cost_tbl <- stateval_tbl( data.frame(strategy_id = hesim_dat$strategies$strategy_id, mean = c(5000, 3000), se = c(200, 100) ), dist = "gamma" ) costmod <- create_StateVals(cost_tbl, n = 2, hesim_data = hesim_dat) # The 'params' field of the `StateVals` class is a tparams_mean object class(costmod$params) costmod$params summary(costmod$params)# Setup model hesim_dat <- hesim_data( strategies = data.frame(strategy_id = c(1, 2)), patients = data.frame(patient_id = c(1, 2)), states = data.frame( state_id = c(1, 2, 3), state_name = c("state1", "state2", "state3") ) ) # Cost model cost_tbl <- stateval_tbl( data.frame(strategy_id = hesim_dat$strategies$strategy_id, mean = c(5000, 3000), se = c(200, 100) ), dist = "gamma" ) costmod <- create_StateVals(cost_tbl, n = 2, hesim_data = hesim_dat) # The 'params' field of the `StateVals` class is a tparams_mean object class(costmod$params) costmod$params summary(costmod$params)
Create a list containing predicted transition probabilities at discrete times.
Since the transition probabilities have presumably already been predicted
based on covariate values, no input data is required for
simulation. The class can be instantiated from either an array,
a data.table, a data.frame, or a tpmatrix. This is the object in
hesim used to specify the transition probabilities required to simulate
Markov chains with the CohortDtstmTrans class.
tparams_transprobs(object, ...) ## S3 method for class 'array' tparams_transprobs( object, tpmatrix_id = NULL, times = NULL, grp_id = NULL, patient_wt = NULL, ... ) ## S3 method for class 'data.table' tparams_transprobs(object, ...) ## S3 method for class 'data.frame' tparams_transprobs(object, ...) ## S3 method for class 'tpmatrix' tparams_transprobs(object, tpmatrix_id, ...)tparams_transprobs(object, ...) ## S3 method for class 'array' tparams_transprobs( object, tpmatrix_id = NULL, times = NULL, grp_id = NULL, patient_wt = NULL, ... ) ## S3 method for class 'data.table' tparams_transprobs(object, ...) ## S3 method for class 'data.frame' tparams_transprobs(object, ...) ## S3 method for class 'tpmatrix' tparams_transprobs(object, tpmatrix_id, ...)
object |
An object of the appropriate class. |
... |
Further arguments passed to or from other methods. Currently unused. |
tpmatrix_id |
An object of class |
times |
An optional numeric vector of distinct times to pass to time_intervals representing time intervals indexed by the 4th dimension of the array. May either be the start or the end of intervals. This argument is not required if there is only one time interval. |
grp_id |
An optional numeric vector of integers denoting the subgroups. Must be the same length as the 3rd dimension of the array. |
patient_wt |
An optional numeric vector denoting the weight to apply to each patient within a subgroup. Must be the same length as the 3rd dimension of the array. |
The format of object depends on its class:
Either a 3D or a 6D array is possible.
If a 3D array, then each slice is a
square transition probability matrix. In this case
tpmatrix_id is required and each matrix slice corresponds to the same
numbered row in tpmatrix_id. The number of matrix slices must equal the number
of rows in tpmatrix_id.
If a 6D array, then the dimensions of the array should be indexed as follows:
1st (sample), 2nd (strategy_id), 3rd (patient_id),
4th (time_id), 5th (rows of transition matrix), and
6th (columns of transition matrix). In other words, an index of
[s, k, i, t] represents the transition matrix for the sth
sample, kth treatment strategy, ith patient, and tth
time interval.
Must contain the following:
ID columns for the parameter sample (sample),
treatment strategy (strategy_id), and patient (patient_id).
If the number of time intervals is greater than 1 it must also contain the
column time_start denoting the starting time of a time interval. A column
patient_wt may also be used to denote the weight to apply to each
patient.
Columns for each element of the transition probability matrix.
They should be prefixed with "prob_" and ordered rowwise.
For example, the following columns would be used for a 2x2 transition
probability matrix:
prob_1 (1st row, 1st column),
prob_2 (1st row, 2nd column),
prob_3 (2nd row, 1st column), and
prob_4 (2nd row, 2nd column).
Same as data.table.
An object of class tpmatrix.
A tparams_transprobs object is also instantiated when creating a
cohort discrete time state transition model using define_model().
An object of class tparams_transprobs,
which is a list containing value and relevant ID attributes. The element
value is an array of predicted transition probability matrices from the
probability distribution of the underlying statistical model. Each matrix in
value is a prediction for a sample, strategy_id, patient_id, and
optionally time_id combination.
A tparams_transprobs object is used to store the "parameters" of
the transition component of a cohort discrete time state transition
model (cDTSTM). You can create such an object with CohortDtstmTran$new().
tpmatrix() and tpmatrix_id() provide a convenient way to construct a
tparams_transprobs object in a flexible way. define_model() is, in turn,
a convenient way to construct a tpmatrix object using mathematical
expressions; in this case, an entire cDTSTM can be instantiated from a model
definition using create_CohortDtstm.model_def(). Detailed examples
are provided in vignette("markov-cohort") and
vignette("markov-inhomogeneous-cohort")
The output of a tparams_transprobs object is rather verbose. It can be
helpful to check the output by converting it to a data.table (containing
both the ID variables and flattened transition probability matrices)
with as.data.table.tparams_transprobs(). Transition probabilities can
also be summarized (across parameter samples) using
summary.tparams_transprobs().
hesim_dat <- hesim_data(strategies = data.frame(strategy_id = 1:2), patients = data.frame(patient_id = 1:3)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) # tpmatrix objects provide a convenient way to construct # tparams_transprobs() objects tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- runif(nrow(tpmat_id), .6, .7) + .05 * (tpmat_id$strategy_id == 2) tpmat <- tpmatrix( C, p_12, 0, 1 ) tprobs <- tparams_transprobs(tpmat, tpmat_id) names(tprobs) # Names of list elements # Convert to data.table in wide format as.data.table(tprobs) # Convert to data.table in long format as.data.table(tprobs, long = TRUE) # Summary where each column is a vector summary(tprobs) summary(tprobs, probs = c(.025, .975)) # Summary where each column is a matrix ps <- summary(tprobs, id = tpmat_id, unflatten = TRUE) ps ps$meanhesim_dat <- hesim_data(strategies = data.frame(strategy_id = 1:2), patients = data.frame(patient_id = 1:3)) input_data <- expand(hesim_dat, by = c("strategies", "patients")) # tpmatrix objects provide a convenient way to construct # tparams_transprobs() objects tpmat_id <- tpmatrix_id(input_data, n_samples = 2) p_12 <- runif(nrow(tpmat_id), .6, .7) + .05 * (tpmat_id$strategy_id == 2) tpmat <- tpmatrix( C, p_12, 0, 1 ) tprobs <- tparams_transprobs(tpmat, tpmat_id) names(tprobs) # Names of list elements # Convert to data.table in wide format as.data.table(tprobs) # Convert to data.table in long format as.data.table(tprobs, long = TRUE) # Summary where each column is a vector summary(tprobs) summary(tprobs, probs = c(.025, .975)) # Summary where each column is a matrix ps <- summary(tprobs, id = tpmat_id, unflatten = TRUE) ps ps$mean
tpmatrix() both defines and evaluates a transition probability matrix in which
elements are expressions. It can be used within define_tparams() to
create a transition probability matrix or directly to create a tparams_transprobs()
object. These are, in turn, ultimately used to create a CohortDtstmTrans object
for simulating health state transitions.
tpmatrix(..., complement = NULL, states = NULL, prefix = "", sep = "_")tpmatrix(..., complement = NULL, states = NULL, prefix = "", sep = "_")
... |
Named values of expressions defining elements of the matrix. Each
element of |
complement |
Either a character vector or a numeric vector denoting the
transitions (i.e., the columns of the tabular object formed from |
states, prefix, sep
|
Arguments passed to |
A tpmatrix is a 2-dimensional tabular object that stores flattened
square transition probability matrices in each row. Each transition probability
matrix is filled rowwise. The complementary probability (equal to
minus the sum of the probabilities of all other elements in a row of a
transition probability matrix) can be conveniently referred to as C or
specified with the complement argument. There can only be one complement
for each row in a transition probability matrix.
Returns a tpmatrix object that inherits from data.table
where each column is an element of the transition probability matrix with
elements ordered rowwise.
A tpmatrix is useful because it provides a convenient
way to construct a tparams_transprobs object, which is the object in
hesim used to specify the transition probabilities required to simulate
Markov chains with the CohortDtstmTrans class. See the
tparams_transprobs documentation for more details.
The summary.tpmatrix() method can be used to summarize a tpmatrix
across parameter samples.
p_12 <- c(.7, .6) tpmatrix( C, p_12, 0, 1 ) tpmatrix( C, p_12, C, 1 ) # Pass matrix pmat <- matrix(c(.5, .5, .3, .7), byrow = TRUE, ncol = 4) tpmatrix(pmat) # Pass vectors and data frames p1 <- data.frame( p_12 = c(.7, .6), p_13 = c(.1, .2) ) p2 <- data.frame( p_21 = 0, p_22 = c(.4, .45), p_23 = c(.6, .55) ) p3 <- data.frame( p_31 = c(0, 0), p_32 = c(0, 0), p_33 = c(1, 1) ) tpmatrix( C, p1, p2, p3 ) # Use the 'complement' argument pmat <- data.frame(s1_s1 = 0, s1_s2 = .5, s2_s1 = .3, s2_s2 = 0) tpmatrix(pmat, complement = c("s1_s1", "s2_s2")) tpmatrix(pmat, complement = c(1, 4)) # Can also pass integers # Can control column names tpmatrix(pmat, complement = c(1, 4), states = c("state1", "state2"), sep = ".")p_12 <- c(.7, .6) tpmatrix( C, p_12, 0, 1 ) tpmatrix( C, p_12, C, 1 ) # Pass matrix pmat <- matrix(c(.5, .5, .3, .7), byrow = TRUE, ncol = 4) tpmatrix(pmat) # Pass vectors and data frames p1 <- data.frame( p_12 = c(.7, .6), p_13 = c(.1, .2) ) p2 <- data.frame( p_21 = 0, p_22 = c(.4, .45), p_23 = c(.6, .55) ) p3 <- data.frame( p_31 = c(0, 0), p_32 = c(0, 0), p_33 = c(1, 1) ) tpmatrix( C, p1, p2, p3 ) # Use the 'complement' argument pmat <- data.frame(s1_s1 = 0, s1_s2 = .5, s2_s1 = .3, s2_s2 = 0) tpmatrix(pmat, complement = c("s1_s1", "s2_s2")) tpmatrix(pmat, complement = c(1, 4)) # Can also pass integers # Can control column names tpmatrix(pmat, complement = c(1, 4), states = c("state1", "state2"), sep = ".")
Creates ID variables for each row returned by tpmatrix(). This function is
most conveniently used along with tpmatrix() to construct a
tparams_transprobs() object.
tpmatrix_id(object, n_samples)tpmatrix_id(object, n_samples)
object |
An object of class |
n_samples |
The number of parameters samples used for the probabilistic sensitivity analysis (PSA). |
Returns a tpmatrix_id object that inherits from data.table with
the same columns in object repeated n_samples times. That is, to facilitate
creation of a tparams_transprobs() object, there is one row for each
parameter sample, treatment strategy, patient, and optionally time interval.
tpmatrix(), tparams_transprobs(), expand.hesim_data()
strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(65, 50, 75), gender = c("Female", "Female", "Male")) hesim_dat <- hesim_data(strategies = strategies, patients = patients) input_data <- expand(hesim_dat, by = c("strategies", "patients")) tpmatrix_id(input_data, n_samples = 2)strategies <- data.frame(strategy_id = c(1, 2)) patients <- data.frame(patient_id = seq(1, 3), age = c(65, 50, 75), gender = c("Female", "Female", "Male")) hesim_dat <- hesim_data(strategies = strategies, patients = patients) input_data <- expand(hesim_dat, by = c("strategies", "patients")) tpmatrix_id(input_data, n_samples = 2)
Create names for all elements of a transition probability matrix given
names for the health states. This is useful for flattening a transition
probability matrix (rowwise) into a vector and naming the resulting vector.
The name of an element of the flattened vector representing a transition from
the ith state to the jth state is of the form
paste0(prefix, states[i], sep, states[j]).
tpmatrix_names(states, prefix = "p_", sep = "_")tpmatrix_names(states, prefix = "p_", sep = "_")
states |
A character vector of the names of health states in the transition matrix. |
prefix |
A prefix that precedes the described transitions between states
used to name a transition. For example, if |
sep |
A character string to separate the terms representing
state |
A character vector containing a name for each element of the transition probability matrix encompassing all possible transitions.
See tpmatrix(), which uses tpmatrix_names() to name the columns
of the returned object.
tpmatrix_names(LETTERS[1:4]) tpmatrix_names(LETTERS[1:4], prefix = "") tpmatrix_names(LETTERS[1:4], prefix = "", sep = ".")tpmatrix_names(LETTERS[1:4]) tpmatrix_names(LETTERS[1:4], prefix = "") tpmatrix_names(LETTERS[1:4], prefix = "", sep = ".")