def report_CEA_CBA(sim_outcomes_none, sim_outcomes_anticoag): """ performs cost-effectiveness and cost-benefit analyses :param sim_outcomes_none: outcomes of a cohort simulated under no therapy :param sim_outcomes_anticoag: outcomes of a cohort simulated under anticoagultation therapy """ # define two strategies no_therapy_strategy = Econ.Strategy( name='No Therapy', cost_obs=sim_outcomes_none.costs, effect_obs=sim_outcomes_none.utilities, color='red' ) anticoag_therapy_strategy = Econ.Strategy( name='Anticoagulation Therapy', cost_obs=sim_outcomes_anticoag.costs, effect_obs=sim_outcomes_anticoag.utilities, color='blue' ) # do cost-effectiveness analysis # (the first strategy in the list of strategies is assumed to be the 'Base' strategy) CEA = Econ.CEA( strategies=[no_therapy_strategy, anticoag_therapy_strategy], if_paired=False ) # plot cost-effectiveness figure CEA.plot_CE_plane( title='Cost-Effectiveness Analysis', x_label='Additional QALYs', y_label='Additional Cost', x_range=(-0.6, 1.5), y_range=(-5000, 50000), interval_type='c' ) # report the CE table CEA.build_CE_table( interval_type='c', alpha=D.ALPHA, cost_digits=0, effect_digits=2, icer_digits=2) # cost-benefit analysis CBA = Econ.CBA( strategies=[no_therapy_strategy, anticoag_therapy_strategy], wtp_range=[0, 100000], if_paired=False ) # show the net monetary benefit figure CBA.plot_incremental_nmbs( title='Cost-Benefit Analysis', x_label='Willingness-to-pay per QALY ($)', y_label='Incremental Net Monetary Benefit ($)', interval_type='c', show_legend=True, figure_size=(6, 5) )
def update(self, time, current_state, next_state): # cost (per unit of time) during the period since the last recording until now cost = self.params.annualStateCosts[current_state.value] if current_state == HealthStates.POST_STROKE: cost += self.params.annuaAntiCoagCost # discounted cost and utility (continuously compounded) discounted_cost = Econ.pv_continuous_payment(payment=cost, discount_rate=self.params.discountRate, discount_period=(self.tLastRecorded, time)) # add discounted stoke cost, if stroke occurred if next_state == HealthStates.STROKE: discounted_cost += Econ.pv_single_payment(payment=self.params.strokeCost, discount_rate=self.params.discountRate, discount_period=time, discount_continuously=True) # utility (per unit of time) during the period since the last recording until now utility = self.params.annualStateUtilities[current_state.value] discounted_utility = Econ.pv_continuous_payment(payment=utility, discount_rate=self.params.discountRate, discount_period=(self.tLastRecorded, time)) # update total discounted cost and utility self.totalDiscountedCost += discounted_cost self.totalDiscountedUtility += discounted_utility # update the time since last recording to the current time self.tLastRecorded = time
def update(self, time, current_state, next_state): """ updates the discounted total cost and health utility :param time: simulation time :param current_state: current health state :param next_state: next health state """ # cost and utility (per unit of time) during the period since the last recording until now cost = self.params.annualStateCosts[ current_state.value] + self.params.annualTreatmentCost utility = self.params.annualStateUtilities[current_state.value] # discounted cost and utility (continuously compounded) discounted_cost = Econ.pv_continuous_payment( payment=cost, discount_rate=self.params.discountRate, discount_period=(self.tLastRecorded, time)) discounted_utility = Econ.pv_continuous_payment( payment=utility, discount_rate=self.params.discountRate, discount_period=(self.tLastRecorded, time)) # update total discounted cost and utility self.totalDiscountedCost += discounted_cost self.totalDiscountedUtility += discounted_utility # update the time since last recording to the current time self.tLastRecorded = time
def update(self, k, current_state, next_state): """ updates the discounted total cost and health utility :param k: simulation time step :param current_state: current health state :param next_state: next health state """ # update cost cost = 0.5 * (self.params.annualStateCosts[current_state.value] + self.params.annualStateCosts[next_state.value]) # update utility utility = 0.5 * (self.params.annualStateUtilities[current_state.value] + self.params.annualStateUtilities[next_state.value]) # add the cost of treatment # if HIV death will occur, add the cost for half-year of treatment if next_state == HealthStates.HIV_DEATH: cost += 0.5 * self.params.annualTreatmentCost else: cost += 1 * self.params.annualTreatmentCost # update total discounted cost and utility (corrected for the half-cycle effect) self.totalDiscountedCost += Econ.pv_single_payment( payment=cost, discount_rate=self.params.discountRate / 2, discount_period=2 * k + 1) self.totalDiscountedUtility += Econ.pv_single_payment( payment=utility, discount_rate=self.params.discountRate / 2, discount_period=2 * k + 1)
def report_CEA_CBA(multi_cohort_outcomes_mono, multi_cohort_outcomes_combo): """ performs cost-effectiveness and cost-benefit analyses :param multi_cohort_outcomes_mono: outcomes of a multi-cohort simulated under mono therapy :param multi_cohort_outcomes_combo: outcomes of a multi-cohort simulated under combination therapy """ # define two strategies mono_therapy_strategy = Econ.Strategy( name='Mono Therapy', cost_obs=multi_cohort_outcomes_mono.meanCosts, effect_obs=multi_cohort_outcomes_mono.meanQALYs, color='green') combo_therapy_strategy = Econ.Strategy( name='Combination Therapy', cost_obs=multi_cohort_outcomes_combo.meanCosts, effect_obs=multi_cohort_outcomes_combo.meanQALYs, color='blue') # do CEA CEA = Econ.CEA(strategies=[mono_therapy_strategy, combo_therapy_strategy], if_paired=True) # show the cost-effectiveness plane CEA.plot_CE_plane(title='Cost-Effectiveness Analysis', x_label='Additional Discounted QALY', y_label='Additional Discounted Cost', fig_size=(6, 5), add_clouds=True, transparency=0.2) # report the CE table CEA.build_CE_table( interval_type='p', # uncertainty (projection) interval alpha=D.ALPHA, cost_digits=0, effect_digits=2, icer_digits=2, file_name='CETable.csv') # CBA NBA = Econ.CBA(strategies=[mono_therapy_strategy, combo_therapy_strategy], wtp_range=(0, 50000), if_paired=True) # show the net monetary benefit figure NBA.plot_incremental_nmbs( title='Cost-Benefit Analysis', x_label='Willingness-To-Pay for One Additional QALY ($)', y_label='Incremental Net Monetary Benefit ($)', interval_type='p', show_legend=True, figure_size=(6, 5), )
def report_CEA_CBA(sim_outcomes_none, sim_outcomes_anti): """ performs cost-effectiveness and cost-benefit analyses :param sim_outcomes_mono: outcomes of a cohort simulated under mono therapy :param sim_outcomes_combo: outcomes of a cohort simulated under combination therapy """ # define two strategies no_therapy_strategy = Econ.Strategy(name='No Anticoagulation ', cost_obs=sim_outcomes_none.costs, effect_obs=sim_outcomes_none.utilities, color='green') anti_therapy_strategy = Econ.Strategy( name='With Anticoagulation', cost_obs=sim_outcomes_anti.costs, effect_obs=sim_outcomes_anti.utilities, color='blue') # do CEA CEA = Econ.CEA(strategies=[no_therapy_strategy, anti_therapy_strategy], if_paired=False) # plot cost-effectiveness figure CEA.plot_CE_plane(title='Cost-Effectiveness Analysis', x_label='Additional QALYs', y_label='Additional Cost', interval_type='c', x_range=(-0.5, 1), y_range=(-1000, 10000)) # report the CE table CEA.build_CE_table(interval_type='c', alpha=D.ALPHA, cost_digits=0, effect_digits=2, icer_digits=2, file_name='CETable.csv') # CBA NBA = Econ.CBA(strategies=[no_therapy_strategy, anti_therapy_strategy], wtp_range=[0, 50000], if_paired=False) # show the net monetary benefit figure NBA.plot_incremental_nmbs(title='Cost-Benefit Analysis', x_label='Willingness-to-pay per QALY ($)', y_label='Incremental Net Monetary Benefit ($)', interval_type='c', show_legend=True, figure_size=(6, 5))
def update(self, t, current_state, next_state): cost = 0.5 * (self.params.annualStateCosts[current_state.value] + self.params.annualStateCosts[next_state.value]) utility = 0.5 * (self.params.annualStateUtilities[current_state.value] + self.params.annualStateUtilities[next_state.value]) self.totalDiscountedCost += Econ.pv_single_payment( payment=cost, discount_rate=self.params.discountRate / 2, discount_period=2 * t + 1) self.totalDiscountedUtility += Econ.pv_single_payment( payment=utility, discount_rate=self.params.discountRate / 2, discount_period=2 * t + 1)
import SimPy.EconEval as Econ print('Present value of $10 collected in year 20 at discount rate 5%:') print(Econ.pv_single_payment(payment=10, discount_rate=0.05, discount_period=20)) print('\nPresent value of $10 collected in year 20 at discount rate 5% (discounted continuously):') print('These 2 numbers should be almost the same:') print(Econ.pv_single_payment(payment=10, discount_rate=0.05, discount_period=20, discount_continuously=True)) print(Econ.pv_single_payment(payment=10, discount_rate=0.05 / 100, discount_period=20 * 100, discount_continuously=False)) print('\nPresent value of a continuous payment of $10 over the period [10, 20] at discount rate 5%:') print(Econ.pv_continuous_payment(payment=10, discount_rate=0.05, discount_period=(10, 20))) print('\nPresent value of a continuous payment of $10 over the period [10, 20] at discount rate 0%:') print(Econ.pv_continuous_payment(payment=10, discount_rate=0, discount_period=(10, 20))) print('\nEquivalent annual value of $50 over 10 years at discount rate 5%:') print(Econ.equivalent_annual_value(present_value=50, discount_rate=0.05, discount_period=10))
from SimPy import EconEval as EV S0 = EV.Strategy(name='Base', cost_obs=[100], effect_obs=[1]) S1 = EV.Strategy(name='A1', cost_obs=[800], effect_obs=[0.5]) S2 = EV.Strategy(name='A2', cost_obs=[2000], effect_obs=[10]) S3 = EV.Strategy(name='A3', cost_obs=[500], effect_obs=[7]) S4 = EV.Strategy(name='A4', cost_obs=[-100], effect_obs=[2]) S5 = EV.Strategy(name='A5', cost_obs=[200], effect_obs=[2]) S6 = EV.Strategy(name='A6', cost_obs=[1000], effect_obs=[7.2]) S7 = EV.Strategy(name='A7', cost_obs=[1100], effect_obs=[7.3]) cea = EV.CEA(strategies=[S0, S1, S2, S3, S4, S5, S6, S7], if_paired=False, health_measure='u') # show the ce plane: cea.plot_CE_plane() # build table cea.build_CE_table(interval_type='n') print('On frontier') frontier_strategies = cea.get_strategies_on_frontier() for i, s in enumerate(frontier_strategies): print(s.name) if i > 0: print('incCost:', s.incCost.get_mean()) print('incEffect:', s.incEffect.get_mean()) print('ICER:', s.icer.get_ICER())
import SimPy.EconEval as EconEval np.random.seed(573) cost_base = np.random.normal(loc=10000, scale=100, size=1000) effect_base = np.random.normal(loc=1, scale=.1, size=1000) cost_intervention = np.random.normal(loc=20000, scale=200, size=1000) effect_intervention = np.random.normal(loc=2, scale=.2, size=1000) print('') # ICER calculation assuming paired observations ICER_paired = EconEval.ICER_Paired(name='Testing paired ICER', costs_new=cost_intervention, effects_new=effect_intervention, costs_base=cost_base, effects_base=effect_base) print('Paired ICER:' '\n\tICER: {} ' '\n\tCI (boostrap): {} ' '\n\tCI (Bayesian): {} ' '\n\tPI: {}'.format(ICER_paired.get_ICER(), ICER_paired.get_CI(0.05), ICER_paired.get_CI(0.05, method='Bayesian'), ICER_paired.get_PI(0.05))) # ICER calculation assuming independent observations ICER_indp = EconEval.ICER_Indp('Testing independent ICER', costs_new=cost_intervention, effects_new=effect_intervention, costs_base=cost_base,
import numpy as np from SimPy import EconEval as EV np.random.seed(seed=1) S0 = EV.Strategy(name='Base', cost_obs=np.random.normal(loc=100, scale=10, size=100), effect_obs=np.random.normal(loc=1, scale=.2, size=100), color='red') S1 = EV.Strategy(name='A1', cost_obs=np.random.normal(loc=800, scale=50, size=100), effect_obs=np.random.normal(loc=0.5, scale=0.1, size=100), color='blue') S2 = EV.Strategy(name='A2', cost_obs=np.random.normal(loc=2000, scale=200, size=100), effect_obs=np.random.normal(loc=10, scale=1, size=100), color='green') S3 = EV.Strategy(name='A3', cost_obs=np.random.normal(loc=500, scale=50, size=100), effect_obs=np.random.normal(loc=7, scale=1, size=100), color='orange') S4 = EV.Strategy(name='A4', cost_obs=np.random.normal(loc=-100, scale=10, size=100), effect_obs=np.random.normal(loc=2, scale=0.1, size=100), color='purple') cea = EV.CEA(strategies=[S0, S1, S2, S3, S4], if_paired=False, health_measure='u') print('On frontier') for s in cea.get_strategies_on_frontier():
def populate_sets_of_scenarios(list_of_scenario_sets, save_cea_results=False, colors_of_scenarios=None, interval_type='n', effect_multiplier=1, cost_multiplier=1, switch_cost_effect_on_figure=False, wtp_range=None): """ :param list_of_scenario_sets: (list) of sets of scenarios :param save_cea_results: set it to True if the CE table should be generated :param colors_of_scenarios: (dictionary) of colors for scenarios :param interval_type: select from Econ.Interval (no interval, CI, or PI) :param effect_multiplier: :param cost_multiplier: :param switch_cost_effect_on_figure: displays cost on the x-axis and effect on the y-axis :param wtp_range: for net monetary benefit analysis """ # populate series to display on the cost-effectiveness plane for i, scenario_set in enumerate(list_of_scenario_sets): if scenario_set.ifPopulated: continue # create the base strategy scn = scenario_set.scenarioDF.scenarios['Base'] base_strategy = Econ.Strategy( name='Base', label='Base', cost_obs=scn.outcomes[COST_MEASURE], effect_obs=scn.outcomes[HEALTH_MEASURE], color=None if colors_of_scenarios is None else colors_of_scenarios[0]) # add base scenario_set.strategies = [base_strategy] # add other scenarios i = 0 for key, scenario in scenario_set.scenarioDF.scenarios.items(): # add only non-Base strategies that can be on this series if scenario.name != 'Base' and scenario_set.if_acceptable( scenario): # find labels of each strategy label_list = [] for varCon in scenario_set.varConditions: if varCon.ifIncludedInLabel: # value of this variable value = scenario.variables[varCon.varName] # if there is not label rules if varCon.labelRules is None: if varCon.labelFormat == '': label_list.append(str(value) + ',') else: label_list.append( varCon.labelFormat.format(value) + ', ') else: label = varCon.get_label(value) if label == '': pass else: label_list.append(label + ', ') for outcomeCon in scenario_set.outcomeConditions: if outcomeCon.ifIncludedInLabel: # value of this variable value = Stat.SummaryStat( name=outcomeCon.outcomeName, data=scenario.outcomes[ outcomeCon.outcomeName]).get_mean() # if there is not label rules if outcomeCon.labelRules is None: if outcomeCon.labelFormat == '': label_list.append(str(value) + ',') else: label_list.append( outcomeCon.labelFormat.format(value) + ', ') else: label = outcomeCon.get_label(value) if label == '': pass else: label_list.append(label + ', ') label = ''.join(str(x) for x in label_list) if len(label) > 0: if label[-1] == ' ' or label[-1] == ',': label = label[:-1] if label[-1] == ' ' or label[-1] == ',': label = label[:-1] # legends scenario_set.legend.append(label) # color of this strategy color = None if colors_of_scenarios is not None: color = colors_of_scenarios[i + 1] if scenario_set.xyLabelsProvided: label = scenario_set.xyLabels[i] scenario_set.strategies.append( Econ.Strategy( name=scenario.name, label=label, cost_obs=scenario.outcomes[COST_MEASURE], effect_obs=scenario.outcomes[HEALTH_MEASURE], color=color)) i += 1 # do CEA on this series scenario_set.build_CE_curve( save_cea_results=save_cea_results, interval_type=interval_type, effect_multiplier=effect_multiplier, cost_multiplier=cost_multiplier, switch_cost_effect_on_figure=switch_cost_effect_on_figure, wtp_range=wtp_range) scenario_set.ifPopulated = True
def build_CE_curve(self, save_cea_results=False, interval_type='n', effect_multiplier=1, cost_multiplier=1, switch_cost_effect_on_figure=False, wtp_range=None): # cost-effectiveness analysis self.CEA = Econ.CEA(self.strategies, if_paired=True, health_measure='d') # CBA if wtp_range is not None: self.CBA = Econ.CBA(self.strategies, wtp_range=wtp_range, if_paired=True, health_measure='d') # if to save the results of the CEA if save_cea_results: self.CEA.build_CE_table(interval_type=interval_type, file_name='CEA Table-' + self.name + '.csv', cost_multiplier=cost_multiplier, effect_multiplier=effect_multiplier, effect_digits=0) # if the CE frontier should be calculated if self.ifFindFrontier: # find the (x, y)'s of strategies on the frontier for idx, strategy in enumerate( self.CEA.get_strategies_on_frontier()): if switch_cost_effect_on_figure: self.frontierXValues.append(strategy.dCost.get_mean() * cost_multiplier) self.frontierYValues.append(strategy.dEffect.get_mean() * effect_multiplier) else: self.frontierXValues.append(strategy.dEffect.get_mean() * effect_multiplier) self.frontierYValues.append(strategy.dCost.get_mean() * cost_multiplier) self.frontierLabels.append(strategy.name) if interval_type != 'n': effect_interval = strategy.dEffect.get_interval( interval_type=interval_type, alpha=ALPHA, multiplier=effect_multiplier) cost_interval = strategy.dCost.get_interval( interval_type=interval_type, alpha=ALPHA, multiplier=effect_multiplier) if switch_cost_effect_on_figure: self.frontierYIntervals.append(effect_interval) self.frontierXIntervals.append(cost_interval) else: self.frontierXIntervals.append(effect_interval) self.frontierYIntervals.append(cost_interval) #else: # the CE frontier needs not to be calculated # find the (x, y) values of strategies to display on CE plane # remove the base strategy if not self.xyLabelsProvided: self.xyLabels = [] for strategy in [s for s in self.CEA.strategies if s.idx > 0]: if switch_cost_effect_on_figure: self.allDeltaEffects = np.append( self.allDeltaEffects, strategy.dEffectObs * effect_multiplier) self.allDeltaCosts = np.append( self.allDeltaCosts, strategy.dCostObs * cost_multiplier) self.xValues.append(strategy.dCost.get_mean() * cost_multiplier) self.yValues.append(strategy.dEffect.get_mean() * effect_multiplier) self.xValuesByScenario.append(strategy.dCostObs * cost_multiplier) self.yValuesByScenario.append(strategy.dEffectObs * effect_multiplier) else: self.allDeltaEffects = np.append( self.allDeltaEffects, strategy.effectObs * effect_multiplier) self.allDeltaCosts = np.append( self.allDeltaCosts, strategy.costObs * cost_multiplier) self.xValues.append(strategy.dEffect.get_mean() * effect_multiplier) self.yValues.append(strategy.dCost.get_mean() * cost_multiplier) self.xValuesByScenario.append(strategy.dEffectObs * effect_multiplier) self.yValuesByScenario.append(strategy.dCostObs * cost_multiplier) if not self.xyLabelsProvided: self.xyLabels.append(strategy.label) if interval_type != 'n': effect_interval = strategy.dEffect.get_interval( interval_type=interval_type, alpha=ALPHA, multiplier=effect_multiplier) cost_interval = strategy.dCost.get_interval( interval_type=interval_type, alpha=ALPHA, multiplier=cost_multiplier) # print(strategy.name, cost_interval, effect_interval) if switch_cost_effect_on_figure: self.yIntervals.append(effect_interval) self.xIntervals.append(cost_interval) else: self.xIntervals.append(effect_interval) self.yIntervals.append(cost_interval)
import numpy as np from SimPy import EconEval as ce N = 100 np.random.seed(573) s_center = np.array([[10000, 0.2], [20000, 0.7], [50000, 1.2]]) s0 = ce.Strategy("s0", s_center[0, 0] + np.random.normal(0, 1000, N), s_center[0, 1] + np.random.normal(0, 0.01, N), color='red') s1 = ce.Strategy("s1", s_center[1, 0] + np.random.normal(0, 1000, N), s_center[1, 1] + np.random.normal(0, 0.01, N), color='blue') s2 = ce.Strategy("s2", s_center[2, 0] + np.random.normal(0, 1000, N), s_center[2, 1] + np.random.normal(0, 0.05, N), color='green') cea = ce.CEA([s0, s1, s2], if_paired=True) cea.plot_CE_plane() nmb_paired = ce.CBA([s0, s1, s2], wtp_range=[0, 100000], if_paired=True) nmb_indp = ce.CBA([s0, s1, s2], wtp_range=[0, 100000], if_paired=False) # list of frontier strategies as input # Try NMB_Lines figure - paired CI nmb_paired.plot_incremental_nmbs(title="deltaNMB lines for paired CI",
import SimPy.EconEval as EconEval np.random.seed(573) cost_base = np.random.normal(loc=10000, scale=100, size=1000) effect_base = np.random.normal(loc=2, scale=.1, size=1000) cost_intervention = np.random.normal(loc=20000, scale=200, size=1000) effect_intervention = np.random.normal(loc=1, scale=.2, size=1000) print('') # ICER calculation assuming paired observations ICER_paired = EconEval.ICER_Paired('Testing paired ICER', cost_intervention, effect_intervention, cost_base, effect_base, health_measure='d') print( 'Paired ICER:\n\tICER: {} \n\tCI (boostrap): {} \n\tCI (Bayesian): {} \n\tPI: ' .format(ICER_paired.get_ICER(), ICER_paired.get_CI(0.05, 1000), ICER_paired.get_CI(0.05, 1000, method='Bayesian'), ICER_paired.get_PI(0.05))) # ICER calculation assuming independent observations ICER_indp = EconEval.ICER_Indp('Testing independent ICER', cost_intervention, effect_intervention, cost_base, effect_base, health_measure='d')
import numpy as np from SimPy import EconEval as ce np.random.seed(573) # create the centers of strategies s_center = np.random.normal(0, 5000, (10, 2)) s0 = ce.Strategy("s1", s_center[0, 0] + np.random.normal(0, 200, 10), s_center[0, 1] + np.random.normal(0, 200, 10)) s1 = ce.Strategy("s2", s_center[1, 0] + np.random.normal(0, 200, 10), s_center[1, 1] + np.random.normal(0, 100, 10)) s2 = ce.Strategy("s3", s_center[2, 0] + np.random.normal(0, 200, 10), s_center[2, 1] + np.random.normal(0, 200, 10)) s3 = ce.Strategy("s4", s_center[3, 0] + np.random.normal(0, 200, 10), s_center[3, 1] + np.random.normal(0, 200, 10)) s4 = ce.Strategy("s5", s_center[4, 0] + np.random.normal(0, 200, 10), s_center[4, 1] + np.random.normal(0, 200, 10)) s5 = ce.Strategy("s6", s_center[5, 0] + np.random.normal(0, 200, 10), s_center[5, 1] + np.random.normal(0, 200, 10)) s6 = ce.Strategy("s7", s_center[6, 0] + np.random.normal(0, 200, 10), s_center[6, 1] + np.random.normal(0, 200, 10)) s7 = ce.Strategy("s8", s_center[7, 0] + np.random.normal(0, 200, 10), s_center[7, 1] + np.random.normal(0, 200, 10)) s8 = ce.Strategy("s9", s_center[8, 0] + np.random.normal(0, 200, 10), s_center[8, 1] + np.random.normal(0, 200, 10)) s9 = ce.Strategy("s10", s_center[9, 0] + np.random.normal(0, 200, 10), s_center[9, 1] + np.random.normal(0, 200, 10)) # create a CEA object -- unpaired myCEA = ce.CEA([s0, s1, s2, s3, s4, s5, s6, s7, s8, s9], if_paired=False)