Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | 0 | 0 | 0 | 0 |
CVD | 0 | 0 | 0 | 0 |
Death_CVD | 0 | 0 | 0 | 0 |
Death_Other | 0 | 0 | 0 | 0 |
iHEA Congress, July 2023
A Novel Decision Model for Cardiovascular Disease (CVD) Prevention and Treatment in South Africa
An Adapted Decision Model for Cardiovascular Disease (CVD) Prevention and Treatment in South Africa
Statistic | Evaluates | Range | Applicable Domain |
---|---|---|---|
Rate | \(\frac{\# \text{events in time period}}{\text{Total time period experienced by all subjects followed}}\) | 0 to \(\infty\) | Rate matrix |
Probability/risk | \(\frac{\# \text{events in time period}}{\# \text{people followed for time period}}\) | 0-1 | Probability matrix |
To construct a new model OR adapt an existing one, we must work from a transition rate matrix.
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | 0 | 0 | 0 | 0 |
CVD | 0 | 0 | 0 | 0 |
Death_CVD | 0 | 0 | 0 | 0 |
Death_Other | 0 | 0 | 0 | 0 |
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | 0 | 0.05 | 0.000 | 0.006 |
CVD | 0 | 0.00 | 0.125 | 0.006 |
Death_CVD | 0 | 0.00 | 0.000 | 0.000 |
Death_Other | 0 | 0.00 | 0.000 | 0.000 |
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | -0.056 | 0.05 | 0.000 | 0.006 |
CVD | 0 | -0.131 | 0.125 | 0.006 |
Death_CVD | 0 | 0 | 0.000 | 0.000 |
Death_Other | 0 | 0 | 0.000 | 0.000 |
Suppose we want to:
“Natural History” rate matrix
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | -0.056 | 0.050 | 0.000 | 0.006 |
CVD | 0.000 | -0.131 | 0.125 | 0.006 |
Death_CVD | 0.000 | 0.000 | 0.000 | 0.000 |
Death_Other | 0.000 | 0.000 | 0.000 | 0.000 |
“Natural History” rate matrix
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | -0.056 | 0.050 | 0.000 | 0.006 |
CVD | 0.000 | -0.131 | 0.125 | 0.006 |
Death_CVD | 0.000 | 0.000 | 0.000 | 0.000 |
Death_Other | 0.000 | 0.000 | 0.000 | 0.000 |
“Strategy A” rate matrix
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | -0.056 | 0.05 | 0 | 0.006 |
CVD | 0.000 | -0.106 | 0.1 | 0.006 |
Death_CVD | 0.000 | 0 | 0 | 0.000 |
Death_Other | 0.000 | 0 | 0 | 0.000 |
\[ p = 1 - \exp(-rt) \] where \(r\) is the rate and \(t\) is the time-step.
\[ \mathbf{P} = e^{{\mathbf{R}t}} \]
\[ \mathbf{P} = e^{{\mathbf{R}t}} \]
\[ \mathbf{P} = e^{\mathbf{R}t} \]
\[ \mathbf{P} = e^{\mathbf{R}t} \]
Pros:
Embedding the transition probability matrix in this way ensures that the correct transition probabilities are calculated.
This ensures that our discrete time Markov model accurately represents the underlying continuous time process.
Cons:
Cons:
For our CVD example, the matrix exponential of the transition rate matrix yields the correct transition probability matrix:
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | 0.9455 | 0.0455 | 0.0029 | 0.0060 |
CVD | 0.0000 | 0.8772 | 0.1172 | 0.0056 |
Death_CVD | 0.0000 | 0.0000 | 1.0000 | 0.0000 |
Death_Other | 0.0000 | 0.0000 | 0.0000 | 1.0000 |
Healthy | CVD | Death_CVD | Death_Other | |
---|---|---|---|---|
Healthy | 0.946 | 0.046 | 0.003 | 0.006 |
CVD | 0.000 | 0.877 | 0.117 | 0.006 |
Death_CVD | 0.000 | 0.000 | 1.000 | 0.000 |
Death_Other | 0.000 | 0.000 | 0.000 | 1.000 |
By constructing our model using the “roots” of a transition rate matrix, we can incorporate disparate sources of information.
Facilitates country/region-specific background mortality rates.
Not all literature-based parameters operate on transition rates.
You may find that the strategies you want to model have inputs based on odds ratios, relative risks, risk differences, etc.
Statistic | Evaluates | Range | Applicable Domain |
---|---|---|---|
Rate | \(\frac{\# \text{events in time period}}{\text{Total time period experienced by all subjects followed}}\) | 0 to \(\infty\) | Rate matrix |
Hazard Ratio | \(\frac{\text{Hazard rate of outcome in exposed}}{\text{Hazard rate of outcome in unexposed}}\) | 0 to \(\infty\) | Rate matrix |
Probability/risk | \(\frac{\# \text{events in time period}}{\# \text{people followed for time period}}\) | 0-1 | Probability matrix |
Odds | \(\frac{\text{Probability of Outcome}}{1 - \text{Probability of Outcome}}\) | 0 to \(\infty\) | Probability matrix |
Odds Ratio | \(\frac{\text{Odds of outcome in exposed}}{\text{Odds of outcome in unexposed}}\) | 0 to \(\infty\) | Probability matrix |
Relative Risk | \(\frac{\text{Probability of outcome in exposed}}{\text{Probablity of outcome in unexposed}}\) | 0 to \(\infty\) | Probability matrix |
Risk Difference | \(\text{Probability of outcome in exposed}-\text{Probablity of outcome in unexposed}\) | -1 to 1 | Probability matrix |
An Adapted Decision Model for HIV Prevention and Treatment in South Africa
Transition probability matrix:
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | 0.721 | 0.202 | 0.067 | 0.010 |
LowCD4 | 0.000 | 0.581 | 0.407 | 0.012 |
AIDS | 0.000 | 0.000 | 0.750 | 0.250 |
Death | 0.000 | 0.000 | 0.000 | 1.000 |
A. Convert the supplied transition probabilities to rates one-by-one (incorrect, but will get you close if you’re lucky!).
B. Compute the matrix logarithm of the transition probability matrix \(P\).
C. Maximum likelihood-based approach.
You can always try 2+ of these methods to see how they compare.
\[ r = -ln(1-p) \]
\[ r = -ln(1-p) \]
Converted rate matrix:
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | -0.305 | 0.226 | 0.069 | 0.010 |
LowCD4 | 0.000 | -0.535 | 0.523 | 0.012 |
AIDS | 0.000 | 0.000 | -0.288 | 0.288 |
Death | 0.000 | 0.000 | 0.000 | 0.000 |
To see if this method gets us a rate matrix that is close to the generator matrix, we can use the methods discussed earlier to see if the rate matrix can recapitulate the original transition probability matrix…
Converted:
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | 0.737 | 0.149 | 0.092 | 0.022 |
LowCD4 | 0.000 | 0.586 | 0.347 | 0.067 |
AIDS | 0.000 | 0.000 | 0.750 | 0.250 |
Death | 0.000 | 0.000 | 0.000 | 1.000 |
Original:
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | 0.721 | 0.202 | 0.067 | 0.010 |
LowCD4 | 0.000 | 0.581 | 0.407 | 0.012 |
AIDS | 0.000 | 0.000 | 0.750 | 0.250 |
Death | 0.000 | 0.000 | 0.000 | 1.000 |
Converted:
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | 0.737 | 0.149 | 0.092 | 0.022 |
LowCD4 | 0.000 | 0.586 | 0.347 | 0.067 |
AIDS | 0.000 | 0.000 | 0.750 | 0.250 |
Death | 0.000 | 0.000 | 0.000 | 1.000 |
Original:
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | 0.721 | 0.202 | 0.067 | 0.010 |
LowCD4 | 0.000 | 0.581 | 0.407 | 0.012 |
AIDS | 0.000 | 0.000 | 0.750 | 0.250 |
Death | 0.000 | 0.000 | 0.000 | 1.000 |
Not great …
\[ R = \log P \]
\[A' = V^{-1} A V\]
\[A' = V^{-1} A V\]
\[\log P = V (\log A') V^{-1}\]
# read the transition probability matrix as stored in an
# excel file
mP <- readxl::read_xlsx("path-excel-file.xls")
# eigenvalue decomposition
V <- eigen(mP)$vectors
iV <- solve(V)
Ap <- iV %*% mP %*% V
lAp <- diag(log(diag(Ap)), nrow(Ap), ncol(Ap))
R <- V %*% lAp %*% iV
R[abs(R) < 1e-6 ] <- 0
dimnames(R) = dimnames(mP)
round(R,3)
V <- eigen(mP)$vectors
iV <- solve(V)
Ap <- iV %*% mP %*% V
lAp <- diag(log(diag(Ap)), nrow(Ap), ncol(Ap))
R <- V %*% lAp %*% iV
R[abs(R) < 1e-6 ] <- 0
dimnames(R) = dimnames(mP)
round(R,3)
Healthy LowCD4 AIDS Death
Healthy -0.327 0.311 0.002 0.013
LowCD4 0.000 -0.543 0.615 -0.072
AIDS 0.000 0.000 -0.288 0.288
Death 0.000 0.000 0.000 0.000
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | -0.327 | 0.311 | 0.002 | 0.013 |
LowCD4 | 0 | -0.543 | 0.615 | -0.072 |
AIDS | 0 | 0 | -0.288 | 0.288 |
Death | 0 | 0 | 0 | 0 |
Healthy | LowCD4 | AIDS | Death | |
---|---|---|---|---|
Healthy | -0.327 | 0.311 | 0.002 | 0.013 |
LowCD4 | 0 | -0.543 | 0.615 | -0.072 |
AIDS | 0 | 0 | -0.288 | 0.288 |
Death | 0 | 0 | 0 | 0 |
expm::logm
Higham (2008) method returns same as eigenvalue method.expm::logm()
Healthy LowCD4 AIDS Death
Healthy -0.327 0.311 0.002 0.013
LowCD4 0.000 -0.543 0.615 -0.072
AIDS 0.000 0.000 -0.288 0.288
Death 0.000 0.000 0.000 0.000
Steps:
tr0 <- # Initial state occupancy.
c("Healthy" = 1000,"LowCD4" = 0, "AIDS" = 0, "Death" = 0)
tr1 <- # State occupancy after one cycle.
tr0 %*% mP
tr <- # Bind together into a data frame.
rbind.data.frame(tr0, tr1) %>%
mutate(cycle = c(0, 1)) %>%
select(cycle,everything())
tr
cycle Healthy LowCD4 AIDS Death
1 0 1000 0 0 0
2 1 721 202 67 10
Healthy
state.Healthy
while 202 are in LowCD4
, etc.tr <-
rbind.data.frame(tr0, tr1) %>%
mutate(cycle = c(0, 1)) %>%
gather(state,count,-cycle) %>%
mutate(count = round(count,0)) %>%
arrange(cycle) %>%
lapply(.,rep,.$count) %>%
cbind.data.frame() %>%
as_tibble() %>%
mutate(state = factor(state,
levels = c("Healthy","LowCD4","AIDS","Death"))) %>%
arrange(cycle,state) %>%
mutate(ptnum = rep(1:1000,2)) %>%
select(-count) %>%
arrange(ptnum,cycle) %>%
mutate(state = as.numeric(state)) %>%
select(ptnum,cycle,state)
# A tibble: 2,000 × 3
ptnum cycle state
<int> <dbl> <dbl>
1 1 0 1
2 1 1 1
3 2 0 1
4 2 1 1
5 3 0 1
6 3 1 1
7 4 0 1
8 4 1 1
9 5 0 1
10 5 1 1
# ℹ 1,990 more rows
logm(mP)
.
Call:
msm(formula = state ~ cycle, subject = ptnum, data = tr, qmatrix = Q.init)
Maximum likelihood estimates
Transition intensities
Baseline
Healthy - Healthy -0.32712 ( -3.680e-01, -2.907e-01)
Healthy - LowCD4 0.32702 ( 1.354e-01, 7.898e-01)
Healthy - Death 0.00010 ( 0.000e+00, Inf)
LowCD4 - LowCD4 -0.64477 ( -1.139e+01, -3.650e-02)
LowCD4 - AIDS 0.63465 ( 9.115e-06, 4.419e+04)
LowCD4 - Death 0.01012 ( 8.238e-299, 1.242e+294)
AIDS - AIDS -0.34837 ( -3.805e+40, -3.189e-42)
AIDS - Death 0.34837 ( 3.189e-42, 3.805e+40)
-2 * log-likelihood: 1572.2
Multistate-Model:
Healthy LowCD4 AIDS Death
[1,] 721 202 67 10
Healthy LowCD4 AIDS Death
[1,] 721 202 67 10
log
numerically unstable converting from probability to rate.Multistate-Model:
With a reasonable generator matrix defined, we can now augment the model as we see fit:
Once done with the above, just embed the new matrix.
Back to Website \(\quad \quad\) Download PDF