THR-MCPSA.R 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. library(tidyverse)
  2. set.seed(13470)
  3. N_PSA <- 20000
  4. revision_risk_coef <- c(-5.490935, -0.0367022, +0.768536, -1.344474, +0.3740968)
  5. revision_risk_var <- matrix(c(+4.32191e-2, -7.83e-4, -7.247e-3, -6.42e-4, -5.691e-3,
  6. -7.83e-4, +2.71566e-5, +3.3e-5, -1.1e-4, +2.8e-8,
  7. -7.247e-3, +3.3e-5, +1.18954e-2, +1.84e-4, +5.1e-6,
  8. -6.42e-4, -1.11e-4, +1.84e-4, +1.46369e-1, +2.59e-4,
  9. -5.691e-3, +2.8e-8, +5.1e-6, +2.59e-4, +2.25151e-3),
  10. 5, 5)
  11. revision_risk_psa <- MASS::mvrnorm(N_PSA, mu = revision_risk_coef, Sigma = revision_risk_var)
  12. params <- tibble(
  13. beta_0 = revision_risk_psa[, 1],
  14. beta_age = revision_risk_psa[, 2],
  15. beta_male = revision_risk_psa[, 3],
  16. beta_NP1 = revision_risk_psa[, 4],
  17. ln_gamma = revision_risk_psa[, 5],
  18. phi = rbeta(N_PSA, 2, 98),
  19. psi = rbeta(N_PSA, 2, 98),
  20. rho = rbeta(N_PSA, 4, 96),
  21. C = rgamma(N_PSA, shape = 12.6749407, scale = 417.6745372),
  22. U_SuccessP = rbeta(N_PSA, 119.566667, 21.1),
  23. U_SuccessR = rbeta(N_PSA, 87.140625, 29.046875),
  24. U_Revision = rbeta(N_PSA, 69.7, 162.633333)
  25. )
  26. state_labels <- c("Standard_SuccessP", "Standard_Revision", "Standard_SuccessR", "Standard_Death",
  27. "NP1_SuccessP", "NP1_Revision", "NP1_SuccessR", "NP1_Death")
  28. cycle_labels <- 1:60
  29. output_labels <- c("Standard_Costs", "Standard_QALYs", "NP1_Costs", "NP1_QALYs", "Incremental_Costs", "Incremental_QALYs")
  30. param_labels <- c("beta_0", "beta_age", "beta_male", "beta_NP1", "ln_gamma", "logit_phi", "logit_psi", "logit_rho", "ln_C", "logit_U_SuccessP", "logit_U_SuccessR", "logit_U_Revision")
  31. age <- 60
  32. male <- 0
  33. mortality <- function(age, male) {
  34. if (male) {
  35. if (age < 45) 0.00151
  36. else if (age < 55) 0.00393
  37. else if (age < 65) 0.0109
  38. else if (age < 75) 0.0316
  39. else if (age < 85) 0.0801
  40. else 0.1879
  41. } else {
  42. if (age < 45) 0.00099
  43. else if (age < 55) 0.0026
  44. else if (age < 65) 0.0067
  45. else if (age < 75) 0.0193
  46. else if (age < 85) 0.0535
  47. else 0.1548
  48. }
  49. }
  50. logit <- function(p) log(p) - log(1 - p)
  51. expit <- function(x) 1 / (1 + exp(-x))
  52. runPSA <- function(...) {
  53. theta <- flatten_dbl(rlang::list2(...))
  54. x <- array(0, dim = c(8, 60), dimnames = list(state = state_labels, cycle = cycle_labels))
  55. P <- array(0, dim = c(8, 8, 60), dimnames = list(state_from = state_labels, state_to = state_labels, cycle = cycle_labels))
  56. V <- array(0, dim = c(8, 6, 60), dimnames = list(state = state_labels, output = output_labels, cycle = cycle_labels))
  57. gt <- array(NA_real_, dim = c(6, 60), dimnames = list(output = output_labels, cycle = cycle_labels))
  58. # INITIAL STATE DISTRIBUTION
  59. x[4, 1] <- theta[6]
  60. x[1, 1] <- 1 - x[4, 1]
  61. x[8, 1] <- theta[6]
  62. x[5, 1] <- 1 - x[8, 1]
  63. # TRANSITION MATRIX
  64. P[4, 4, ] <- 1
  65. P[8, 8, ] <- 1
  66. for (t in 1:60) {
  67. rt_Standard <- 1 - exp(exp(theta[1] + theta[2] * age + theta[3] * male) * ((t - 1)^exp(theta[5]) - t^exp(theta[5])))
  68. rt_NP1 <- 1 - exp(exp(theta[1] + theta[2] * age + theta[3] * male + theta[4]) * ((t - 1)^exp(theta[5]) - t^exp(theta[5])))
  69. P[1, 2, t] <- rt_Standard
  70. P[5, 6, t] <- rt_NP1
  71. P[1, 4, t] <- mortality(age + t, male)
  72. P[2, 4, t] <- mortality(age + t, male) + theta[7]
  73. P[3, 4, t] <- mortality(age + t, male)
  74. P[5, 8, t] <- mortality(age + t, male)
  75. P[6, 8, t] <- mortality(age + t, male) + theta[7]
  76. P[7, 8, t] <- mortality(age + t, male)
  77. P[3, 2, t] <- theta[8]
  78. P[7, 6, t] <- theta[8]
  79. P[1, 1, t] <- 1 - P[1, 2, t] - P[1, 4, t]
  80. P[2, 3, t] <- 1 - P[2, 4, t]
  81. P[3, 3, t] <- 1 - P[3, 2, t] - P[3, 4, t]
  82. P[5, 5, t] <- 1 - P[5, 6, t] - P[5, 8, t]
  83. P[6, 7, t] <- 1 - P[6, 8, t]
  84. P[7, 7, t] <- 1 - P[7, 6, t] - P[7, 8, t]
  85. }
  86. # VALUE MATRIX
  87. V_base <- matrix(0, 8, 6)
  88. V_base[2, 1] <- theta[9]
  89. V_base[2, 5] <- -theta[9]
  90. V_base[6, c(3, 5)] <- theta[9]
  91. V_base[1, 2] <- theta[10]
  92. V_base[1, 6] <- -theta[10]
  93. V_base[5, 4] <- theta[10]
  94. V_base[5, 6] <- theta[10]
  95. V_base[3, 2] <- theta[11]
  96. V_base[3, 6] <- -theta[11]
  97. V_base[7, 4] <- theta[11]
  98. V_base[7, 6] <- theta[11]
  99. V_base[2, 2] <- theta[12]
  100. V_base[2, 6] <- -theta[12]
  101. V_base[6, 4] <- theta[12]
  102. V_base[6, 6] <- theta[12]
  103. for (t in 0:59) {
  104. V[, , t+1] <- V_base %*% diag(rep(c(1.06^(-t), 1.015^(-t)), 3), 6, 6)
  105. }
  106. # STANDARD MARKOV COHORT SIMULATION
  107. g0 <- c(394, 0, 579, 0, 579 - 394, 0)
  108. gt[, 1] <- t(V[, , 1]) %*% x[, 1]
  109. for (t in 2:60) {
  110. x[, t] <- t(P[, , t-1]) %*% x[, t-1]
  111. gt[, t] <- t(V[, , t]) %*% x[, t]
  112. }
  113. g <- g0 + rowSums(gt)
  114. # RESULTS
  115. as.list(g)
  116. }
  117. g_psa <- pmap_dfr(params, runPSA)
  118. saveRDS(g_psa, "THR-MCPSA.rds")