Home page

This model was developed by Philippe Beutels, Joke Bilcke and Lander Willem for illustration and teaching purposes only. Please make contact if you would like to use this model in any public way.

In the field of economic evaluation in general, it could be applicable to any intervention with effectiveness realised within one year (like many curative interventions). In the field of infectious disease, it would only be applicable to influenza, and only if vaccination targets a small proportion of the population that does not at the same time form a core transmitter group of the virus (eg it is unlikely to be suitable to model childhood influenza vaccination). Note that for most applications, practical use of this model would likely entail having separate, though similarly simple decision trees to obtain the unit cost estimates (implying that these cells would be intermediary outcomes, and that there would be additional input cells for each relevant stage of disease (for instance for the number of consultations, the unit costs per consultation, medication use, hospital days etc for cases of pneumonia, and all other relevant disease stages)).

Note that the final output is independent of coverage and target group size, if fixed administration costs are set to 0. This is due to the exclusion of herd immunity effects in this model.

For further information, questions or comments please contact us.

Set working directory

The first step when creating a new R file is to specify a working directory. You need to tell the R session where you want it to work. To do this you use the command to “set the working directory” or setwd().

You can label this working directory as ‘home’, and have other locations stored for plotting or for getting data. This location should be an existing folder on your computer. For example

home <- "~/Documents/Modelling_intro/"     # on OS X
home <- "C:\\Documents\\Modelling_intro\\" # on windows
setwd(home)

Goal, input and assumptions

The goal is to calculate the cost-effectiveness (cost per flu case prevented, per hospitalisation prevented, per death averted, and per life-year gained) of a vaccination program in elderly against flu, based on the following assumptions and input parameters:

# population
targetgroup             <- 2500000 # people +65 years
life_expectancy         <- 12      # years

# burden of disease
force_of_infection      <- 0.04  # static
proportion_hospitalised <- 0.10
casefatality_ratio      <- 0.03  # applies to all infections

# disease-related costs
cost_per_hospitalised_case    <- 2000 # dollars
cost_per_nonhospitalised_case <- 100  # dollars

# program details
uptake_program          <- 0.80
vaccine_efficacy        <- 0.60
vaccine_price_per_dose  <- 10   # dollars
admin_cost_per_dose     <- 50   # dollars
fixed_program_costs     <- 0    # dollars

Health Technology Assessment (part I)

Here are the tasks you need to complete to run the health technology assessment:

  1. Calculate Vaccine and Treatment Costs:
    • To begin, calculate the vaccine cost per dose and the treatment cost per case, considering the proportion of cases that result in hospitalization.
  2. Calculate Burden of Disease with the Program:
    • Calculate the burden of disease with the program in place, along with the associated medical and program costs.
  3. Calculate Burden of Disease for the Comparator:
    • Calculate the burden of disease for the comparator without the program in place, including the medical costs.
  4. Calculate Differences Between Program and Comparator:
    • Calculate the difference between the program and the comparator.
  5. Calculate Incremental Effectiveness Ratios:
    • Calculate the incremental effectiveness ratios for infections, hospitalizations, and deaths averted.
    • Finally, calculate the incremental effectiveness ratios for life years saved.
  6. Show Results:
    • Display the results.



Solutions I: step-by-step

To begin the health technology assessment, we calculate the vaccine cost per dose and the treatment cost per case, considering the proportion of cases that result in hospitalization:

vaccine_cost_per_dose     <- vaccine_price_per_dose + admin_cost_per_dose
treatment_cost_per_case   <- cost_per_hospitalised_case * proportion_hospitalised + 
                              (1-proportion_hospitalised) * cost_per_nonhospitalised_case

Calculate the burden of disease with the program in place, along with the associated medical and program costs:

# Program
population_at_risk       <- targetgroup * (1-uptake_program) + targetgroup * uptake_program * (1-vaccine_efficacy)

program_infections       <- population_at_risk * force_of_infection 
program_hospitalisations <- program_infections * proportion_hospitalised
program_deaths           <- program_infections * casefatality_ratio
program_lifeyearslost    <- program_deaths * life_expectancy

program_treatmentcosts   <- program_infections * treatment_cost_per_case
program_vaccinationcosts <- fixed_program_costs + targetgroup * uptake_program * vaccine_cost_per_dose
program_totaldirectcosts <- program_treatmentcosts + program_vaccinationcosts

Calculate the burden of disease for the comparator without the program in place, including the medical costs:

# Comparator
comparator_infections       <- targetgroup * force_of_infection
comparator_hospitalisations <- comparator_infections * proportion_hospitalised
comparator_deaths           <- comparator_infections * casefatality_ratio
comparator_lifeyearslost    <- comparator_deaths * life_expectancy

comparator_treatmentcosts   <- comparator_infections * treatment_cost_per_case
comparator_vaccinationcosts <- 0
comparator_totaldirectcosts <- comparator_treatmentcosts + comparator_vaccinationcosts

Calculate the difference between the program and the comparator:

# To calculate the difference between 'program' and 'comparator' 
infections_averted       <- comparator_infections - program_infections
hospitalisations_averted <- comparator_hospitalisations - program_hospitalisations
deaths_averted           <- comparator_deaths - program_deaths
lifeyearslost_averted    <- comparator_lifeyearslost - program_lifeyearslost

treatment_costs_averted  <- comparator_treatmentcosts - program_treatmentcosts
incr_vaccination_costs   <- program_vaccinationcosts - comparator_vaccinationcosts # incremental costs
incr_total_costs         <- incr_vaccination_costs - treatment_costs_averted

Calculate the incremental effectiveness ratios for infections, hospitalizations, and deaths averted. Finally, calculate the incremental effectiveness ratios for life years saved:

# Calculate incremental effectiveness ratios
incr_cost_per_case_prevented            <- incr_total_costs / infections_averted
incr_cost_per_hospitalisation_prevented <- incr_total_costs / hospitalisations_averted
incr_cost_per_death_averted             <- incr_total_costs / deaths_averted
incr_cost_per_lifeyear_gained           <- incr_total_costs / lifeyearslost_averted

Show the results:

# combine results
# note: specify column names at once
ICER_values<-c(incr_cost_per_case_prevented  = incr_cost_per_case_prevented,
               incr_cost_per_hospitalisation_prevented = incr_cost_per_hospitalisation_prevented,
               incr_cost_per_death_averted   = incr_cost_per_death_averted,
               incr_cost_per_lifeyear_gained =incr_cost_per_lifeyear_gained)

round(ICER_values) # print
##            incr_cost_per_case_prevented incr_cost_per_hospitalisation_prevented 
##                                    2210                                   22100 
##             incr_cost_per_death_averted           incr_cost_per_lifeyear_gained 
##                                   73667                                    6139



Health Technology Assessment (part II): QALY

The burden of disease can also be represented by quality-adjusted life years (QALYs). Please calculate the incremental cost-effectiveness ratio in terms of the incremental cost per QALY gained, using the following QALY values:

QALYslost_per_hospitalised_case    <- 0.018
QALYslost_per_nonhospitalised_case <- 0.0082



Solutions II: step-by-step

# intermediate results
QALYslost_per_case        <- QALYslost_per_hospitalised_case * proportion_hospitalised +        
                               QALYslost_per_nonhospitalised_case * (1-proportion_hospitalised)

# program: effect
program_QALYslost          <- program_infections * QALYslost_per_case + program_lifeyearslost

# comparator: effect
comparator_QALYslost       <- comparator_infections * QALYslost_per_case + comparator_lifeyearslost

# incremental effect
QALY_gained                <- comparator_QALYslost - program_QALYslost

# incremental cost-effectiveness ratio
incr_costs_per_QALY_gained <- incr_total_costs / QALY_gained

ICER_values <- c(ICER_values,
                 incr_costs_per_QALY_gained = incr_costs_per_QALY_gained)

# print
round(ICER_values)
##            incr_cost_per_case_prevented incr_cost_per_hospitalisation_prevented 
##                                    2210                                   22100 
##             incr_cost_per_death_averted           incr_cost_per_lifeyear_gained 
##                                   73667                                    6139 
##              incr_costs_per_QALY_gained 
##                                    5986



Health Technology Assessment (part III): discounting

Health Technology Assessments often involves comparing the costs and benefits of healthcare interventions over time. Discounting is a critical concept in HTA, reflecting the principle that costs and benefits occurring in the future are worth less than those occurring today. This is because of the time preference for immediate benefits and the opportunity cost of capital. By applying discount rates, HTA practitioners can appropriately adjust future costs and health outcomes to present values, enabling fair and consistent comparisons between different healthcare technologies or interventions. Here’s a small example to illustrate how discounting is applied in HTA:

# Set the discount rate (e.g., 1.5% or 3%)
discount_rate <- 0.015
# Define a discounting function
discount <- function(values, rate, years) {
  # Calculate discounted values
  discounted_values <- values / ((1 + rate) ^ years)
  return(discounted_values)
}

# Example data: costs and QALYs over 10 years
years <- 0:11  # Time periods from 0 to 9 (10 years)

# fixed
costs <- rep(1000, length(years))  # Example costs per year
qalys <- rep(1, length(years))     # Example QALYs per year

# Apply discounting
discounted_costs <- discount(costs, discount_rate, years)
discounted_qalys <- discount(qalys, discount_rate, years)

# Display the results
discounted_data <- data.frame(
  Year = years,
  Costs = costs,
  Discounted_Costs = discounted_costs,
  QALYs = qalys,
  Discounted_QALYs = discounted_qalys
)

# print 
print(discounted_data)
##    Year Costs Discounted_Costs QALYs Discounted_QALYs
## 1     0  1000        1000.0000     1        1.0000000
## 2     1  1000         985.2217     1        0.9852217
## 3     2  1000         970.6617     1        0.9706617
## 4     3  1000         956.3170     1        0.9563170
## 5     4  1000         942.1842     1        0.9421842
## 6     5  1000         928.2603     1        0.9282603
## 7     6  1000         914.5422     1        0.9145422
## 8     7  1000         901.0268     1        0.9010268
## 9     8  1000         887.7111     1        0.8877111
## 10    9  1000         874.5922     1        0.8745922
## 11   10  1000         861.6672     1        0.8616672
## 12   11  1000         848.9332     1        0.8489332
# print sum
print(colSums(discounted_data))
##             Year            Costs Discounted_Costs            QALYs 
##         66.00000      12000.00000      11071.11779         12.00000 
## Discounted_QALYs 
##         11.07112

Task

Incorporate time preference into our health technology assessments for flu. Although all costs are incurred in the current year, the benefits, measured in life years saved, extend into the future. To accurately reflect the value of these future health effects, they should be adjusted using a discount rate.




Solutions III: step-by-step

# intermediate results
life_expectancy_disc <- sum(1/((1+discount_rate)^(0:(life_expectancy-1))))


# program: effect
program_lifeyearslost_disc   <- program_deaths * life_expectancy_disc
program_QALYslost_disc       <- program_infections * QALYslost_per_case + program_lifeyearslost_disc

# comparator: effect
comparator_lifeyearslost_disc <- comparator_deaths * life_expectancy_disc
comparator_QALYslost_disc     <- comparator_infections * QALYslost_per_case + comparator_lifeyearslost_disc

# incremental effect
QALY_gained_disc              <- comparator_QALYslost_disc - program_QALYslost_disc

# incremental cost-effectiveness ratio
incr_costs_per_QALY_gained_disc <- incr_total_costs / QALY_gained_disc

# add to output vector
ICER_values <- c(ICER_values,
                 incr_costs_per_QALY_gained_disc = incr_costs_per_QALY_gained_disc)

# print
round(ICER_values)
##            incr_cost_per_case_prevented incr_cost_per_hospitalisation_prevented 
##                                    2210                                   22100 
##             incr_cost_per_death_averted           incr_cost_per_lifeyear_gained 
##                                   73667                                    6139 
##              incr_costs_per_QALY_gained         incr_costs_per_QALY_gained_disc 
##                                    5986                                    6475

Total costs and effects

In addition to the incremental costs and effects per case or disease burden type, it is also worthwhile to assess the overall costs and effects at the population level. Therefore, consider the total investment and revenue of an intervention given the target group.

# impact of comparator strategy
data.frame(comparator_totaldirectcosts=comparator_totaldirectcosts,
           comparator_QALYslost_disc=comparator_QALYslost_disc)
##   comparator_totaldirectcosts comparator_QALYslost_disc
## 1                     2.9e+07                  34131.35
# impact of program           
data.frame(program_totaldirectcosts=program_totaldirectcosts,
           program_QALYslost_disc=program_QALYslost_disc)
##   program_totaldirectcosts program_QALYslost_disc
## 1                135080000                17748.3
# program vs comparator
data.frame(incr_total_costs=incr_total_costs,
           QALY_gained_disc=QALY_gained_disc)
##   incr_total_costs QALY_gained_disc
## 1        106080000         16383.05