https://gianluca.statistica.it/
https://egon.stats.ucl.ac.uk/research/statistics-health-economics/
6 November 2022
Check out our departmental podcast "Random Talks" on Soundcloud!
Follow our departmental social media accounts
Best opening sentence #ISPOREurope from Gianluca Baio: “statisticians should rule the world and Bayesian statisticians should rule all statisticians” https://t.co/GN2w7liAcR
— Manuela Joore (@ManuelaJoore) November 4, 2019
...Just so you know what you're about to get into... 😉
Objective: Combine costs and benefits of a given intervention into a rational scheme for allocating resources
Objective: Combine costs and benefits of a given intervention into a rational scheme for allocating resources
Objective: Combine costs and benefits of a given intervention into a rational scheme for allocating resources
Objective: Combine costs and benefits of a given intervention into a rational scheme for allocating resources
For each module, we may need/use different/specific packages! (the "R-HTA-verse"?)
For each module, we may need/use different/specific packages! (the "R-HTA-verse"?)
For each module, we may need/use different/specific packages! (the "R-HTA-verse"?)
R
?R
is a very powerful statistical software R
?R
is a very powerful statistical software R
?Everything can be (and almost invariably is) scripted
This helps with:
Fantastic graphical capability
Generally fit for purpose
"Transparency is in the eye of the beholder"
(Andy Briggs at the R-HTA workshop – October 2020)
"Transparency is in the eye of the beholder"
(Andy Briggs at the R-HTA workshop – October 2020)
There is an entry cost
And more importantly, the effort goes hand in hand with sophistication in the statistical modelling associated with the economic evaluation!
BCEA
R
package for (Bayesian) cost-effectiveness analysisBCEA
and its use directly in R
are designed with these objectives in mindChecking the model assumptions
BCEA
R
package for (Bayesian) cost-effectiveness analysisBCEA
and its use directly in R
are designed with these objectives in mindChecking the model assumptions
Produce the base-case economic evaluation
BCEA
R
package for (Bayesian) cost-effectiveness analysisBCEA
and its use directly in R
are designed with these objectives in mindChecking the model assumptions
Produce the base-case economic evaluation
Perform uncertainty analysis
BCEA
R
package for (Bayesian) cost-effectiveness analysisBCEA
and its use directly in R
are designed with these objectives in mindChecking the model assumptions
Produce the base-case economic evaluation
Perform uncertainty analysis
Standardised reporting
R
facilities)docx
/pdf
)BCEA
R
package for (Bayesian) cost-effectiveness analysis
BCEA
to summarise outputs of an economic modelBCEA
work?BCEA
is available from CRAN
But it is also under constant development in the GitHub repository
> # Install BCEA (only required once and needs an internet connection!). > > # You can either get the "official" version from CRAN> install.packages("BCEA")> > # Or the development version from the GitHub repository> remotes::install_github("giabaio/BCEA") # stable version (2.4-2)> > remotes::install_github("giabaio/BCEA",ref="dev") # development version (2.4-2)
NB: The beauty of the GitHub version is that it can be updated on the fly and be immediately available for users!
> library(dplyr) # (Not necessary - helpful for data manipulation!)> > library(BCEA) # Then loads the package (so you can access its functions)> data(Vaccine) # Loads an example dataset
The "Vaccine" example is a fictional cost-effectiveness model for and influenza vaccine, based on evidence synthesis (and a real case)
2 treatment options ("Standard of care" vs "Vaccination") and overall 63 parameters
Discussed in details in Baio et al, 2017 and Baio and Dawid, 2011
In this case, PSA simulations obtained from a full Bayesian model, but could be done in a spreadsheet and imported into R
> # The object 'Vaccine' contains a matrix 'vaccine_mat', with all the simulated values for the many model > # parameters BCEA can create a matrix with the underlying model simulations starting from various formats > # (BUGS/R/Excel) and can get rid of "redundant" columns (those that are linear combination of each other...)> inp = createInputs(vaccine_mat, print_is_linear_comb = FALSE)> > # Visualise the output: "piping" ('%>%') + nicer visualisation> inp$mat %>% as_tibble()
NB: There are various R
packages/tools to work with tables
# A tibble: 1,000 × 56 Adverse.e…¹ Death…² Death…³ Death…⁴ GP.1.1. GP.2.1. GP.2.2. Hospi…⁵ Hospi…⁶ Hospi…⁷ Infec…⁸ Infec…⁹ Infec…˟ Mild.…˟ Mild.…˟ Mild.…˟ Pneum…˟ Pneum…˟ <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1466 1 0 0 1664 958 230 0 1 0 5992 3401 876 691 405 102 18 15 2 5329 1 1 0 1414 748 276 0 0 1 7471 4024 1536 570 308 112 12 15 3 5203 1 1 0 809 489 80 0 0 0 6718 4300 788 332 214 40 10 2 4 2351 2 0 0 1761 1157 261 1 0 0 4837 3269 702 739 479 109 19 17 5 8303 1 2 0 2472 964 432 1 1 0 4749 1894 846 1049 425 177 25 11 6 3607 1 1 0 2224 1342 260 1 0 0 4938 2976 596 915 560 100 35 21 7 6304 4 1 1 3478 1107 591 2 1 0 11080 3547 2045 1505 482 247 66 19 8 4337 1 1 1 1483 799 189 0 0 0 3867 2164 525 622 333 65 22 7 9 5482 0 0 0 1587 798 279 0 0 0 5163 2532 910 675 332 115 25 1110 3125 2 2 0 2578 1681 243 0 0 0 7265 4766 700 1063 711 102 41 17# … with 990 more rows, 38 more variables: Pneumonia.2.2. <dbl>, Trt.1.1.1. <dbl>, Trt.2.1.1. <dbl>, Trt.1.2.1. <dbl>, Trt.2.2.1. <dbl>,# Trt.1.2.2. <dbl>, Trt.2.2.2. <dbl>, beta.1. <dbl>, beta.2. <dbl>, beta.3. <dbl>, beta.4. <dbl>, beta.5. <dbl>, beta.6. <dbl>, beta.7. <dbl>,# delta <dbl>, eta <dbl>, gamma.1. <dbl>, gamma.2. <dbl>, lambda <dbl>, n.1.2. <dbl>, n.2.2. <dbl>, phi <dbl>, pi.1.2. <dbl>, psi.1. <dbl>,# psi.2. <dbl>, psi.3. <dbl>, psi.4. <dbl>, psi.5. <dbl>, psi.6. <dbl>, psi.7. <dbl>, psi.8. <dbl>, q.1. <dbl>, q.4. <dbl>, q.5. <dbl>, q.6. <dbl>,# q.7. <dbl>, rho.2. <dbl>, xi <dbl>, and abbreviated variable names ¹Adverse.events, ²Death.1.1., ³Death.2.1., ⁴Death.2.2., ⁵Hospital.1.1.,# ⁶Hospital.2.1., ⁷Hospital.2.2., ⁸Infected.1.1., ⁹Infected.2.1., ˟Infected.2.2., ˟Mild.Compl.1.1., ˟Mild.Compl.2.1., ˟Mild.Compl.2.2.,# ˟Pneumonia.1.1., ˟Pneumonia.2.1.
> # Defines the number of simulations considered> n.sims=inp$mat %>% nrow() > # applies the function 'nrow' (number of rows) to the object 'inp$mat'> # NB: Since R 4.1.0, can also use 'native' pipe ('|>')> # (probably a bit quicker, but in most cases, may be immaterial...)> > # Aggregates the model inputs to compute (e,c)> QALYs.inf = QALYs.pne <- QALYs.hosp <- QALYs.adv <- QALYs.death <- matrix(0,n.sims,2)> for (t in 1:2) {+ QALYs.inf[,t] = ((Infected[,t,1] + Infected[,t,2])*omega[,1]/365)/N+ QALYs.pne[,t] = ((Pneumonia[,t,1] + Pneumonia[,t,2])*omega[,4]/365)/N+ QALYs.hosp[,t] = ((Hospital[,t,1] + Hospital[,t,2])*omega[,5]/365)/N+ QALYs.death[,t] = ((Death[,t,1] + Death[,t,2])*omega[,6])/N+ }> QALYs.adv[,2] = (Adverse.events*omega[,7]/365)/N> e = -(QALYs.inf + QALYs.pne + QALYs.adv + QALYs.hosp + QALYs.death) + ...
NB: The data stored in the Vaccine
object (built-in in BCEA
) already contains the objects e,c
that can be used to run the decision analysis...
So, this step is actually not needed (but documented in Baio et al, 2017)
> cbind(eff,cost) %>% as_tibble(.name_repair="universal") # ensures that the columns are named
# A tibble: 1,000 × 4 Status.Quo...1 Vaccination...2 Status.Quo...3 Vaccination...4 <dbl> <dbl> <dbl> <dbl> 1 -0.00105 -0.000899 10.4 16.3 2 -0.000884 -0.000732 5.83 9.37 3 -0.000890 -0.000698 5.78 15.9 4 -0.00164 -0.00114 12.2 18.7 5 -0.00135 -0.000957 9.79 16.5 6 -0.00143 -0.000936 6.56 9.69 7 -0.000960 -0.00105 8.45 11.3 8 -0.00181 -0.00139 6.76 9.99 9 -0.000842 -0.000556 3.60 10.1 10 -0.00168 -0.00105 4.09 11.0 # … with 990 more rows
BCEA
work?bcea
that runs the economic analysis, for example something like > treats = c("Status quo","Vaccination")> m = bcea(e=eff,c=cost,ref=2,interventions=treats,Kmax=50000)
eff
: a matrix containing the simulations for the clinical benefits (that is nsim×nint values)cost
: a matrix containing the simulations for the costs (that is nsim×nint values)ref
: an indication of which intervention is to be taken as reference (default: the intervention in the first column of e
or c
)interventions
: a vector of labels for the interventions being compared Kmax
: the maximum value of k, the parameter of willingness to payBCEA
work?bcea
that runs the economic analysis, for example something like > treats = c("Status quo","Vaccination")> m = bcea(e=eff,c=cost,ref=2,interventions=treats,Kmax=50000)
eff
: a matrix containing the simulations for the clinical benefits (that is nsim×nint values)cost
: a matrix containing the simulations for the costs (that is nsim×nint values)ref
: an indication of which intervention is to be taken as reference (default: the intervention in the first column of e
or c
)interventions
: a vector of labels for the interventions being compared Kmax
: the maximum value of k, the parameter of willingness to paym
containing several elements> names(m)
[1] "n_sim" "n_comparators" "n_comparisons" "delta_e" "delta_c" "ICER" "Kmax" "k" "ceac" [10] "ib" "eib" "kstar" "best" "U" "vi" "Ustar" "ol" "evi" [19] "ref" "comp" "step" "interventions" "e" "c"
BCEA
work?Can visualise the output in various formats (tables/graphs)
> # The 'summary' "method" produces a tabular output> summary(m)
Cost-effectiveness analysis summary Reference intervention: VaccinationComparator intervention: Status quoOptimal decision: choose Status quo for k < 20100 and Vaccination for k >= 20100Analysis for willingness to pay parameter k = 25000 Expected net benefitVaccination -36.054Status quo -34.826 EIB CEAC ICERVaccination vs Status quo 1.2284 0.529 20098Optimal intervention (max expected net benefit) for k = 25000: VaccinationEVPI 2.4145
BCEA
work?Can visualise the output in various formats (tables/graphs)
> # The 'plot' "method" produces a *specific* > # version of graphical output> plot(m)
> ceplane.plot(+ m,wtp=20000,xlim=c(-.002,.002),ylim=c(-10,20)+ )
BCEA
work?
> # Using 'ggplot', you can go crazy with customisation...> ceplane.plot(m,wtp=10000,graph="gg",point=list(color="blue",size=1.8),area=list(fill="springgreen3"))
BCEA
work?> # Plots the Cost-Effectiveness Acceptability Curve> ceac.plot(m)
> # Plots the Expected Value of Partial Information (EVPI)> evi.plot(m)
> # "Basic" contourplot> contour(m)
The specialised function contour2
also shows the sustainability area
> contour2(m)
> contour2(m,wtp=100,xlim=c(-.0005,0.0015))
Cost-effectiveness efficiency frontier
> ceef.plot(m,print.plot=FALSE)
Cost-effectiveness efficiency frontier summary Interventions on the efficiency frontier: Effectiveness Costs Increase slope Increase angleVaccination -0.00080537 14.691 NA NAInterventions not on the efficiency frontier: Effectiveness Costs Dominance typeStatus quo -0.0010559 9.6555 Extended dominance
> ceef.plot(m,print.summary=FALSE)
R
has excellent graphical facilities and the graphs produced by BCEA
can be easily exported to many different formats> # "Opens" the graphical device> pdf("NAME_OF_THE_FILE",width=8,height=8) # for 'pdf', units are in inches> # Makes the plot> ceplane.plot(BCEA_OBJECT) # of course, specify whatever name you've > # chosen when creating the object...> # "Closes" the graphical device> dev.off()> > > # "Open" the graphical device"> jpeg("NAME_OF_FILE.jpg",width=480,height=480) # for 'jpeg' units are in px> # Makes the plot> ceplane.plot(BCEA_OBJECT)> # "Closes" the graphical device> dev.off()
NB: Rstudio
and rmarkdown
can do even more – that's for another time...
BCEA
Fictional model comparing antidepressants to cognitive behaviour therapy (CBT) and no treatment in people with depression
Statistical modelling based on evidence synthesis
Economic modelling: two matrices with relevant population summaries
effects
costs
> # Intervention labels> t.names<-c("No treatment","CBT","Antidepressant")> > # "Standard" analysis: pairwise comparisons> depression.bcea = bcea(effects,costs,+ interventions=t.names,ref=3) > # the third intervention is the reference> > # Plots the results> plot(depression.bcea)
> # For multiple treatment comparison> depression.multi.ce = multi.ce(depression.bcea)> > # Specialised plot method> ceac.plot(+ depression.multi.ce,pos=c(1,0.8),+ graph="ggplot2"+ )
NB: In older releases of BCEA
, this graph was done using the deprecated function mce.plot
ggplot
to customise the graph > ceac.plot(+ depression.multi.ce,pos=c(1,1),+ graph="ggplot2"+ ) + + ggplot2::stat_summary(+ fun=max, geom="line",+ colour="grey25", + alpha=.3, lwd=2.5+ )
ceaf.plot
> # Specialised plot> ceaf.plot(depression.multi.ce)
BCEAweb
Inspired by similar projects – eg SAVI
Create a web interface to use BCEA without even opening R (or even having it installed on your computer!)
BCEAweb
Inspired by similar projects – eg SAVI
Create a web interface to use BCEA without even opening R (or even having it installed on your computer!)
Typical work flow
BCEAweb
BCEA
in the background to do all the economic analysisBCEAweb
> # Creates a matrix with the underlying model simulations> inp = createInputs(vaccine_mat, print_is_linear_comb=FALSE)> > # Runs BCEAweb> BCEAweb(e=e, # matrix of simulations for the effectiveness+ c=c, # matrix of simulations for the costs+ parameters=inp$mat # matrix of simulations for all the model parameters+ )
BCEAweb
> # Creates a matrix with the underlying model simulations> inp = createInputs(vaccine_mat, print_is_linear_comb=FALSE)> > # Runs BCEAweb> BCEAweb(e=e, # matrix of simulations for the effectiveness+ c=c, # matrix of simulations for the costs+ parameters=inp$mat # matrix of simulations for all the model parameters+ )
BCEAweb
exists as a standalone webapp
Or, you can launch your own "local" version from the BCEA
package (as in the code above)!
Best opening sentence #ISPOREurope from Gianluca Baio: “statisticians should rule the world and Bayesian statisticians should rule all statisticians” https://t.co/GN2w7liAcR
— Manuela Joore (@ManuelaJoore) November 4, 2019
...Just so you know what you're about to get into... 😉
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |