THR-deltaPSA.R 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. library(tidyverse)
  2. library(here)
  3. # optim(par = c(0, 1),
  4. # fn = function(params, beta_shape1, beta_shape2) {
  5. # a <- beta_shape1
  6. # b <- beta_shape2
  7. # beta_mean <- a / (a + b)
  8. # beta_var <- a * b / ((a + b) ^ 2 * (a + b + 1))
  9. # moments <- logitnorm::momentsLogitnorm(params[1], params[2])
  10. # (moments[1] - beta_mean) ^ 2 + (moments[2] - beta_var) ^ 2
  11. # },
  12. # beta_shape1 = 69.7,
  13. # beta_shape2 = 162.633333,
  14. # method = "BFGS")
  15. theta_mean <- c(-5.490935,
  16. -0.0367022,
  17. 0.768536,
  18. -1.344474,
  19. 0.3740968,
  20. -4.0944849,
  21. -4.0944849,
  22. -3.2869827,
  23. log(5294^2 / sqrt(1487 ^ 2 + 5294 ^ 2)),
  24. 1.753857,
  25. 1.1100567,
  26. -0.8513930)
  27. theta_var <- matrix(0, 12, 12)
  28. theta_var[1:5,1:5] <- c(+4.32191e-2, -7.83e-4, -7.247e-3, -6.42e-4, -5.691e-3,
  29. -7.83e-4, +2.71566e-5, +3.3e-5, -1.1e-4, +2.8e-8,
  30. -7.247e-3, +3.3e-5, +1.18954e-2, +1.84e-4, +5.1e-6,
  31. -6.42e-4, -1.11e-4, +1.84e-4, +1.46369e-1, +2.59e-4,
  32. -5.691e-3, +2.8e-8, +5.1e-6, +2.59e-4, +2.25151e-3)
  33. theta_var[6,6] <- 0.6527744^2
  34. theta_var[7,7] <- 0.6527744^2
  35. theta_var[8,8] <- 0.4889407^2
  36. theta_var[9,9] <- log(1487^2/5294^2 + 1)
  37. theta_var[10,10] <- 0.235360^2
  38. theta_var[11,11] <- 0.2147719^2
  39. theta_var[12,12] <- 0.1433964^2
  40. # ggplot(tibble(x = c(0, 0.2)), aes(x)) +
  41. # stat_function(aes(colour = "Beta(4, 96)"), fun = dbeta, args = list(shape1 = 4, shape2 = 96)) +
  42. # stat_function(aes(colour = "LogitN(-3.29, 0.49)"), fun = logitnorm::dlogitnorm, args = list(mu = -3.2869827, sigma = 0.4889407)) +
  43. # labs(x = "Re-revision risk", y = "Probability density function", colour = NULL) +
  44. # theme_bw()
  45. # ggsave(filename = "logitnormal-approx.png", width = 20.28, height = 10.62, units = "cm", scale = 0.8)
  46. #
  47. #
  48. # ggplot(tibble(x = c(0, 20000)), aes(x)) +
  49. # stat_function(aes(colour = "Gamma(12.67, 417.67)"), fun = dgamma, args = list(shape = 12.67, scale = 417.67)) +
  50. # stat_function(aes(colour = "LogN(8.54, 0.28)"), fun = dlnorm, args = list(meanlog = 8.53636, sdlog = 0.2755688)) +
  51. # labs(x = "Cost of revision THR", y = "Probability density function", colour = NULL) +
  52. # theme_bw()
  53. # ggsave(filename = "lognormal-approx.png", width = 20.28, height = 10.62, units = "cm", scale = 0.8)
  54. state_labels <- c("Standard_SuccessP", "Standard_Revision", "Standard_SuccessR", "Standard_Death",
  55. "NP1_SuccessP", "NP1_Revision", "NP1_SuccessR", "NP1_Death")
  56. cycle_labels <- 1:60
  57. output_labels <- c("Standard_Costs", "Standard_QALYs", "NP1_Costs", "NP1_QALYs", "Incremental_Costs", "Incremental_QALYs")
  58. 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")
  59. names(theta_mean) <- param_labels
  60. dimnames(theta_var) <- list(theta_i = param_labels, theta_j = param_labels)
  61. age <- 60
  62. male <- 0
  63. mortality <- function(age, male) {
  64. if (male) {
  65. if (age < 45) 0.00151
  66. else if (age < 55) 0.00393
  67. else if (age < 65) 0.0109
  68. else if (age < 75) 0.0316
  69. else if (age < 85) 0.0801
  70. else 0.1879
  71. } else {
  72. if (age < 45) 0.00099
  73. else if (age < 55) 0.0026
  74. else if (age < 65) 0.0067
  75. else if (age < 75) 0.0193
  76. else if (age < 85) 0.0535
  77. else 0.1548
  78. }
  79. }
  80. logit <- function(p) log(p) - log(1 - p)
  81. expit <- function(x) 1 / (1 + exp(-x))
  82. x <- array(0, dim = c(8, 60), dimnames = list(state = state_labels, cycle = cycle_labels))
  83. P <- array(0, dim = c(8, 8, 60), dimnames = list(state_from = state_labels, state_to = state_labels, cycle = cycle_labels))
  84. V <- array(0, dim = c(8, 6, 60), dimnames = list(state = state_labels, output = output_labels, cycle = cycle_labels))
  85. gt <- array(NA_real_, dim = c(6, 60), dimnames = list(output = output_labels, cycle = cycle_labels))
  86. dx <- array(0, dim = c(8, 60, 12), dimnames = list(state = state_labels, cycle = cycle_labels, theta_i = param_labels))
  87. d2x <- array(0, dim = c(8, 60, 12, 12), dimnames = list(state = state_labels, cycle = cycle_labels, theta_i = param_labels, theta_j = param_labels))
  88. dP <- array(0, dim = c(8, 8, 60, 12), dimnames = list(state_from = state_labels, state_to = state_labels, cycle = cycle_labels, theta_i = param_labels))
  89. d2P <- array(0, dim = c(8, 8, 60, 12, 12), dimnames = list(state_from = state_labels, state_to = state_labels, cycle = cycle_labels, theta_i = param_labels, theta_j = param_labels))
  90. dV <- array(0, dim = c(8, 6, 60, 12), dimnames = list(state = state_labels, output = output_labels, cycle = cycle_labels, theta_i = param_labels))
  91. d2V <- array(0, dim = c(8, 6, 60, 12, 12), dimnames = list(state = state_labels, output = output_labels, cycle = cycle_labels, theta_i = param_labels, theta_j = param_labels))
  92. dgt <- array(NA_real_, dim = c(6, 60, 12), dimnames = list(output = output_labels, cycle = cycle_labels, theta_i = param_labels))
  93. d2gt <- array(NA_real_, dim = c(6, 60, 12, 12), dimnames = list(output = output_labels, cycle = cycle_labels, theta_i = param_labels, theta_j = param_labels))
  94. # INITIAL STATE DISTRIBUTION
  95. x[4, 1] <- expit(theta_mean[6])
  96. x[1, 1] <- 1 - x[4, 1]
  97. x[8, 1] <- expit(theta_mean[6])
  98. x[5, 1] <- 1 - x[8, 1]
  99. # TRANSITION MATRIX
  100. P[4, 4, ] <- 1
  101. P[8, 8, ] <- 1
  102. for (t in 1:60) {
  103. rt_Standard <- 1 - exp(exp(theta_mean[1] + theta_mean[2] * age + theta_mean[3] * male) * ((t - 1)^exp(theta_mean[5]) - t^exp(theta_mean[5])))
  104. rt_NP1 <- 1 - exp(exp(theta_mean[1] + theta_mean[2] * age + theta_mean[3] * male + theta_mean[4]) * ((t - 1)^exp(theta_mean[5]) - t^exp(theta_mean[5])))
  105. P[1, 2, t] <- rt_Standard
  106. P[5, 6, t] <- rt_NP1
  107. P[1, 4, t] <- mortality(age + t, male)
  108. P[2, 4, t] <- mortality(age + t, male) + expit(theta_mean[7])
  109. P[3, 4, t] <- mortality(age + t, male)
  110. P[5, 8, t] <- mortality(age + t, male)
  111. P[6, 8, t] <- mortality(age + t, male) + expit(theta_mean[7])
  112. P[7, 8, t] <- mortality(age + t, male)
  113. P[3, 2, t] <- expit(theta_mean[8])
  114. P[7, 6, t] <- expit(theta_mean[8])
  115. P[1, 1, t] <- 1 - P[1, 2, t] - P[1, 4, t]
  116. P[2, 3, t] <- 1 - P[2, 4, t]
  117. P[3, 3, t] <- 1 - P[3, 2, t] - P[3, 4, t]
  118. P[5, 5, t] <- 1 - P[5, 6, t] - P[5, 8, t]
  119. P[6, 7, t] <- 1 - P[6, 8, t]
  120. P[7, 7, t] <- 1 - P[7, 6, t] - P[7, 8, t]
  121. }
  122. # VALUE MATRIX
  123. V_base <- matrix(0, 8, 6)
  124. V_base[2, 1] <- exp(theta_mean[9])
  125. V_base[2, 5] <- -exp(theta_mean[9])
  126. V_base[6, c(3, 5)] <- exp(theta_mean[9])
  127. V_base[1, 2] <- expit(theta_mean[10])
  128. V_base[1, 6] <- -expit(theta_mean[10])
  129. V_base[5, 4] <- expit(theta_mean[10])
  130. V_base[5, 6] <- expit(theta_mean[10])
  131. V_base[3, 2] <- expit(theta_mean[11])
  132. V_base[3, 6] <- -expit(theta_mean[11])
  133. V_base[7, 4] <- expit(theta_mean[11])
  134. V_base[7, 6] <- expit(theta_mean[11])
  135. V_base[2, 2] <- expit(theta_mean[12])
  136. V_base[2, 6] <- -expit(theta_mean[12])
  137. V_base[6, 4] <- expit(theta_mean[12])
  138. V_base[6, 6] <- expit(theta_mean[12])
  139. for (t in 1:60) {
  140. V[, , t] <- V_base %*% diag(rep(c(1.06^(-t), 1.015^(-t)), 3), 6, 6)
  141. }
  142. # STANDARD MARKOV COHORT SIMULATION
  143. g0 <- c(394, 0, 579, 0, 579 - 394, 0)
  144. gt[, 1] <- t(V[, , 1]) %*% x[, 1]
  145. for (t in 2:60) {
  146. x[, t] <- t(P[, , t-1]) %*% x[, t-1]
  147. gt[, t] <- t(V[, , t]) %*% x[, t]
  148. }
  149. g <- g0 + rowSums(gt)
  150. # DELTA METHOD
  151. # - Transition matrix (use symbolic differentiation, but exclude mortality as constant)
  152. P11 <- expression(exp(exp(theta1 + theta2 * age + theta3 * male) * ((t - 1)^exp(theta5) - t^exp(theta5))))
  153. P12 <- expression(1 - exp(exp(theta1 + theta2 * age + theta3 * male) * ((t - 1)^exp(theta5) - t^exp(theta5))))
  154. P23 <- expression(1 - 1/(1+exp(-theta7)))
  155. P24 <- expression(1/(1+exp(-theta7)))
  156. P32 <- expression(1/(1+exp(-theta8)))
  157. P33 <- expression(1 - 1/(1+exp(-theta8)))
  158. P55 <- expression(exp(exp(theta1 + theta2 * age + theta3 * male + theta4) * ((t - 1)^exp(theta5) - t^exp(theta5))))
  159. P56 <- expression(1 - exp(exp(theta1 + theta2 * age + theta3 * male + theta4) * ((t - 1)^exp(theta5) - t^exp(theta5))))
  160. P67 <- expression(1 - 1/(1+exp(-theta7)))
  161. P68 <- expression(1/(1+exp(-theta7)))
  162. P76 <- expression(1/(1+exp(-theta8)))
  163. P77 <- expression(1 - 1/(1+exp(-theta8)))
  164. dP11 <- deriv3(P11, paste0("theta", 1:12))
  165. dP12 <- deriv3(P12, paste0("theta", 1:12))
  166. dP23 <- deriv3(P23, paste0("theta", 1:12))
  167. dP24 <- deriv3(P24, paste0("theta", 1:12))
  168. dP32 <- deriv3(P32, paste0("theta", 1:12))
  169. dP33 <- deriv3(P33, paste0("theta", 1:12))
  170. dP55 <- deriv3(P55, paste0("theta", 1:12))
  171. dP56 <- deriv3(P56, paste0("theta", 1:12))
  172. dP67 <- deriv3(P67, paste0("theta", 1:12))
  173. dP68 <- deriv3(P68, paste0("theta", 1:12))
  174. dP76 <- deriv3(P76, paste0("theta", 1:12))
  175. dP77 <- deriv3(P77, paste0("theta", 1:12))
  176. param_list <- set_names(as.list(theta_mean), paste0("theta", 1:12))
  177. grad <- purrr::attr_getter("gradient")
  178. hessian <- purrr::attr_getter("hessian")
  179. from_ <- rep(c(1, 2, 3, 5, 6, 7), each = 2)
  180. to_ <- c(1:4, 2, 3, 5:8, 6, 7)
  181. for (t in 1:60) {
  182. param_list$t <- pmax(t, 1 + 1e-10)
  183. walk2(from_, to_, function(f_, t_) {
  184. tmp <- eval(get(paste0("dP", f_, t_)), param_list)
  185. dP[f_, t_, t, ] <<- unname(grad(tmp))[1, ]
  186. d2P[f_, t_, t, , ] <<- unname(hessian(tmp))[1, , ]
  187. })
  188. }
  189. # - Value matrix
  190. # - Utilities
  191. dV[1, 2, , 10] <- -exp(-theta_mean[10]) * (1 + exp(-theta_mean[10])) ^ (-2) * 1.015 ^ (-(1:60)) # V[1, 2, t] = U_SuccessP 1.015^(-t)
  192. dV[1, 6, , 10] <- -dV[1, 2, , 10]
  193. dV[2, 2, , 12] <- -exp(-theta_mean[12]) * (1 + exp(-theta_mean[12])) ^ (-2) * 1.015 ^ (-(1:60))
  194. dV[2, 6, , 12] <- -dV[2, 2, , 12]
  195. dV[3, 2, , 11] <- -exp(-theta_mean[11]) * (1 + exp(-theta_mean[11])) ^ (-2) * 1.015 ^ (-(1:60))
  196. dV[3, 6, , 11] <- -dV[3, 2, , 11]
  197. dV[5, 4, , 10] <- -exp(-theta_mean[10]) * (1 + exp(-theta_mean[10])) ^ (-2) * 1.015 ^ (-(1:60))
  198. dV[5, 6, , 10] <- dV[5, 4, , 10]
  199. dV[6, 4, , 12] <- -exp(-theta_mean[12]) * (1 + exp(-theta_mean[12])) ^ (-2) * 1.015 ^ (-(1:60))
  200. dV[6, 6, , 12] <- dV[6, 4, , 12]
  201. dV[7, 4, , 11] <- -exp(-theta_mean[11]) * (1 + exp(-theta_mean[11])) ^ (-2) * 1.015 ^ (-(1:60))
  202. dV[7, 6, , 11] <- dV[7, 4, , 11]
  203. d2V[1, 2, , 10, 10] <- exp(-theta_mean[10]) * (1 - exp(-theta_mean[10])) * (1 + exp(-theta_mean[10])) ^ (-3) * 1.015 ^ (-(1:60))
  204. d2V[1, 6, , 10, 10] <- -d2V[1, 2, , 10, 10]
  205. d2V[2, 2, , 12, 12] <- exp(-theta_mean[12]) * (1 - exp(-theta_mean[12])) * (1 + exp(-theta_mean[12])) ^ (-3) * 1.015 ^ (-(1:60))
  206. d2V[2, 6, , 12, 12] <- -d2V[2, 2, , 12, 12]
  207. d2V[3, 2, , 11, 11] <- exp(-theta_mean[11]) * (1 - exp(-theta_mean[11])) * (1 + exp(-theta_mean[11])) ^ (-3) * 1.015 ^ (-(1:60))
  208. d2V[3, 6, , 11, 11] <- -d2V[3, 2, , 11, 11]
  209. d2V[5, 4, , 10, 10] <- exp(-theta_mean[10]) * (1 - exp(-theta_mean[10])) * (1 + exp(-theta_mean[10])) ^ (-3) * 1.015 ^ (-(1:60))
  210. d2V[5, 6, , 10, 10] <- d2V[5, 4, , 10, 10]
  211. d2V[6, 4, , 12, 12] <- exp(-theta_mean[12]) * (1 - exp(-theta_mean[12])) * (1 + exp(-theta_mean[12])) ^ (-3) * 1.015 ^ (-(1:60))
  212. d2V[6, 6, , 12, 12] <- d2V[6, 4, , 12, 12]
  213. d2V[7, 4, , 11, 11] <- exp(-theta_mean[11]) * (1 - exp(-theta_mean[11])) * (1 + exp(-theta_mean[11])) ^ (-3) * 1.015 ^ (-(1:60))
  214. d2V[7, 6, , 11, 11] <- d2V[7, 4, , 11, 11]
  215. # - Costs
  216. dV[2, 1, , 9] <- V[2, 1, ] # V[2, 1, t] = exp(theta[9]) 1.06^(-t)
  217. dV[2, 5, , 9] <- V[2, 5, ]
  218. dV[6, 3, , 9] <- V[6, 3, ]
  219. dV[6, 5, , 9] <- V[6, 5, ]
  220. d2V[2, 1, , 9, 9] <- V[2, 1, ]
  221. d2V[2, 5, , 9, 9] <- V[2, 5, ]
  222. d2V[6, 3, , 9, 9] <- V[6, 3, ]
  223. d2V[6, 5, , 9, 9] <- V[6, 5, ]
  224. # - Initial state distribution
  225. dx[c(1, 4, 5, 8), 1, 6] <- c(-1, 1, -1, 1) * exp(-theta_mean[6]) * (1 + exp(-theta_mean[6])) ^ (-2)
  226. d2x[c(1, 4, 5, 8), 1, 6, 6] <- c(1, -1, 1, -1) * exp(-theta_mean[6]) * (1 - exp(-theta_mean[6])) * (1 + exp(-theta_mean[6])) ^ (-3)
  227. for (i in 1:12) {
  228. dgt[, 1, i] <- t(dV[, , 1, i]) %*% x[, 1] + t(V[, , 1]) %*% dx[, 1, i]
  229. for (j in 1:12) {
  230. d2gt[, 1, i, j] <- t(d2V[, , 1, i, j]) %*% x[, 1] +
  231. t(dV[, , 1, i]) %*% dx[, 1, j] +
  232. t(dV[, , 1, j]) %*% dx[, 1, i] +
  233. t(V[, , 1]) %*% d2x[, 1, i, j]
  234. }
  235. }
  236. # - Recurrence relation
  237. for (t in 2:60) {
  238. for (i in 1:12) {
  239. dx[, t, i] <- t(dP[, , t-1, i]) %*% x[, t-1] + t(P[, , t-1]) %*% dx[, t-1, i]
  240. dgt[, t, i] <- t(dV[, , t, i]) %*% x[, t] + t(V[, , t]) %*% dx[, t-1, i]
  241. for (j in 1:12) {
  242. d2x[, t, i, j] <- t(d2P[, , t-1, i, j]) %*% x[, t-1] +
  243. t(dP[, , t-1, i]) %*% dx[, t-1, j] +
  244. t(dP[, , t-1, j]) %*% dx[, t-1, i] +
  245. t(P[, , t-1]) %*% d2x[, t-1, i, j]
  246. d2gt[, t, i, j] <- t(d2V[, , t, i, j]) %*% x[, t] +
  247. t(dV[, , t, i]) %*% dx[, t, j] +
  248. t(dV[, , t, j]) %*% dx[, t, i] +
  249. t(V[, , t]) %*% d2x[, t, i, j]
  250. }
  251. }
  252. }
  253. # RESULTS!
  254. dg <- apply(dgt, c(1, 3), sum)
  255. d2g <- apply(d2gt, c(1, 3, 4), sum)
  256. g_expected <- sapply(1:6, function(v) g[v] + 0.5 * sum(d2g[v, , ] * theta_var))
  257. g_variance <- dg %*% theta_var %*% t(dg)
  258. g_sd <- sqrt(diag(g_variance))
  259. # COMPARE WITH PSA
  260. g_psa <- readRDS("THR-MCPSA.rds")
  261. library(patchwork)
  262. p_standard_costs <- ggplot(g_psa, aes(x = Standard_Costs)) +
  263. geom_density() +
  264. stat_function(fun = dnorm, args = list(mean = g_expected[1], sd = g_sd[1]), linetype = "dashed", colour = "blue") +
  265. scale_x_continuous("Lifetime costs", labels = scales::dollar_format(prefix = "£")) +
  266. ggtitle("Costs for standard prosthesis") +
  267. theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank())
  268. p_standard_QALYs <- ggplot(g_psa, aes(x = Standard_QALYs)) +
  269. geom_density() +
  270. stat_function(fun = dnorm, args = list(mean = g_expected[2], sd = g_sd[2]), linetype = "dashed", colour = "blue") +
  271. scale_x_continuous("Quality adjusted life years (QALYs)") +
  272. ggtitle("QALYs for standard prosthesis") +
  273. theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank())
  274. p_NP1_costs <- ggplot(g_psa, aes(x = NP1_Costs)) +
  275. geom_density() +
  276. stat_function(fun = dnorm, args = list(mean = g_expected[3], sd = g_sd[3]), linetype = "dashed", colour = "blue") +
  277. scale_x_continuous("Lifetime costs", labels = scales::dollar_format(prefix = "£")) +
  278. ggtitle("Costs for NP1 prosthesis") +
  279. theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank())
  280. p_NP1_QALYs <- ggplot(g_psa, aes(x = NP1_QALYs)) +
  281. geom_density() +
  282. stat_function(fun = dnorm, args = list(mean = g_expected[4], sd = g_sd[4]), linetype = "dashed", colour = "blue") +
  283. scale_x_continuous("Quality adjusted life years (QALYs)") +
  284. ggtitle("QALYs for NP1 prosthesis") +
  285. theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank())
  286. p_inc_costs <- ggplot(g_psa, aes(x = Incremental_Costs)) +
  287. geom_density() +
  288. stat_function(fun = dnorm, args = list(mean = g_expected[5], sd = g_sd[5]), linetype = "dashed", colour = "blue") +
  289. scale_x_continuous("Lifetime costs", labels = scales::dollar_format(prefix = "£")) +
  290. ggtitle("Incremental costs") +
  291. theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank())
  292. p_inc_QALYs <- ggplot(g_psa, aes(x = Incremental_QALYs)) +
  293. geom_density() +
  294. stat_function(fun = dnorm, args = list(mean = g_expected[6], sd = g_sd[6]), linetype = "dashed", colour = "blue") +
  295. scale_x_continuous("Quality adjusted life years (QALYs)") +
  296. ggtitle("Incremental QALYs") +
  297. theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank())
  298. (p_standard_costs + p_NP1_costs + p_inc_costs) / (p_standard_QALYs + p_NP1_QALYs + p_inc_QALYs)
  299. ggsave("Delta-PSA comparison.png", width = 20.28, height = 10.62, units = "cm")
  300. wtp <- seq(0, 10000, by = 100)
  301. ceac_psa <- sapply(wtp, function(lambda) mean(lambda * g_psa$Incremental_QALYs >= g_psa$Incremental_Costs))
  302. m <- - g_expected[5] + wtp * g_expected[6]
  303. s <- sqrt(wtp ^ 2 * g_variance[6,6] - 2 * wtp * g_variance[5,6] + g_variance[5,5])
  304. ggplot(tibble(x = wtp, ceac.delta = pnorm(m/s), ceac.psa = ceac_psa), aes(x)) +
  305. geom_line(aes(y = ceac.delta, linetype = "Delta-PSA", colour = "Delta-PSA")) +
  306. geom_line(aes(y = ceac.psa, linetype = "MC-PSA", colour = "MC-PSA")) +
  307. scale_x_continuous("Willingness-to-pay for additional QALY", labels = scales::dollar_format(prefix = "£")) +
  308. scale_y_continuous("Probability NP1 is cost-effective", labels = scales::percent_format()) +
  309. scale_colour_discrete("Method") +
  310. scale_linetype_discrete("Method")
  311. ggsave("Delta-PSA CEAC.png", width = 20.28, height = 10.62, units = "cm", scale = 0.8)
  312. evpi_psa <- sapply(wtp, function(lambda) {
  313. inmb <- lambda * g_psa$Incremental_QALYs - g_psa$Incremental_Costs
  314. evpi <- mean(abs(inmb)) - abs(mean(inmb))
  315. evpi
  316. })
  317. evpi_delta <- (s * sqrt(2/pi) * exp(-m^2 / (2 * s^2)) - m * (1 - 2 * pnorm(m/s))) - abs(m)
  318. ggplot(tibble(x = wtp, evpi.delta = evpi_delta, evpi.psa = evpi_psa), aes(x)) +
  319. geom_line(aes(y = evpi.delta, linetype = "Delta-PSA", colour = "Delta-PSA")) +
  320. geom_line(aes(y = evpi.psa, linetype = "MC-PSA", colour = "MC-PSA")) +
  321. scale_x_continuous("Willingness-to-pay for additional QALY", labels = scales::dollar_format(prefix = "£")) +
  322. scale_y_continuous("Expected value of perfect information", labels = scales::dollar_format(prefix = "£")) +
  323. scale_colour_discrete("Method") +
  324. scale_linetype_discrete("Method")
  325. ggsave("Delta-PSA EVPI.png", width = 20.28, height = 10.62, units = "cm", scale = 0.8)