Home page

This model was developed by Philippe Beutels, Joke Bilcke and Lander Willem for illustration and teaching purposes only. Please contact us 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 (e.g. 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 numberof 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
p_hospital <- 0.10
case_fatality_ratio     <- 0.03  # applies to all infections

# disease-related costs
cost_hosp_case    <- 2000 # euro
cost_non_hosp_case <- 100  # euro

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


Part I: costs and burden of disease

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_hosp_case * p_hospital + 
                              (1-p_hospital) * cost_non_hosp_case
print(c(treatment_cost_per_case = treatment_cost_per_case, 
        vaccine_cost_per_dose = vaccine_cost_per_dose))
## treatment_cost_per_case   vaccine_cost_per_dose 
##                     290                      60

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

# Comparator
comparator_infections       <- targetgroup * force_of_infection
comparator_hospitalisations <- comparator_infections * p_hospital
comparator_deaths           <- comparator_infections * case_fatality_ratio
comparator_lifeyearslost    <- comparator_deaths * life_expectancy

comparator_treatment_costs   <- comparator_infections * treatment_cost_per_case
comparator_vaccination_costs <- 0
comparator_total_costs <- comparator_treatment_costs + comparator_vaccination_costs

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 * p_hospital
program_deaths           <- program_infections * case_fatality_ratio
program_lifeyearslost    <- program_deaths * life_expectancy

program_treatment_costs   <- program_infections * treatment_cost_per_case
program_vaccination_costs <- fixed_program_costs + targetgroup * uptake_program * vaccine_cost_per_dose
program_total_costs <- program_treatment_costs + program_vaccination_costs
print(c(comparator_treatment_costs = comparator_treatment_costs, 
        program_treatment_costs = program_treatment_costs))
## comparator_treatment_costs    program_treatment_costs 
##                   29000000                   15080000

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_treatment_costs - program_treatment_costs
incr_vaccination_costs   <- program_vaccination_costs - comparator_vaccination_costs # 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


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:

QALYloss_hosp_case    <- 0.018
QALYloss_non_hosp_case <- 0.0082


Solutions II: step-by-step

Calculate the effect per average case and the total burden of disease for the comparator and program.

# intermediate results
QALYloss_per_case        <- QALYloss_hosp_case * p_hospital +        
                               QALYloss_non_hosp_case * (1-p_hospital)

# program: effect
program_QALYloss          <- program_infections * QALYloss_per_case + program_lifeyearslost

# comparator: effect
comparator_QALYloss       <- comparator_infections * QALYloss_per_case + comparator_lifeyearslost

Time to calculate the incremental effect, and ICER:

# incremental effect
QALY_gained                <- comparator_QALYloss - program_QALYloss

# 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


Part III: Total cost

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.

# treatment costs (in million)
data.frame(comparator_treatment_costs = comparator_treatment_costs,
           program_treatment_costs    = program_treatment_costs,
           treatment_costs_averted    = treatment_costs_averted) / 1e6
##   comparator_treatment_costs program_treatment_costs treatment_costs_averted
## 1                         29                   15.08                   13.92
# investment costs (in million)           
data.frame(incr_vaccination_costs = incr_vaccination_costs) / 1e6
##   incr_vaccination_costs
## 1                    120
# program vs comparator (in million)
data.frame(comparator_total_costs = comparator_total_costs,
           program_total_costs = program_total_costs,
           incr_total_costs = incr_total_costs) / 1e6
##   comparator_total_costs program_total_costs incr_total_costs
## 1                     29              135.08           106.08

Part VI: 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 12 years
years <- 0:11  # Time periods from 0 to 11 (12 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)[-1])
##            Costs Discounted_Costs            QALYs Discounted_QALYs 
##      12000.00000      11071.11779         12.00000         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 VI: step-by-step

Calculate the discounted life expectancy to include in the effect calculation, and continue to obtain the discounted ICER:

# 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_QALYloss_disc       <- program_infections * QALYloss_per_case + program_lifeyearslost_disc

# comparator: effect
comparator_lifeyearslost_disc <- comparator_deaths * life_expectancy_disc
comparator_QALYloss_disc     <- comparator_infections * QALYloss_per_case + comparator_lifeyearslost_disc

# incremental effect
QALY_gained_disc              <- comparator_QALYloss_disc - program_QALYloss_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