Rates, Probabilities, and Embedding
params =
list(
t_names = c("natural_history"), # Strategy names.
n_treatments = 1, # Number of treatments
s_names = c("Healthy", "CVD"), # State names
n_states = 2, # Number of states
n_cohort = 1, # Cohort size
n_cycles = 100, # Number of cycles in model.
cycle = 1, # Cycle length
initial_age = 55, # Cohort starting age
r_H_CVD = 0.15 # Rate of healthy -> CVD
)
We’ll next construct a transition probability matrix using the standard rate-to-probability conversion formula:
\[ p = 1 - \exp(-rt) \] where \(r\) is the rate, \(t\) is the time-step (e.g., 1 for annual, 1/12 for monthly, etc.).
$natural_history
to
from Healthy CVD
Healthy 0.86071 0.13929
CVD 0.00000 1.00000
sim_cohort(params)
is a function that constructs a Markov trace from the supplied parameters.The markov trace tells us the fraction of the population in each state in any cycle:
Healthy | CVD |
---|---|
740.82 | 259.18 |
1payoff_life_exp = c("Healthy" = 1, "CVD" = 1)
2life_exp_cycle = trace[-1,] %*% payoff_life_exp
3total_life_exp = sum(life_exp_cycle)
$natural_history
to
from Healthy CVD
Healthy 0.99959 0.00041087
CVD 0.00000 1.00000000
Healthy | CVD |
---|---|
740.82 | 259.18 |
params_mort =
list(
t_names = c("natural_history"), # Strategy names.
n_treatments = 1, # Number of treatments
s_names = c("Healthy", "CVD", "Dead"), # State names
n_states = 3, # Number of states
n_cohort = 1, # Cohort size
n_cycles = 100, # Number of cycles in model.
cycle = 1, # Cycle length
initial_age = 55, # Cohort starting age
r_H_CVD = 0.15, # Rate of healthy -> CVD
hr_CVD = 10, # Hazard Ratio: CVD Death
r_H_D = 0.01 # Rate of healthy -> dead
)
params_mort$mP <-
with(params_mort,{
tp_H_CVD = 1 - exp(-r_H_CVD * cycle)
tp_H_D = 1 - exp(-r_H_D * cycle)
tp_CVD_D <- 1 - exp(-(hr_CVD * r_H_D) * cycle)
array(data = c(1 - tp_H_CVD - tp_H_D, 0, 0,
tp_H_CVD,1-tp_CVD_D, 0,
tp_H_D, tp_CVD_D, 1),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
})
$natural_history
to
from Healthy CVD Dead
Healthy 0.85076 0.13929 0.0099502
CVD 0.00000 0.90484 0.0951626
Dead 0.00000 0.00000 1.0000000
Healthy | CVD | Dead |
---|---|---|
723.8 | 244.5 | 31.7 |
params_mort_daily$mP <-
with(params_mort_daily,{
tp_H_CVD = 1 - exp(-r_H_CVD * cycle)
tp_H_D = 1 - exp(-r_H_D * cycle)
tp_CVD_D <- 1 - exp(-(hr_CVD * r_H_D) * cycle)
array(data = c(1 - tp_H_CVD - tp_H_D, 0, 0,
tp_H_CVD,1-tp_CVD_D, 0,
tp_H_D, tp_CVD_D, 1),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
})
$natural_history
to
from Healthy CVD Dead
Healthy 0.99956 0.00041087 0.000027397
CVD 0.00000 0.99972606 0.000273935
Dead 0.00000 0.00000000 1.000000000
Healthy | CVD | Dead |
---|---|---|
726.1 | 231.5 | 42.4 |
In the presence of competing events (mortality), we obtain different results for different cycle lengths!
In the presence of competing events (mortality), we obtain different results for different cycle lengths!
Model With No Mortality | Model With Mortality | |||
---|---|---|---|---|
Yearly Cycle | Daily Cycle | Yearly Cycle | Daily Cycle | |
1. CVD State Occupancy at Two Years | 259.18 | 259.18 | 244.540 | 231.488 |
2. Life Expectancy | 100.00 | 100.00 | 15.507 | 15.624 |
In the presence of competing events (mortality), we obtain different results for different cycle lengths! Notice how the state occupancy in CVD differs in the right panel of the figure below.
params_mort2$mP <-
with(params_mort2,{
tp_H_CVD = 1 - exp(-r_H_CVD * cycle)
tp_H_D = 1 - exp(-r_H_D * cycle)
tp_CVD_D <- 1 - exp(-(hr_CVD * r_H_D) * cycle)
array(data = c(1 - tp_H_CVD - tp_H_D, 0, 0,0,
tp_H_CVD,1-tp_CVD_D, 0,0,
0,tp_CVD_D,1,0,
tp_H_D, 0,0, 1),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
})
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.85076 0.13929 0.000000 0.0099502
CVD 0.00000 0.90484 0.095163 0.0000000
CVDDeath 0.00000 0.00000 1.000000 0.0000000
Dead 0.00000 0.00000 0.000000 1.0000000
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.85076 0.13929 0.000000 0.0099502
CVD 0.00000 0.90484 0.095163 0.0000000
CVDDeath 0.00000 0.00000 1.000000 0.0000000
Dead 0.00000 0.00000 0.000000 1.0000000
Recall that in this model, CVD has a very high death rate—meaning that many people who develop CVD will die very soon after.
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.85076 0.13929 0.000000 0.0099502
CVD 0.00000 0.90484 0.095163 0.0000000
CVDDeath 0.00000 0.00000 1.000000 0.0000000
Dead 0.00000 0.00000 0.000000 1.0000000
Recall that in this model, CVD has a very high death rate—meaning that many people who develop CVD will die very soon after.
With this knowledge in mind, can you spot something wrong with the above (annual) transition matrix?
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.12797 0.77687 0.00000 0.095163
CVD 0.00000 0.36788 0.63212 0.000000
CVDDeath 0.00000 0.00000 1.00000 0.000000
Dead 0.00000 0.00000 0.00000 1.000000
Recall that in this model, CVD has a very high death rate—meaning that many people who develop CVD will die very soon after.
With this knowledge in mind, can you spot something wrong with the above (annual) transition matrix?
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.12797 0.77687 0.00000 0.095163
CVD 0.00000 0.36788 0.63212 0.000000
CVDDeath 0.00000 0.00000 1.00000 0.000000
Dead 0.00000 0.00000 0.00000 1.000000
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.12797 0.77687 0.00000 0.095163
CVD 0.00000 0.36788 0.63212 0.000000
CVDDeath 0.00000 0.00000 1.00000 0.000000
Dead 0.00000 0.00000 0.00000 1.000000
That is, \(p_{H,CVD}= 1 - \exp(-r_{H,CVD} t)\) captures the probability of following scenarios occurring in a cycle:
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.12797 0.77687 0.00000 0.095163
CVD 0.00000 0.36788 0.63212 0.000000
CVDDeath 0.00000 0.00000 1.00000 0.000000
Dead 0.00000 0.00000 0.00000 1.000000
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.12797 0.77687 0.00000 0.095163
CVD 0.00000 0.36788 0.63212 0.000000
CVDDeath 0.00000 0.00000 1.00000 0.000000
Dead 0.00000 0.00000 0.00000 1.000000
$natural_history
to
from Healthy CVD Dead
Healthy 0.12797 0.77687 0.095163
CVD 0.00000 0.36788 0.632121
Dead 0.00000 0.00000 1.000000
$natural_history
to
from Healthy CVD CVDDeath Dead
Healthy 0.12797 0.77687 0.00000 0.095163
CVD 0.00000 0.36788 0.63212 0.000000
CVDDeath 0.00000 0.00000 1.00000 0.000000
Dead 0.00000 0.00000 0.00000 1.000000
Changing to shorter cycle does not get us out of this problem.
\[f(\theta_A) + \epsilon_A - (f(\theta_{B}) + \epsilon_{B})\]
If \(\epsilon_A - \epsilon_{B} \sim 0\) the impact to the decision threshold is minimal.
In the presence of competing events (mortality), using standard conversion formulas will yield incorrect transition probability matrices.
The amount of error for a decision threshold is the difference in contour. In this example: \(0.07 - 0.02 = 0.05\).
Discrete Event Simulation automatically handles competing events.
Microsimulation misspecification error interacts with the discrete time step truncation and increases this error!
Published rates from clinical studies are usually adjusted for competing events (the purpose of survival studies).
Rather than use the conversion formulas, we need to properly “embed” the transition probability matrix.
The correct transition probability matrix should include a seemingly impossible transition: Healthy CVDDeath
Rather than use the conversion formulas, we need to properly “embed” the transition probability matrix.
The correct transition probability matrix should include a seemingly impossible transition: Healthy CVDDeath
Healthy CVD CVDDeath Dead
Healthy 0.202 0.415 0.333 0.05
CVD 0.000 0.368 0.632 0.00
CVDDeath 0.000 0.000 1.000 0.00
Dead 0.000 0.000 0.000 1.00
This process will ensure that the matrix captures “jumpover” states for compound transitions!
This process will ensure that the matrix captures “jumpover” states for compound transitions!
It also ensures that changing cycle lengths will not change your answers!
params_mort_embedded$mR <-
with(params_mort2_emb,{
r_CVD_D <- hr_CVD * r_H_D
R_ <-
array(data = c(0, 0, 0,0,
r_H_CVD,0, 0,0,
0,r_CVD_D,0,0,
r_H_D, 0,0, 0),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
R <- apply(R_,3, simplify=FALSE,function(x) {
diag(x) = -rowSums(x)
x * cycle
})
R
})
params_mort_embedded$mR <-
with(params_mort2_emb,{
r_CVD_D <- hr_CVD * r_H_D
R_ <-
array(data = c(0, 0, 0,0,
r_H_CVD,0, 0,0,
0,r_CVD_D,0,0,
r_H_D, 0,0, 0),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
R <- apply(R_,3, simplify=FALSE,function(x) {
diag(x) = -rowSums(x)
x * cycle
})
R
})
params_mort_embedded$mR <-
with(params_mort2_emb,{
r_CVD_D <- hr_CVD * r_H_D
R_ <-
array(data = c(0, 0, 0,0,
r_H_CVD,0, 0,0,
0,r_CVD_D,0,0,
r_H_D, 0,0, 0),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
R <- apply(R_,3, simplify=FALSE,function(x) {
diag(x) = -rowSums(x)
x * cycle
})
R
})
params_mort_embedded$mR <-
with(params_mort2_emb,{
r_CVD_D <- hr_CVD * r_H_D
R_ <-
array(data = c(0, 0, 0,0,
r_H_CVD,0, 0,0,
0,r_CVD_D,0,0,
r_H_D, 0,0, 0),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
R <- apply(R_,3, simplify=FALSE,function(x) {
diag(x) = -rowSums(x)
x * cycle
})
R
})
params_mort_embedded$mR <-
with(params_mort2_emb,{
r_CVD_D <- hr_CVD * r_H_D
R_ <-
array(data = c(0, 0, 0,0,
r_H_CVD,0, 0,0,
0,r_CVD_D,0,0,
r_H_D, 0,0, 0),
dim = c(n_states, n_states, n_treatments),
dimnames = list(from = s_names,
to = s_names,
t_names))
R <- apply(R_,3, simplify=FALSE,function(x) {
diag(x) = -rowSums(x)
x * cycle
})
R
})
Healthy CVD CVDDeath Dead
Healthy 0.85214 0.13173 0.0068811 0.009241
CVD 0.00000 0.90484 0.0951626 0.000000
CVDDeath 0.00000 0.00000 1.0000000 0.000000
Dead 0.00000 0.00000 0.0000000 1.000000
to
from Healthy CVD CVDDeath Dead
Healthy 0.851 0.139 0.000 0.01
CVD 0.000 0.905 0.095 0.00
CVDDeath 0.000 0.000 1.000 0.00
Dead 0.000 0.000 0.000 1.00
Healthy CVD CVDDeath Dead
Healthy 0.852 0.132 0.007 0.009
CVD 0.000 0.905 0.095 0.000
CVDDeath 0.000 0.000 1.000 0.000
Dead 0.000 0.000 0.000 1.000