Difference between revisions of "Economic evaluation"

From Testiwiki
Jump to: navigation, search
(default serotyyppi valintoja muutettu)
(curator added)
 
(156 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{method}}
+
{{progression class|progression=Reviewed|curator=THL|date=2016-03-21}}
{{progression class|progression=Draft}}
 
  
 
[[op_fi:Taloudellinen_arviointi]]
 
[[op_fi:Taloudellinen_arviointi]]
  
 
== Question ==  
 
== Question ==  
 +
How to identify the most cost-effective pneumococcal conjugate vaccine to the national immunisation programme?
  
Are the incremental health effects worth the incremental costs, if a vaccine is both more effective and more expensive?
+
* The health benefit (effectiveness) of the pneumococcal infant immunisation programme is assessed by the expected gain in Quality-Adjusted Life Years (QALYs), corresponding to the expected reduction in the annual number of invasive pneumococcal disease in the whole Finnish population.  
*The health benefit of the national infant immunisation programme is assessed by the expected reduction in the annual number of invasive pneumococcal disease in the Finnish population. The health benefit or effectiveness is measured in Quality-Adjusted Life Years (QALYs).  
+
* The perspective of the analysis is that of the health care provider.  
*The perspective of this analysis is that of the health care provider.  
+
* The analysis is based on incremental cost effectiveness
  
  
 
== Answer ==
 
== Answer ==
  
To find the most cost-effective vaccination programme according to the criteria described in the rationale.
+
A general approach to answer the question is based on the concept of incremental cost-effectiveness. For example, if there are only two vaccines to be compared, the more effective (and more expensive vaccine) is said to be more cost-effective if the incremental cost effectiveness ratio (ICER), comparing the vaccine to the less effective vaccine, exceeds the ICER of the less effective vaccine as compared to the alternative 'no vaccination'. The general principle is explained below (see 'Rationale').
  
{{attack|# |Code works but the costs seem unrealistic.|--[[User:Jouni|Jouni]] ([[User talk:Jouni|talk]]) 05:49, 11 August 2014 (UTC)}}
+
The importance of alternative assumptions about protection against individual serotypes were assessed in a sensitivity analysis. Several 'modifications' for PCV10 and PCV13 were considered, regarding assumptions about the extent of indirect protection against serotypes
 +
3, 6A, 6A, and 19A. A detailed account of the sensitivity analysis is on page [[Cost_effectiveness_sensitivity|'''Cost_effectiveness_sensitivity''']]. These analyses included determining the difference in the QALYs gained under PCV10 and PCV13.
  
 +
In summary, if PCV13 does not induce population-level (i.e. indirect) effects on serotype 3, the difference between PCV10 and PCV13 in quality adjusted life years (QALYs) gained and medical costs are relatively minor. Different assumptions about the roles of 6A protection by PCV10 and 6C protection by PCV13 lead to different preferences, with minor absolute differences in QALYs with respect to the overall effectiveness (QALYs gained) due to PCV vaccination. 
 +
 +
Therefore, in view of the intrinsic uncertainties in the evaluation, PCV10 and PCV13 can be regarded as equally effective. This also means that incremental cost effectiveness ratios do not need to be calculated.
 +
 +
== Evaluation tool ==
 +
 +
The following programme can be used to calculate the incremental cost effectiveness ratios (ICERs) for
 +
two alternative vaccination programmes. The input required is:
 +
 +
(a) the serotype compositions of the two vaccines to be compared (the defaults are PCV10 and PCV13), and
 +
 +
(b) the prices per dose for the two vaccine products.
 +
 +
The computation utilises the [[Epidemiological modelling|epidemiological model]]<ref name="optimalserotype">[http://www.ploscompbiol.org/article/info%3Adoi%2F10.1371%2Fjournal.pcbi.1003477  Nurhonen M, Auranen K (2014) Optimal Serotype Compositions for Pneumococcal Conjugate Vaccination under Serotype Replacement. PLoS Comput Biol 10(2): e1003477. doi:10.1371/journal.pcbi.1003477]</ref> to predict the annual number of invasive pneumococcal disease (IPD) under both vaccination programmes and, for comparison, for the scenario 'no vaccination'. The summary table presents the ICERs. The vaccine programme with the lower ICER is identified as the more cost-effective of the two alternatives. Note, that some of the ouput is irrelevant if the vaccine programme is cost saving (i.e, if savings in medical costs exceed vaccine programme cost).
 +
 +
'''N.B.''' Some assumptions applied int the sensitivity analysis cannot be realised with the current version of the programme. In particular, there is currently no option to include direct protection only (i.e. vaccine efficacy for the vaccinated cohorts only) for individual serotypes. However, the sensitivity analyses show that the difference between 'direct protection only' and 'no protection at all' is usually not decisive for the overall effectiveness of conjugate vaccination. In other words, the most important assumptions concers indirect protection.
 +
 +
<br>
 +
* <big>'''<u>Instructions for user: Choose the desired vaccine compositions and their prices and then press "Run code".</u>'''
 +
 +
The results of the cost-effectiveness analysis will be displayed on a separate tab. </big>
 
<rcode embed=0 graphics=1 variables="
 
<rcode embed=0 graphics=1 variables="
 
name:vac|description:Please choose the vaccines to be compared:|type:checkbox|options:
 
name:vac|description:Please choose the vaccines to be compared:|type:checkbox|options:
Line 23: Line 45:
 
default:'PCV10';'PCV13'|
 
default:'PCV10';'PCV13'|
 
category:Scenarios|
 
category:Scenarios|
name:price10|description:What is the total price of the PCV10 vaccine?|type:text|
+
name:price10|description:What is the price of a single PCV10 vaccination?|type:text|default:10|
name:price13|description:What is the total price of the PCV13 vaccine?|type:text|
+
name:price13|description:What is the price of a single PCV13 vaccination?|type:text|default:20|
 
name:custom_vac|description:Do you want to adjust PCV-10 or PCV-13 vaccine composition?|type:selection|options:
 
name:custom_vac|description:Do you want to adjust PCV-10 or PCV-13 vaccine composition?|type:selection|options:
 
FALSE;No;
 
FALSE;No;
Line 61: Line 83:
 
category:User defined vaccine|
 
category:User defined vaccine|
 
category_conditions:custom_vac;TRUE|
 
category_conditions:custom_vac;TRUE|
name:vac_user13|description:Choose the serotypes for the PCV-10 vaccine composition|type:checkbox|options:
+
name:vac_user13|description:Choose the serotypes for the PCV-13 vaccine composition|type:checkbox|options:
 
'1';1;
 
'1';1;
 
'3';3;
 
'3';3;
Line 101: Line 123:
 
if (length(vac) == 0) stop("Mitään skenaariota ei valittu")
 
if (length(vac) == 0) stop("Mitään skenaariota ei valittu")
  
vac <- c(vac, "No_vaccination")
+
vac <- c("No_vaccination",vac)
  
 
if(price10 == '') price10 <- 0
 
if(price10 == '') price10 <- 0
 
if(price13 == '') price13 <- 0
 
if(price13 == '') price13 <- 0
 +
n_vac <- 1.8e5
  
 
vacprice <- data.frame(
 
vacprice <- data.frame(
Line 110: Line 133:
 
Result = c(0, price10, price13)
 
Result = c(0, price10, price13)
 
)
 
)
vacprice <- EvalOutput(Ovariable("vacprice", data = vacprice[vacprice$Vaccine %in% vac , ]))
+
 
 +
vacprice <- EvalOutput(Ovariable("vacprice", data = vacprice[vacprice$Vaccine %in% vac , ])) * n_vac
  
 
temp <- opbase.data("Op_en6353", subset = "serotypes_in_typical_pneumococcal_vaccines")
 
temp <- opbase.data("Op_en6353", subset = "serotypes_in_typical_pneumococcal_vaccines")
Line 170: Line 194:
 
#Car <- Car * Ovariable("adjust", data = data.frame(Age = c("Under 5", "Over 5"), Result = c(1, adultcarriers)))
 
#Car <- Car * Ovariable("adjust", data = data.frame(Age = c("Under 5", "Over 5"), Result = c(1, adultcarriers)))
  
VacCar <- EvalOutput(VacCar)
+
#VacCar <- EvalOutput(VacCar)
 
VacIPD <- EvalOutput(VacIPD)
 
VacIPD <- EvalOutput(VacIPD)
  
Line 184: Line 208:
 
}
 
}
  
if("Iter" %in% colnames(VacCar@output)) N <- max(VacCar@output$Iter) else N <- 1
+
#if("Iter" %in% colnames(VacCar@output)) N <- max(VacCar@output$Iter) else N <- 1
 +
if("Iter" %in% colnames(VacIPD@output)) N <- max(VacIPD@output$Iter) else N <- 1
  
 
if (1==0) {ggplot(VacCar@output, aes(x = Serotype, weight = result(VacCar) / N, fill = Vaccine)) + geom_bar(position = "dodge") + theme_gray(base_size = 24) +  
 
if (1==0) {ggplot(VacCar@output, aes(x = Serotype, weight = result(VacCar) / N, fill = Vaccine)) + geom_bar(position = "dodge") + theme_gray(base_size = 24) +  
Line 190: Line 215:
  
 
ggplot(VacIPD@output, aes(x = Serotype, weight = result(VacIPD) / N, fill = Vaccine)) + geom_bar(position = "dodge") + theme_gray(base_size = 24) +
 
ggplot(VacIPD@output, aes(x = Serotype, weight = result(VacIPD) / N, fill = Vaccine)) + geom_bar(position = "dodge") + theme_gray(base_size = 24) +
labs(title = "Incidence of invasive pneumococcal disease", y = "Number of cases per year")
+
labs(title = "Figure 1. Number of IPD cases per year, by serotype.", y = "Number of cases per year")
  
 
VacIPD@output$Agegroup <- cut(
 
VacIPD@output$Agegroup <- cut(
Line 197: Line 222:
 
include.lowest = TRUE
 
include.lowest = TRUE
 
)
 
)
 +
VacIPD@marginal <- c(VacIPD@marginal, FALSE)
  
 
ggplot(VacIPD@output, aes(x = Vaccine, weight = result(VacIPD) / N, fill = Agegroup)) + geom_bar(position = "stack") + theme_gray(base_size = 24) +
 
ggplot(VacIPD@output, aes(x = Vaccine, weight = result(VacIPD) / N, fill = Agegroup)) + geom_bar(position = "stack") + theme_gray(base_size = 24) +
labs(title = "Incidence of invasive pneumococcal disease", y = "Number of cases per year")
+
labs(title = "Figure 2. Number of IPD  cases per year, by age group.", y = "Number of cases per year")
  
 
######################
 
######################
  
QALYpercase <- Ovariable("QALYpc", ddata = "Op_en6358.qalys_lost") # [[Economic evaluation]] QALYs per case
+
# Sum over Serotype
 +
VacIPD <- oapply(VacIPD, NULL, sum, c("Serotype"), na.rm = TRUE)
  
costpercase <- Ovariable("costpc", ddata = "Op_en6358.costs_incurred") # [[Economic evaluation]] QALYs per case
+
Costs <- EvalOutput(Costs) # Healthcare costs
 +
Total_costs <- oapply(Costs, NULL, sum, c("Outcome", "Age"))
 +
Total_costs <- oapply(Total_costs, Total_costs@output[colnames(Total_costs@output) %in% c("Vaccine", "Iter")], mean)
 +
health_care_costs <- Total_costs
 +
Total_costs <- Total_costs + vacprice
 +
Total_costs@output <- Total_costs@output[c(colnames(Total_costs@output)[colnames(Total_costs@output) %in% c("Vaccine", "Iter")], "Result")]
 +
Total_costs@marginal <- colnames(Total_costs@output) %in% c("Vaccine", "Iter")
  
QALY <- VacIPD * QALYpercase
+
QALYs <- EvalOutput(QALYs)
  
cost <- VacIPD * costpercase + vacprice
+
#### Tässä voi tehdä tapauskohtaista säätöä valitsemalla sopivat indeksit.
  
#### Tässä voi tehdä tapauskohtaista säätöä valitsemalla sopivat indeksit.
+
qalyind <- "Vaccine"
 +
if("Iter" %in% colnames(QALYs@output)) qalyind <- c(qalyind, "Iter")
  
qalyind <- "Vaccine"; if("Iter" %in% colnames(QALY@output)) qalyind <- c(qalyind, "Iter")
+
qalysum <- oapply(QALYs, INDEX = QALYs@output[qalyind], FUN = sum)
costind <- "Vaccine"; if("Iter" %in% colnames(cost@output)) costind <- c(costind, "Iter")
+
qalysum@name <- ""
 +
colnames(qalysum@output)[colnames(qalysum@output) == "QALYsResult"] <- "Result"
  
qalysum <- oapply(QALY, INDEX = QALY@output[qalyind], FUN = sum)
+
costsum <- Total_costs
costsum <- oapply(cost, INDEX = cost@output[costind], FUN = sum)
 
  
 
#### The actual model
 
#### The actual model
Line 223: Line 257:
 
ICER <- EvalOutput(ICER)
 
ICER <- EvalOutput(ICER)
  
cat("QALYs after different vaccination choices\n")
+
if (FALSE){#!is.null(debug_plot)) {
 +
temp <- QALYs
 +
temp <- oapply(temp, NULL, sum, "Outcome")
 +
temp@output$Age <- as.numeric(as.character(temp@output$Age))
 +
plot1 <- ggplot(
 +
temp@output,
 +
aes(x = Age, y = QALYsResult, colour = Vaccine, group = Vaccine)
 +
) + geom_line() + theme_gray(base_size = 24) + labs(title = "QALYs lost due to IPD", y = "QALYs lost per year")
 +
# + facet_wrap(~ Outcome)
 +
 +
temp <- Costs
 +
temp <- oapply(temp, NULL, sum, "Outcome")
 +
temp@output$Age <- as.numeric(as.character(temp@output$Age))
 +
plot2 <- ggplot(
 +
temp@output,
 +
aes(x = Age, y = CostsResult, colour = Vaccine, group = Vaccine)
 +
) + geom_line() + theme_gray(base_size = 24) + labs(title = "IPD health care cost (excl. vaccination)", y = "")
 +
# + facet_wrap(~ Outcome)
 +
 +
temp <- VacIPD
 +
temp@output$Age <- as.numeric(as.character(temp@output$Age))
 +
plot3 <- ggplot(
 +
temp@output,
 +
aes(x = Age, y = VacIPDResult, colour = Vaccine, group = Vaccine)
 +
) + geom_line() + theme_gray(base_size = 24) + labs(title = "IPD cases per year", y = "Cases per year")
 +
}
 +
#if (!is.null(debug_plot)) plot3
 +
#if (!is.null(debug_plot)) plot2
 +
#if (!is.null(debug_plot)) plot1
 +
 
 +
# Rigid implementation which doesnt allow uncertainty...
 +
 
 +
qorder <- qalysum@output$Vaccine[order(result(qalysum), decreasing = TRUE)]
 +
 
 +
QALYs_incremental <- c(0, -diff(result(qalysum)[match(qorder, qalysum@output$Vaccine)]))
 +
QALYs_gained <- cumsum(QALYs_incremental)
 +
Cost_total <- result(Total_costs)[match(qorder, Total_costs@output$Vaccine)]
 +
Cost_incremental <- c(0,diff( Cost_total))
 +
ICER2 <- Cost_incremental / QALYs_incremental
 +
ICER2[1] <- 0
 +
 
 +
ipdtable <- oapply(VacIPD, VacIPD@output["Vaccine"], sum)@output
 +
colnames(ipdtable)[colnames(ipdtable) == "VacIPDResult"] <- "N_of_IPD_cases"
 +
 
 +
oprint(
 +
ipdtable[order(match(ipdtable$Vaccine, qorder)),],
 +
sortable = FALSE,
 +
include.rownames = FALSE,
 +
caption = "Table 1. Number of cases of invasive pneumococcal disease (IPD) per year (see also Figures 1-2 below).",
 +
caption.placement = "top",
 +
digits = rep(0, ncol(ipdtable) + 1)
 +
 +
 
 +
##############################
 +
## print health care costs table
 +
 
 +
sum_table1A <- data.frame(
 +
Vaccine = qorder,
 +
Medical_costs = result(health_care_costs)[match(qorder,health_care_costs@output$Vaccine)] * 1e-6,
 +
 
 +
##  this row was corrected by Markku Nurhonen (mnud) 14 April 2015
 +
##  old version listed prices sometimes in wrong order:  Vaccine_programme_cost = result(vacprice) * 1e-6,
 +
 
 +
        Vaccine_programme_cost = result(vacprice)[match(qorder,vacprice@output$Vaccine)] * 1e-6,
 +
Health_care_costs = result(costsum)[match(qorder,costsum@output$Vaccine)] * 1e-6
 +
)
 +
oprint(
 +
sum_table1A,
 +
sortable = FALSE,
 +
include.rownames = FALSE,
 +
caption = "Table 2. Health care costs (in MEUR)",
 +
caption.placement = "top",
 +
digits = c(0,0,2,2,2)
 +
)
 +
 
 +
##############################
 +
## print summary table
  
oprint(qalysum)
 
  
cat("Costs after different vaccination choices\n")
 
  
oprint(costsum)
+
tekstia<-data.frame(Columns=c(" 1  Vaccine ",
 +
" 2  QALYs gained ",
 +
" 3  Incremental effect ",
 +
" 4  Health-case costs ",
 +
" 5  Incremental cost ",
 +
" 6  ICER ",
 +
"  "),
 +
Content=c("vaccination programme",
 +
"QALYs gained in the Finnish population (*) as compared to 'no vaccination'",
 +
"difference in QALYs gained",
 +
"medical costs due to IPD in the Finnish population(*)  plus the cost of vaccination (in MEUR, 180000 doses) ",
 +
"health-care cost difference (in MEUR)",
 +
"incremental cost-effectiveness ratio (in euros). The programme with the lower ICER is identified as the more cost-effective",
 +
"(*) QALYs and health-care costs refer to the Finnish population of 5.4 million individuals"))
  
cat("Cost-effectiveness after different vaccination choices\n")
+
oprint(
 +
tekstia,
 +
include.rownames = FALSE,
 +
include.colnames = FALSE,
 +
caption = "Columns appearing in Table 3 (below)",
 +
caption.placement = "top"
 +
)
  
oprint(ICER)
 
  
cat("Summary table\n")
 
  
oprint(sumtable())
+
sum_table2 <- data.frame(
 +
Vaccine = qorder,
 +
QALYs_gained = QALYs_gained,
 +
Incremental_effect = QALYs_incremental,
 +
Health_care_costs = Cost_total * 1e-6,
 +
Incremental_cost = Cost_incremental * 1e-6,
 +
ICER = ICER2
 +
)
  
 +
oprint(
 +
sum_table2,
 +
sortable = FALSE,
 +
include.rownames = FALSE,
 +
caption = "Table 3. Cost-effectiveness analysis summary table ",
 +
caption.placement = "top",
 +
digits = c(0,0,0,0,2,2,2)
 +
)
 
</rcode>
 
</rcode>
 +
  
 
== Rationale ==  
 
== Rationale ==  
  
Vaccination programmes are ranked according to their effectiveness (V1 < V2 < V3, etc.). Effectiveness is measured as reduction in invasive pneumococcal disease. Vaccine programmes that are more expensive and less effective as compared with at least one other alternative (strongly dominated) are excluded. Incremental cost-effectiveness ratios (ICER) are calculated for the remaining vaccines:
+
Vaccination programmes are ranked in ascending order according to their effectiveness. The effectiveness is measured as the expected reduction in invasive pneumococcal disease, as predicted by the [[Epidemiological modelling|epidemiological model]].  
 +
Alternatives for which there is at least one other alternative with lower cost and better effectiveness are first excluded.
 +
Each programme ('A') is then compared to the next more effective programme ('B') by the incremental cost-effectiveness ratio (ICER){{reslink|Economic comparison method}}:
 +
 
 +
<math>ICER = \frac{(C_B-S_B) - (C_A-S_A)}{E_B-E_A},</math>
 +
 
 +
where C is the price of the vaccination program, S is the savings in health care costs (as compared to strategy 'no vaccination') and E is the savings in QALYs (as compared to 'no vaccination'). Any programme that is followed by a (more effective) programme with a smaller ICER (i.e. one which produces an additional unit of effect with lower cost) is dropped off from further consideration. The ICERs are then re-calculated and the procedure repeated as many times as needed to eventually identify the most cost-effective alternative. For a tutorial on incremental cost effectiveness analysis, see Phillips (2009) <ref name="whatis">
 +
[http://www.medicine.ox.ac.uk/bandolier/painres/download/whatis/Cost-effect.pdf? Phillips C (2009) What is cost-effectiveness? What is...? series. Hayward Medical Communications.]</ref>.
 +
 
 +
=== Costs ===
 +
 
 +
Health care resource use in secondary health care, per IPD case and sequelae after meningitis, were estimated from the Hospital Discharge Register (2000-2006). For each meningitis and bacteremia case, an episode of care was constructed by linking the outpatient visits and inpatient hospitalizations, using the unique personal identity code. The case fatality ratio (CFR) for IPD was obtained from a Finnish study <ref name="klemets">[http://www.biomedcentral.com/1471-2334/8/96 Klemets et al. (2008) Invasive pneumococcal infections among persons with and without underlying medical conditions: implications for prevention strategies. BMC Infect Dis. 2008 Jul 22;8:96.]</ref>. The unit costs for hospitalizations and outpatient visits were estimated based on individual-level cost accounting data from one hospital district. Other unit cost estimates were mainly taken from a widely used national price list for the unit costs of health care in Finland. The costs were presented in 2012 prices and were evaluated from the health care provider perspective. Future costs and benefits were discounted at 3% per annum. 
 +
 
 +
=== Data ===
 +
Summary table of the data applied in the cost-effectiveness analysis. Note, that the cost-effectiveness analysis is based on age-year (0-100) specific data on IPD and life years lost.
 +
 
 +
1. QALY_menin = QALY losses due to meningitis incl. sequlae (in years, *)
 +
2. QALY_bact = QALY losses due to bacteremia (in years, *)
 +
3. CFR = Case fatality ratio for meningitis and bacteremia
 +
4. Life_y_lost = Life years lost due to IPD (mengitis or bacteremia, *)
 +
5. Cost_ menin = Medical costs attributed to meningitis incl. sequlae (in euros *)
 +
6. Cost_ bact = Medical costs attributed to bacteremia  (in euros *)
 +
7. Menin_proportion = Proportion of meningitis cases of all IPD cases
 +
    (*) a discount rate of 3%/year was applied in all calculations
 +
{| || {{prettytable}}
 +
|+Estimated medical costs and years lost due to a single bacteremia or meningitis episode
 +
|  Age class || QALY_men || QALY_bac || CFR || Life_y_lost || COST_men || COST_bac || Menin_proportion
 +
|---
 +
| <5 years || 0.22 || 0.0079 || 0.014 || 31.1 || 22 070 || 1 986 || 0.037
 +
|---
 +
| 5-64 years || 0.16 || 0.0079 || 0.112 || 20.7 || 26 488 || 9 000 || 0.046
 +
|---
 +
| 65+ years || 0.08 || 0.0079 || 0.196 || 9.4 || 21 529 || 6 823 || 0.019
 +
|---
 +
|}
 +
* Note: The above table lists averages within each age class. Cost-effectiveness analysis is based on age year -specific values.
 +
 
 +
<br>
  
<math>ICER = \frac{(C_2-S_2) - (C_1-S_1)}{E_2-E_1},</math>
+
{|{{prettytable}}
 +
|+Estimated medical costs and years lost in Finland without vaccination (per year)
 +
|---
 +
|Age group||QALY_meningitis||QALY_bacteremia||Life_years_lost||Cost_meningitis||Cost_bacteremia
 +
|---
 +
|0-4y||0.83||0.75||43.64||81 591||189 444
 +
|---
 +
|5-64y||2.89||2.90||895.01||470 949||3 308 515
 +
|---
 +
|65+y||0.51||2.34||555.60||125 916||2 020 437
 +
|---
 +
|}
  
where C is the price of the vaccination program, <br>S is the savings in health care costs and <br>E is the savings in QALYs.
+
<br>
  
Each vaccine (ranked according to their effectiveness) is compared with the next highest ranked vaccine. The least effective vaccine is compared with doing nothing. The most cost-effective vaccine is determined.
+
=== Computation ===
  
=== Calculations ===
+
==== Variable initiation (Only for developers) ====
  
An example involving two vaccine products will be presented on this page. The input
 
required from the user includes (a) the serotype compositions of the two vaccines to be compared, and (b) the prices per dose for the two products. The computation utilises
 
the epidemiological model to predict the incidence of invasive pneumococcal disease under each
 
vaccination programmes. The output will produce the most cost-effective alternative.
 
  
  
Line 263: Line 448:
 
library(OpasnetUtils)
 
library(OpasnetUtils)
  
#### Initiate ovariable ICER and function sumtable
+
# Initiate model components
 +
 
 +
primary_outcomes <- Ovariable("primary_outcomes", ddata = "Op_en6358.primary_outcomes")
 +
secondary_outcomes <- Ovariable("secondary_outcomes", ddata = "Op_en6358.secondary_outcomes")
 +
costs_per_outcomes <- Ovariable("costs_per_outcomes", ddata = "Op_en6358.costs_per_outcomes")
 +
QALYs_per_outcomes <- Ovariable("QALYs_per_outcomes", ddata = "Op_en6358.QALYs_per_outcomes")
 +
 
 +
Outcomes <- Ovariable(
 +
"Outcomes",
 +
dependencies = data.frame(
 +
Name = c("primary_outcomes", "secondary_outcomes", "VacIPD"),
 +
Ident = c(rep("Op_en6358/initiate", 2), "Op_en6353/initiate")
 +
),
 +
formula = function(...) {
 +
# Primaries
 +
out <- VacIPD * primary_outcomes
 +
 +
# Secondaries
 +
temp <- out * secondary_outcomes
 +
 +
# Combine outcomes under single index
 +
temp@output <- temp@output[!colnames(temp@output) %in% "Outcome"]
 +
colnames(temp@output)[colnames(temp@output) == "Outcome_new"] <- "Outcome"
 +
temp@output <- temp@output[colnames(temp@output) %in% colnames(out@output)]
 +
out <- orbind(out, temp)
 +
return(out)
 +
}
 +
)
 +
 
 +
# Healthcare costs
 +
Costs <- Ovariable(
 +
"Costs",
 +
dependencies = data.frame(
 +
Name = c("Outcomes", "costs_per_outcomes"),
 +
Ident = rep("Op_en6358/initiate", 2)
 +
),
 +
formula = function(...) {
 +
out <- Outcomes * costs_per_outcomes
 +
return(out)
 +
}
 +
)
 +
 
 +
# QALYs lost
 +
QALYs <- Ovariable(
 +
"QALYs",
 +
dependencies = data.frame(
 +
Name = c("Outcomes", "QALYs_per_outcomes"),
 +
Ident = rep("Op_en6358/initiate", 2)
 +
),
 +
formula = function(...) {
 +
out <- Outcomes * QALYs_per_outcomes
 +
return(out)
 +
}
 +
)
 +
 
 +
 
 +
# Initiate analysis ovariable ICER and function sumtable
  
 
ICER <- Ovariable("ICER",  
 
ICER <- Ovariable("ICER",  
 
dependencies = data.frame(Name = c(
 
dependencies = data.frame(Name = c(
 
"qalysum",  
 
"qalysum",  
"costsum"
+
"costsum",
 +
"QALYs"
 
)),
 
)),
 
formula = function(...) {
 
formula = function(...) {
  
qalyorder <- oapply(QALY, INDEX = QALY@output["Vaccine"], FUN = sum)
+
qalyorder <- oapply(QALYs, INDEX = QALYs@output["Vaccine"], FUN = sum)
 
qalyorder <- as.character(qalyorder@output$Vaccine[order(result(qalyorder), decreasing = TRUE)])
 
qalyorder <- as.character(qalyorder@output$Vaccine[order(result(qalyorder), decreasing = TRUE)])
  
Line 286: Line 528:
 
costsum2@output <- costsum2@output[!is.na(costsum2@output$Vaccine) , ]
 
costsum2@output <- costsum2@output[!is.na(costsum2@output$Vaccine) , ]
  
out <- (costsum - costsum2) / (qalysum - qalysum2)
+
out <- (costsum - costsum2) / (-1 * (qalysum - qalysum2)) # The formula calls for QALY _savings_, hence * -1
  
 
return(out)
 
return(out)
Line 311: Line 553:
 
}
 
}
  
objects.store(ICER, sumtable)
+
objects.store(primary_outcomes, secondary_outcomes, costs_per_outcomes, QALYs_per_outcomes, Outcomes, Costs, QALYs, ICER, sumtable)
 +
 
 +
cat("Initiated ovariables primary_outcomes, secondary_outcomes, costs_per_outcomes, QALYs_per_outcomes, Outcomes, Costs, QALYs, ICER and function sumtable\n")
 +
 
 +
</rcode>
 +
 
 +
==== Cost calculation (Only for developers) ====
 +
 
 +
<rcode name="cost_calculation" label="Initiate cost calculation objects" embed=1>
 +
 
 +
library(OpasnetUtils)
 +
 
 +
 
 +
cost_table <- opasnet.csv("/0/0e/Pneumococcus_cost_table.csv", wiki = "opasnet_en")
 +
 
 +
 
 +
 
 +
 
 +
 
 +
#cost_table<-re#ad.table("Cost_Table.dat")
 +
## 101*8 taulukko
 +
 
 +
## Title of cost_table:
 +
##  QALY losses and medical costs per case, separately for meningitis and bacteremia.
 +
##  (Note: QALY losses and costs for meningitis cases include sequlae.)
 +
 
 +
 
 +
##Columns of  cost_table :
 +
#1# Age (years)
 +
age<-cost_table[,1]
 +
#2# QALYs lost due to one meningitis case (incl. sequlae)
 +
QALY_men<-cost_table[,2]
 +
#3# QALYs lost due to one bacteremia case
 +
QALY_bac<-cost_table[,3]
 +
#4# case-fatality ratio for a meningitis or bacteremia case (ie for an IPD case)
 +
CFR<-cost_table[,4]
 +
#5# life years lost per one fatal IPD case
 +
LYL<-cost_table[,5]
 +
#6# Medical costs due to one meningitis case (including sequlae)
 +
COST_men<-cost_table[,6]
 +
#7# Medical costs due to one bacteremia case
 +
COST_bac<-cost_table[,7]
 +
#8# Proportion of meningitis cases among all IPD cases (rest are bacteremia)
 +
PROP_men<-cost_table[,8]
 +
 
 +
## Tässä  koodissa "Cost_calculation.R" luetaan taulukko "Cost_Table.dat" ja muunnetaan
 +
## se taukukoksi "Loss_per_IPDcase" vastaamaan yhtä IPD tapausta.
 +
##
 +
## Tällöin kust.vaik.-mallin antamat tulokset saadaan funktiossa
 +
## "calc_qalys_and_med_costs" kun argumentiksi annetaan IPD tapausten määrät
 +
## Suomessa ikävuosittain (101 kpl). Nämä IPD tapausten määrät vastaavat joko
 +
## "ei rokoteta" tilannetta tai lasketaan epidemiologisen mallin avulla eri
 +
## rokotevaihtiehdoille. (opasnetissä IPD-vektorit saadaan siis ovariablien kautta).
 +
##
 +
## Funktio "calc_3_ouput_tables" tuottaa 3 tulostaulukkoa.
 +
## Nämä ovat kust.vaik.-mallin lopputulokset.
 +
 
 +
##                          Markku Nurhonen 15.8.2014
 +
######################################################################################
 +
 
 +
 
 +
 
 +
 
 +
## Adjust matrix "Loss_per_case"  to correspond to one ipd case
 +
## (instead of just meningitis or bacterremia case)
 +
onevec<-rep(1,101)
 +
adjustment<-cbind(onevec,PROP_men,(onevec-PROP_men),onevec,CFR,PROP_men,(onevec-PROP_men),onevec)
 +
Loss_per_case<-cbind(age,QALY_men,QALY_bac,CFR,LYL,COST_men,COST_bac,PROP_men)
 +
Loss_per_IPDcase<-Loss_per_case*adjustment
 +
 
 +
## Matriisia Loss_per_IPDcase käytetään päivitettäessä
 +
## kustannuksia ja QALY-arvoja IPD insidenssien muuttuessa
 +
## rokotteiden vaihtuessa
 +
 
 +
calc_qalys_and_med_costs<-function(ipd_novacc,ipd,Loss_per_IPDcase)
 +
## for two given 101-long IPD vectors
 +
## ipd_novacc = ipd under NO vaccination
 +
## ipd        = ipd under vaccination
 +
## this function gives a list of
 +
## non-fatal,fatal and total QALYs gained:  result[[1]]:(1,2,3)
 +
## and medical costs under novacc and vacc: result[[2]]:(1,2)
 +
## Loss_per_IPDcase is a 101*8 matrix
 +
{
 +
Loss_total_novacc<-matrix(ipd_novacc,101,8)*Loss_per_IPDcase
 +
Loss_total<-matrix(ipd,101,8)*Loss_per_IPDcase
 +
Gain<-apply(Loss_total_novacc-Loss_total,2,sum)  ##koko populaatio
 +
## Now columns 2+3 are nonfatal, 5 is fatal QALYs
 +
## list Qalys gained: nonfatal, fatal and total
 +
QALYs<-c(Gain[2]+Gain[3], Gain[5], Gain[2]+Gain[3]+Gain[5])
 +
## Now columns 6+7 are medical costs
 +
## list med cost under novacc and vacc
 +
medical_cost0<-cbind(Loss_total_novacc[,6]+Loss_total_novacc[,7],Loss_total[,6]+Loss_total[,7])
 +
medical_cost<-apply(medical_cost0,2,sum)
 +
list(QALYs,medical_cost)
 +
}
 +
 
 +
 
 +
calc_3_output_tables<-function(ipd0,ipd1,ipd2,vaccine_cost1,vaccine_cost2,Loss_per_IPDcase)
 +
## for 3 given 101-long IPD vectors
 +
## ipd0 = ipd under NO vaccination
 +
## ipd1= ipd under vaccination 1
 +
## ipd1= ipd under vaccination 2
 +
## and
 +
## vaccine_cost1,vaccine_cost2=
 +
##  per dose costs of vaccines 1 and 2
 +
## Loss_per_IPDcase is a 101*8 matrix
 +
##
 +
## calculate a list of 3 output tables
 +
##  rows and columns as indicated below
 +
##
 +
## typical call of this function:
 +
## calc_3_ouput_tables(IPD_noVac,IPD_pcv10,IPD_pcv13,20,40,Loss_per_IPDcase)
 +
{
 +
c1<-calc_qalys_and_med_costs(ipd0,ipd1,Loss_per_IPDcase)
 +
c2<-calc_qalys_and_med_costs(ipd0,ipd2,Loss_per_IPDcase)
 +
 
 +
## output table 1
 +
## columns(3): vaccination, non fatal, fatal and total qalys gained
 +
## rows: no_vacc, vacc1, vacc2
 +
table1<-rbind(rep(0,3),c1[[1]],c2[[1]])
 +
qalys_gained<-table1[,3]
 +
 
 +
## output table 2
 +
## columns(3): medical costs, vaccination programme costs, health care costs
 +
##rows: no_vacc, vacc1, vacc2
 +
vaccine_cost_tot<-180000*c(0,vaccine_cost1,vaccine_cost2)
 +
med_cost<-c(c1[[2]],c2[[2]][2])
 +
healthcare_cost<-med_cost+vaccine_cost_tot
 +
table2<-cbind(med_cost,vaccine_cost_tot,healthcare_cost)
 +
 
 +
## ouput table3
 +
## columns(5):  1.QALYs gained compared to no_vacc
 +
##              2.incremental effects (=incremental QALYS gained)
 +
##              3.Health care costs  4.incremental costs
 +
##       5.ICER=column4/column2
 +
##rows: no_vacc, vacc1, vacc2
 +
 
 +
incr_qalys<-(c(qalys_gained,0)-c(0,qalys_gained))[seq(3)]
 +
incr_costs<-(c(healthcare_cost,0)-c(0,healthcare_cost))[seq(3)]
 +
table3<-cbind(qalys_gained,incr_qalys,healthcare_cost,incr_costs,c(0,incr_costs[-1]/incr_qalys[-1]))
 +
 
 +
list(table1,table2,table3)
 +
}
 +
 
 +
objects.store(age, QALY_men, QALY_bac, CFR, LYL, COST_men, COST_bac, PROP_men, onevec, adjustment, Loss_per_case,
 +
Loss_per_IPDcase, calc_qalys_and_med_costs, calc_3_output_tables
 +
)
  
cat("Initiated ovariable ICER and function sumtable\n")
+
cat("Objects age, QALY_men, QALY_bac, CFR, LYL, COST_men, COST_bac, PROP_men, onevec, adjustment, Loss_per_case,
 +
Loss_per_IPDcase, calc_qalys_and_med_costs, calc_3_output_tables successfully stored.\n"
 +
)
  
 
</rcode>
 
</rcode>
  
=== Data ===
+
== Sensitivity ==
  
<t2b name="QALYs lost" index="Age" unit="QALYs per case">
+
The effects of alternative vaccine compositions on the outcomes of the cost-effectiveness analysis were assessed. Several modifications for PCV10 and PCV13 were considered. Conclusion: The assumption about serotype 3 in PCV13 is crucial. In addition, assumptions about the role of 6A in PCV10 is important. '''For results, see''' [[Cost_effectiveness_sensitivity|'''Cost_effectiveness_sensitivity''']].
1|10
 
2|9
 
3|9
 
4|8
 
</t2b>
 
  
<t2b name="Costs incurred" index="Age" unit="Euro per case">
+
If serotype 3 is not included as a vaccine type in PCV13, then the differences between PCV10 and PCV13 in quality adjusted life years (QALYs) gained and medical costs are relatively minor. Therefore, in view of the intrinsic uncertainties in the model, PCV10 and PCV13 can be regarded as equally effective.
1|1000
 
2|1000
 
3|500
 
4|400
 
</t2b>
 
  
  
Line 337: Line 717:
  
 
{{pneumococcal vaccine}}
 
{{pneumococcal vaccine}}
 +
{{method|moderator=Mnud}}
  
 
== References ==
 
== References ==
  
 
<references/>
 
<references/>
 +
 +
== Related files ==
 +
 +
* {{#l:GSK 04  Economic evaluation_final_for Opasnet.docx}}
  
 
== Comment the content ==
 
== Comment the content ==
  
 
{{commenting tool}}
 
{{commenting tool}}

Latest revision as of 11:27, 23 March 2016

Progression class
In Opasnet many pages being worked on and are in different classes of progression. Thus the information on those pages should be regarded with consideration. The progression class of this page has been assessed:
This page is reviewed
It has been read with a critical eye and commented on by an outside source, and given impairment suggestions have been included in the page. An equivalent to a peer-reviewed article.
The content and quality of this page is being curated by THL.
Error creating thumbnail: Unable to save thumbnail to destination

The quality was last checked: 2016-03-21.

Question

How to identify the most cost-effective pneumococcal conjugate vaccine to the national immunisation programme?

  • The health benefit (effectiveness) of the pneumococcal infant immunisation programme is assessed by the expected gain in Quality-Adjusted Life Years (QALYs), corresponding to the expected reduction in the annual number of invasive pneumococcal disease in the whole Finnish population.
  • The perspective of the analysis is that of the health care provider.
  • The analysis is based on incremental cost effectiveness


Answer

A general approach to answer the question is based on the concept of incremental cost-effectiveness. For example, if there are only two vaccines to be compared, the more effective (and more expensive vaccine) is said to be more cost-effective if the incremental cost effectiveness ratio (ICER), comparing the vaccine to the less effective vaccine, exceeds the ICER of the less effective vaccine as compared to the alternative 'no vaccination'. The general principle is explained below (see 'Rationale').

The importance of alternative assumptions about protection against individual serotypes were assessed in a sensitivity analysis. Several 'modifications' for PCV10 and PCV13 were considered, regarding assumptions about the extent of indirect protection against serotypes 3, 6A, 6A, and 19A. A detailed account of the sensitivity analysis is on page Cost_effectiveness_sensitivity. These analyses included determining the difference in the QALYs gained under PCV10 and PCV13.

In summary, if PCV13 does not induce population-level (i.e. indirect) effects on serotype 3, the difference between PCV10 and PCV13 in quality adjusted life years (QALYs) gained and medical costs are relatively minor. Different assumptions about the roles of 6A protection by PCV10 and 6C protection by PCV13 lead to different preferences, with minor absolute differences in QALYs with respect to the overall effectiveness (QALYs gained) due to PCV vaccination.

Therefore, in view of the intrinsic uncertainties in the evaluation, PCV10 and PCV13 can be regarded as equally effective. This also means that incremental cost effectiveness ratios do not need to be calculated.

Evaluation tool

The following programme can be used to calculate the incremental cost effectiveness ratios (ICERs) for two alternative vaccination programmes. The input required is:

(a) the serotype compositions of the two vaccines to be compared (the defaults are PCV10 and PCV13), and

(b) the prices per dose for the two vaccine products.

The computation utilises the epidemiological model[1] to predict the annual number of invasive pneumococcal disease (IPD) under both vaccination programmes and, for comparison, for the scenario 'no vaccination'. The summary table presents the ICERs. The vaccine programme with the lower ICER is identified as the more cost-effective of the two alternatives. Note, that some of the ouput is irrelevant if the vaccine programme is cost saving (i.e, if savings in medical costs exceed vaccine programme cost).

N.B. Some assumptions applied int the sensitivity analysis cannot be realised with the current version of the programme. In particular, there is currently no option to include direct protection only (i.e. vaccine efficacy for the vaccinated cohorts only) for individual serotypes. However, the sensitivity analyses show that the difference between 'direct protection only' and 'no protection at all' is usually not decisive for the overall effectiveness of conjugate vaccination. In other words, the most important assumptions concers indirect protection.


  • Instructions for user: Choose the desired vaccine compositions and their prices and then press "Run code".

The results of the cost-effectiveness analysis will be displayed on a separate tab.

Scenarios

Please choose the vaccines to be compared::
PCV-10
PCV-13

What is the price of a single PCV10 vaccination?:

What is the price of a single PCV13 vaccination?:

Do you want to adjust PCV-10 or PCV-13 vaccine composition?:

User defined vaccine

Choose the serotypes for the PCV-10 vaccine composition:
1
3
4
5
6A
6B
6C
7F
8
9N
9V
10
11
12
14
15
16
18C
19A
19F
20
22
23A
23F
33
35
38
Other

Choose the serotypes for the PCV-13 vaccine composition:
1
3
4
5
6A
6B
6C
7F
8
9N
9V
10
11
12
14
15
16
18C
19A
19F
20
22
23A
23F
33
35
38
Other

+ Show code


Rationale

Vaccination programmes are ranked in ascending order according to their effectiveness. The effectiveness is measured as the expected reduction in invasive pneumococcal disease, as predicted by the epidemiological model. Alternatives for which there is at least one other alternative with lower cost and better effectiveness are first excluded. Each programme ('A') is then compared to the next more effective programme ('B') by the incremental cost-effectiveness ratio (ICER)R↻ :

Failed to parse (Missing <code>texvc</code> executable. Please see math/README to configure.): ICER = \frac{(C_B-S_B) - (C_A-S_A)}{E_B-E_A},

where C is the price of the vaccination program, S is the savings in health care costs (as compared to strategy 'no vaccination') and E is the savings in QALYs (as compared to 'no vaccination'). Any programme that is followed by a (more effective) programme with a smaller ICER (i.e. one which produces an additional unit of effect with lower cost) is dropped off from further consideration. The ICERs are then re-calculated and the procedure repeated as many times as needed to eventually identify the most cost-effective alternative. For a tutorial on incremental cost effectiveness analysis, see Phillips (2009) [2].

Costs

Health care resource use in secondary health care, per IPD case and sequelae after meningitis, were estimated from the Hospital Discharge Register (2000-2006). For each meningitis and bacteremia case, an episode of care was constructed by linking the outpatient visits and inpatient hospitalizations, using the unique personal identity code. The case fatality ratio (CFR) for IPD was obtained from a Finnish study [3]. The unit costs for hospitalizations and outpatient visits were estimated based on individual-level cost accounting data from one hospital district. Other unit cost estimates were mainly taken from a widely used national price list for the unit costs of health care in Finland. The costs were presented in 2012 prices and were evaluated from the health care provider perspective. Future costs and benefits were discounted at 3% per annum.

Data

Summary table of the data applied in the cost-effectiveness analysis. Note, that the cost-effectiveness analysis is based on age-year (0-100) specific data on IPD and life years lost.

1. QALY_menin = QALY losses due to meningitis incl. sequlae (in years, *)
2. QALY_bact = QALY losses due to bacteremia (in years, *)
3. CFR = Case fatality ratio for meningitis and bacteremia
4. Life_y_lost = Life years lost due to IPD (mengitis or bacteremia, *)
5. Cost_ menin = Medical costs attributed to meningitis incl. sequlae (in euros *)
6. Cost_ bact = Medical costs attributed to bacteremia  (in euros *)
7. Menin_proportion = Proportion of meningitis cases of all IPD cases
   (*) a discount rate of 3%/year was applied in all calculations
Estimated medical costs and years lost due to a single bacteremia or meningitis episode
Age class QALY_men QALY_bac CFR Life_y_lost COST_men COST_bac Menin_proportion
<5 years 0.22 0.0079 0.014 31.1 22 070 1 986 0.037
5-64 years 0.16 0.0079 0.112 20.7 26 488 9 000 0.046
65+ years 0.08 0.0079 0.196 9.4 21 529 6 823 0.019
  • Note: The above table lists averages within each age class. Cost-effectiveness analysis is based on age year -specific values.


Estimated medical costs and years lost in Finland without vaccination (per year)
Age group QALY_meningitis QALY_bacteremia Life_years_lost Cost_meningitis Cost_bacteremia
0-4y 0.83 0.75 43.64 81 591 189 444
5-64y 2.89 2.90 895.01 470 949 3 308 515
65+y 0.51 2.34 555.60 125 916 2 020 437


Computation

Variable initiation (Only for developers)

+ Show code

Cost calculation (Only for developers)

+ Show code

Sensitivity

The effects of alternative vaccine compositions on the outcomes of the cost-effectiveness analysis were assessed. Several modifications for PCV10 and PCV13 were considered. Conclusion: The assumption about serotype 3 in PCV13 is crucial. In addition, assumptions about the role of 6A in PCV10 is important. For results, see Cost_effectiveness_sensitivity.

If serotype 3 is not included as a vaccine type in PCV13, then the differences between PCV10 and PCV13 in quality adjusted life years (QALYs) gained and medical costs are relatively minor. Therefore, in view of the intrinsic uncertainties in the model, PCV10 and PCV13 can be regarded as equally effective.


See also

Tendering process for pneumococcal conjugate vaccine
Parts of the assessment

Comparison criteria for vaccine   · Epidemiological modelling   · Economic evaluation

Background information

Sensitivity analysis · Replacement   · Pneumococcal vaccine products   · Finnish vaccination schedule   · Selected recent publications


Help for discussion and wiki editing

Pages in Finnish

Pneumokokkirokotteen hankinta  · Rokotteen vertailuperusteet · Epidemiologinen malli · Taloudellinen arviointi · Pneumokokkirokotteen turvallisuus


Work scheduling · Monitoring the effectiveness of the pneumococcal conjugate vaccine · Glossary of vaccine terminology



References

Related files

Comment the content

Current comments that have not yet been included in the main page or talk page.


You can give comments about the content without login simply by writing your comments into the text box below. The page moderator will include your comments in the actual content of the page and then moves the comment to the archive: Show results


Your comment about the page content or discussion:

To what part of the page does you comment refer?:

Comments to be removed (after they have been moved to the page text)

ID of the comment to be removed:

Reason to remove: