def plot_select_sweeps(): """ Plot Vancomycin & Zosyn to Zosyn Plot Zosyn to Cefazolin """ # abx_settings = {"Vancomycin" : 13, # "Ampicillin" : 0, # "Cefazolin" : 8, # "Ceftriaxone" : 20,#404, # "Cefepime" : 14, # "Zosyn" : 20,#102, # "Ciprofloxacin" : 8, # "Meropenem" : 9, # "Vancomycin_Meropenem" : 9, # "Vancomycin_Zosyn" : 20,#149, # "Vancomycin_Cefepime" : 23, # "Vancomycin_Ceftriaxone" : 31 # } abx_settings = { "Ceftriaxone": 404, "Vancomycin_Zosyn": 149, "Zosyn": 102, "Vancomycin_Ceftriaxone": 31, "Vancomycin_Cefepime": 23, "Cefepime": 14, "Vancomycin": 13, "Vancomycin_Meropenem": 9, "Meropenem": 9, "Cefazolin": 8, "Ciprofloxacin": 8, "Ampicillin": 0, } f_name_missrates = 'select_sweep_miss_rates.txt' df_predictions = load_predictions() df_drugs = get_clinician_prescribing_patterns() # df_drugs = for_debugging_plot_select_sweeps(df_drugs, abx_settings) opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings) opt.solve_and_assign() random_covered_rate, clin_covered_rate, ip_covered_rate = opt.get_coverage_rates( ) baseline_clin_miss_rate = 1 - clin_covered_rate sweep_one = ("Vancomycin_Zosyn", "Zosyn") sweep_two = ("Zosyn", "Cefazolin") # sweep_three = ("Zosyn", "Ampicillin") sweep_three = ("Ceftriaxone", 'Cefazolin') sweep_four = ("Ceftriaxone", 'Ampicillin') # fig, ax = plt.subplots(1, 3, figsize=(24,8)) plt.figure(figsize=(36, 30)) gs = gridspec.GridSpec(5, 6, wspace=0.5, hspace=0.35) ax1a = plt.subplot(gs[0, 2:4]) ax2a = plt.subplot(gs[1, 1:3]) ax2b = plt.subplot(gs[1, 3:5]) ax3a = plt.subplot(gs[2, 1:3]) ax3b = plt.subplot(gs[2, 3:5]) ax4a = plt.subplot(gs[3, 1:3]) ax4b = plt.subplot(gs[3, 3:5]) ax5a = plt.subplot(gs[4, 1:3]) ax5b = plt.subplot(gs[4, 3:5]) axes = [[ax1a], [ax2a, ax2b], [ax3a, ax3b], [ax4a, ax4b], [ax5a, ax5b]] # Plot original clinician distribution plot_histogram(abx_settings, axes[0][0]) axes[0][0].set_title("Actual Clinician Allocation") # hard coded miss rate axes[0][0].set_xlabel("Number of Allcations") axes[0][0].set_ylabel('') with open(f_name_missrates, 'w') as w: w.write("Clinician Miss Rate: %.2f\n" % (baseline_clin_miss_rate * 100)) # sweep_one = ('Cefepime', 'Cefazolin') for k, sweep in enumerate([sweep_one, sweep_two, sweep_three, sweep_four]): opt.reset_df() abx_settings_perturbed = { key: abx_settings[key] for key in abx_settings } #deep copy max_deescalation = None print("Performing %s to %s sweep" % (sweep[0], sweep[1])) random_rates, clin_rates, ip_rates = [], [], [] c_from_rs, ip_from_rs = [], [] opt.set_abx_settings(abx_settings_perturbed) opt.solve_and_assign() r, c, i = opt.get_coverage_rates() if k == 0: print((1 - c) * 100) random_rates.append(1 - r) ip_rates.append(1 - i) clin_rates.append(1 - c) for iter_ in tqdm(range(abx_settings[sweep[0]])): abx_settings_perturbed[sweep[0]] -= 1 abx_settings_perturbed[sweep[1]] += 1 opt.set_abx_settings(abx_settings_perturbed) opt.replace_one(sweep[0], sweep[1]) opt.solve_and_assign() r, c, i = opt.get_coverage_rates() random_rates.append(1 - r) ip_rates.append(1 - i) clin_rates.append(1 - c) if 1 - i > baseline_clin_miss_rate and max_deescalation is None: # Number of iterations before gettting to baseline clinician error rate max_deescalation = abx_settings[ sweep[0]] - abx_settings_perturbed[sweep[0]] + 1 max_deescaltion_miss_rate = ip_rates[len(ip_rates) - 2] settings_to_plot = { key: abx_settings_perturbed[key] for key in abx_settings_perturbed } settings_to_plot[sweep[0]] += 1 settings_to_plot[sweep[1]] -= 1 plot_histogram(settings_to_plot, axes[k + 1][0]) axes[k + 1][0].set_title("Optmized Allocation Fewer %s" % sweep[0].replace('_', ' & ')) axes[k + 1][0].set_xlabel('Number of Allocations') axes[k + 1][0].set_ylabel('') print(max_deescalation) d_rate = float(abx_settings[sweep[0]] - (abx_settings_perturbed[sweep[0]] + 1)) / abx_settings[sweep[0]] with open(f_name_missrates, 'a') as w: w.write("Miss rate of %.2f achieve with %.2f fewer %s\n" % ((max_deescaltion_miss_rate) * 100, d_rate * 100, sweep[0].replace("_", ' & '))) # if abx_settings_perturbed == abx_settings: # clin_iter = iter_ # save point on x axis for clinician performance if max_deescalation is None: max_deescalation = abx_settings[sweep[0]] deescalations = [i for i in range(len(random_rates))] deescalations.reverse() axes[k + 1][1].plot(deescalations, ip_rates, label='Optimized', linewidth=2.0) axes[k + 1][1].plot(deescalations, clin_rates, label='Clinician', linewidth=2.0) axes[k + 1][1].plot(deescalations, random_rates, label='Random', linewidth=2.0) axes[k + 1][1].plot( deescalations, [baseline_clin_miss_rate for c in range(len(random_rates))], linestyle='--', color='black') axes[k + 1][1].invert_xaxis() axes[k + 1][1].set_title("Replacing %s with %s" % (sweep[0].replace("_", ' & '), sweep[1])) axes[k + 1][1].set_xlabel("Number of %s Allocated" % sweep[0].replace("_", ' & ')) axes[k + 1][1].set_ylabel("Miss Rate") axes[k + 1][1].set_ylim((0.10, 0.40)) print("Max Re-allocations of %s to %s: %s" % (sweep[0], sweep[1], str(max_deescalation))) if k == 0: axes[k + 1][1].legend(loc='upper left', fontsize='small') plt.savefig('select_sweeps.png')
def bootstrap_miss_rates(): abx_settings = { "Vancomycin": 13, "Ampicillin": 0, "Cefazolin": 8, "Ceftriaxone": 404, "Cefepime": 14, "Zosyn": 102, "Ciprofloxacin": 8, "Meropenem": 9, "Vancomycin_Meropenem": 9, "Vancomycin_Zosyn": 149, "Vancomycin_Cefepime": 23, "Vancomycin_Ceftriaxone": 31 } # Solve once then bootstrap solutions df_predictions = load_predictions() df_drugs = get_clinician_prescribing_patterns() opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings) opt.solve_and_assign() rs, cs, ls = [], [], [] l_c_relatives, l_r_relatives = [], [] for i in tqdm(range(1000)): # Don't stratify, only stratify if bootstrapping the solving procedure as well df_drugs_b = (opt.df.sample(frac=1.0, replace=True)) # # Stratified bootstrap # df_drugs_b = pd.DataFrame() # for abx in abx_settings: # df_temp = (opt.df # .query("med_description == @abx", engine='python') # .sample(frac=1.0, replace=True) # ) # df_drugs_b = pd.concat([df_drugs_b, df_temp]) # Sanity Check # for abx in abx_settings: # num_allocations = len(df_drugs_b[df_drugs_b['med_description'] == abx]) # assert num_allocations == abx_settings[abx] if i == 0: print(opt.n) r, c, l = opt.get_coverage_rates(df=df_drugs_b) rs.append(1 - r) cs.append(1 - c) ls.append(1 - l) l_r_relative = ((rs[-1] - ls[-1]) / rs[-1]) * 100 l_r_relatives.append(l_r_relative) l_c_relative = ((cs[-1] - ls[-1]) / cs[-1]) * 100 l_c_relatives.append(l_c_relative) # Miss Rates r_mean = np.mean(rs) * 100 r_low = np.percentile(rs, 2.5) * 100 r_high = np.percentile(rs, 97.5) * 100 r_miss_rate = "%.2f [%.2f, %.2f]" % (r_mean, r_low, r_high) c_mean = np.mean(cs) * 100 c_low = np.percentile(cs, 2.5) * 100 c_high = np.percentile(cs, 97.5) * 100 c_miss_rate = "%.2f [%.2f, %.2f]" % (c_mean, c_low, c_high) l_mean = np.mean(ls) * 100 l_low = np.percentile(ls, 2.5) * 100 l_high = np.percentile(ls, 97.5) * 100 l_miss_rate = "%.2f [%.2f, %.2f]" % (l_mean, l_low, l_high) # Relative Miss Reductions l_c_means = np.mean(l_c_relatives) l_c_low = np.percentile(l_c_relatives, 2.5) l_c_high = np.percentile(l_c_relatives, 97.5) l_c_final = "%.2f [%.2f, %.2f]" % (l_c_means, l_c_low, l_c_high) l_r_means = np.mean(l_r_relatives) l_r_low = np.percentile(l_r_relatives, 2.5) l_r_high = np.percentile(l_r_relatives, 97.5) l_r_final = "%.2f [%.2f, %.2f]" % (l_r_means, l_r_low, l_r_high) return r_miss_rate, c_miss_rate, l_miss_rate, l_r_final, l_c_final
def full_waterfall(): abx_settings = { "Vancomycin": 0, "Ampicillin": 0, "Cefazolin": 0, "Ceftriaxone": 0, "Cefepime": 0, "Zosyn": 0, "Ciprofloxacin": 0, "Meropenem": 0, "Vancomycin_Meropenem": 697, "Vancomycin_Zosyn": 0, "Vancomycin_Cefepime": 0, "Vancomycin_Ceftriaxone": 0 } abx_rankings = [ 'Vancomycin_Meropenem', 'Vancomycin_Cefepime', 'Vancomycin_Zosyn', 'Zosyn', 'Vancomycin_Ceftriaxone', 'Meropenem', 'Cefepime', 'Ceftriaxone', 'Ciprofloxacin', 'Cefazolin', 'Ampicillin', 'Vancomycin' ] if os.path.exists('df_predictions.csv'): df_predictions = pd.read_csv('df_predictions.csv') else: df_predictions = load_predictions() df_predictions.to_csv('df_predictions.csv', index=None) if os.path.exists('df_drugs.csv'): df_drugs = pd.read_csv('df_drugs.csv') else: df_drugs = get_clinician_prescribing_patterns() df_drugs.to_csv('df_drugs.csv', index=None) deplete_idx = 0 push_from_idx = 0 push_to_idx = 1 random_rates = [] ip_rates = [] counter = 0 while abx_settings['Vancomycin'] != 697: # end of sweep opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings) opt.solve_and_assign() r, c, i = opt.get_coverage_rates() random_rates.append(r) ip_rates.append(i) if counter == 10: print(abx_settings) counter = 0 # Make more narrow spectrum abx_settings[abx_rankings[push_from_idx]] -= 1 abx_settings[abx_rankings[push_to_idx]] += 1 if abx_settings[abx_rankings[deplete_idx]] == 0: deplete_idx += 1 print("Moving deplete index from %s to %s" % (abx_rankings[deplete_idx - 1], abx_rankings[deplete_idx])) if push_to_idx == len(abx_rankings) - 1: push_to_idx = deplete_idx + 1 push_from_idx = deplete_idx else: push_from_idx += 1 push_to_idx += 1 counter += 1 clin_rates = [c for i in range(len(random_rates))] df = pd.DataFrame( data={ 'clin_rates': clin_rates, 'random_rates': random_rates, 'ip_rates': ip_rates }) df.to_csv('summary_sweep.csv') fix, ax = plt.subplots(1, 1, figsize=(8, 8)) ax.plot(range(len(random_rates)), random_rates, label='Random Assignment') ax.plot(range(len(random_rates)), ip_rates, label='Integer Programming') ax.plot(range(len(random_rates)), c, label='Clinician Benchmark') fig_name = "summary_sweep.jpg" plt.savefig(fig_name)
def perform_abx_sweep(): """ Simulates antibiotic delivery sweeping through different abx prescribing contraints. For each abx pair, we add the number of times the two were prescribed in total (N) in actual practice and then sweep contraints from the extreme where only the first antbiotic prescribed N times to the other extreme where the other antibiotic is prescribed N times. We show how coverage rate changes as we change these contraints for both the IP decision and a random decision. """ abx_settings = { "Vancomycin": 13, "Ampicillin": 0, "Cefazolin": 8, "Ceftriaxone": 404, "Cefepime": 14, "Zosyn": 102, "Ciprofloxacin": 8, "Meropenem": 9, "Vancomycin_Meropenem": 16, "Vancomycin_Zosyn": 153, "Vancomycin_Cefepime": 23, "Vancomycin_Ceftriaxone": 31 } df_predictions = load_predictions() df_drugs = get_clinician_prescribing_patterns() opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings) opt.solve_and_assign() random_covered_rate, clin_covered_rate, ip_covered_rate = opt.get_coverage_rates( ) for abx_to_perturb in abx_settings: # plt.figure(figsize=(32,24)) # fig, ax = plt.subplots(3, 4, figsize=(32, 24)) # gs = gridspec.GridSpec(4, 24, wspace=2.0) # ax1a = plt.subplot(gs[0, 0:6]) # ax1b = plt.subplot(gs[0, 6:12]) # ax1c = plt.subplot(gs[0, 12:18]) # ax1d = plt.subplot(gs[0, 18:24]) # ax2a = plt.subplot(gs[1, 3:9]) # ax2b = plt.subplot(gs[1, 9:15]) # ax2c = plt.subplot(gs[1, 15:21]) # ax3a = plt.subplot(gs[2, 0:6]) # ax3b = plt.subplot(gs[2, 6:12]) # ax3c = plt.subplot(gs[2, 12:18]) # ax3d = plt.subplot(gs[2, 18:24]) plt.figure(figsize=(24, 32)) gs = gridspec.GridSpec(4, 6, wspace=0.5) ax1a = plt.subplot(gs[0, 0:2]) ax1b = plt.subplot(gs[0, 2:4]) ax1c = plt.subplot(gs[0, 4:6]) ax2a = plt.subplot(gs[1, 0:2]) ax2b = plt.subplot(gs[1, 2:4]) ax2c = plt.subplot(gs[1, 4:6]) ax3a = plt.subplot(gs[2, 0:2]) ax3b = plt.subplot(gs[2, 2:4]) ax3c = plt.subplot(gs[2, 4:6]) ax4a = plt.subplot(gs[3, 1:3]) ax4b = plt.subplot(gs[3, 3:5]) axes = [ ax1a, ax1b, ax1c, ax2a, ax2b, ax2c, ax3a, ax3b, ax3c, ax4a, ax4b ] skip = 0 for ind, abx in enumerate(abx_settings): if abx == abx_to_perturb: skip = 1 continue else: abx_settings_perturbed = { key: abx_settings[key] for key in abx_settings } print("Performing %s to %s sweep" % (abx_to_perturb, abx)) random_rates, ip_rates = [], [] # Total selections to sweep over total_selections = abx_settings[abx] + abx_settings[ abx_to_perturb] abx_settings_perturbed[abx_to_perturb] = total_selections abx_settings_perturbed[abx] = 0 opt.set_abx_settings(abx_settings_perturbed) opt.solve_and_assign() r, c, i = opt.get_coverage_rates() random_rates.append(r) ip_rates.append(i) if abx_settings_perturbed == abx_settings: clin_iter = -1 # save point on x axis for clinician performance for iter_ in tqdm(range(total_selections)): abx_settings_perturbed[abx_to_perturb] -= 1 abx_settings_perturbed[abx] += 1 opt.set_abx_settings(abx_settings_perturbed) opt.solve_and_assign() r, c, i = opt.get_coverage_rates() random_rates.append(r) ip_rates.append(i) if abx_settings_perturbed == abx_settings: clin_iter = iter_ # save point on x axis for clinician performance axes[ind - skip].plot(range(total_selections + 1), random_rates, label='Random Assignment') axes[ind - skip].plot(range(total_selections + 1), ip_rates, label='Integer Programming') axes[ind - skip].plot(clin_iter + 1, clin_covered_rate, marker='o', label='Clinician Benchmark') # forward = lambda x: total_selections - x # backward = lambda x: total_selections - x # secax = axes[ind-skip].secondary_xaxis('top', functions=(forward, backward)) axes[ind - skip].set_xlabel("Num %s Administered" % abx) # secaxes[ind-skip].set_xlabel("Num %s Administered" % abx_to_perturb) axes[ind - skip].set_ylabel("Coverage Rate") axes[ind - skip].set_ylim((0.5, 1.)) axes[ind - skip].set_title("%s to %s Sweep" % (abx_to_perturb, abx)) axes[ind - skip].legend() dir_ = './tall_grid/' os.makedirs(dir_, exist_ok=True) fig_name = "./tall_grid/%s_sweeps.jpg" % abx_to_perturb plt.savefig(fig_name)
def plot_distribution_of_allocated_abx(): """ Bar plots of allocated abx """ df = pd.DataFrame() abx_settings = { "Vancomycin": 13, "Ampicillin": 0, "Cefazolin": 8, "Ceftriaxone": 404, "Cefepime": 14, "Zosyn": 102, "Ciprofloxacin": 8, "Meropenem": 9, "Vancomycin_Meropenem": 9, "Vancomycin_Zosyn": 149, "Vancomycin_Cefepime": 23, "Vancomycin_Ceftriaxone": 31 } df_predictions = load_predictions() df_drugs = get_clinician_prescribing_patterns() opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings) opt.df = (opt.df.assign(was_covered_dr=opt.df.apply( lambda x: opt.compute_was_covered(x), axis=1))) # Get counts df_final = (opt.df.groupby('med_description').agg( num_distinct_csns=('pat_enc_csn_id_coded', 'nunique'), num_times_covered_by_dr=('was_covered_dr', 'sum') ).reset_index().assign(med_description=lambda x: [ m.replace('_', ' & ') + " [%s/%s]" % (nc, nd) for m, nd, nc in zip( x.med_description, x.num_distinct_csns, x.num_times_covered_by_dr) ])) fig, ax = plt.subplots(1, 1, figsize=(12, 12)) df_final = df_final.sort_values('num_distinct_csns', ascending=False) sns.barplot(x="num_distinct_csns", y="med_description", ci=None, data=df_final, ax=ax, color='red') sns.barplot(x="num_times_covered_by_dr", y="med_description", ci=None, data=df_final, ax=ax, color='blue') ax.set_ylabel("") ax.set_xlabel("Number of Allocations") ax.set_title( "Clinician Antibiotic Selections and Fraction of Patients Covered") # ax.set_xlim((0, 550)) # Save Figure # plt.gcf().subplots_adjust(left=0.25) # plt.savefig('abx_distribution.png') plt.show() # Save Miss Rates For Each antibiotic fname = 'clinicians_miss_rates_by_abx.csv' df_miss_rates = (df_final.assign(num_misses=lambda x: [ csn - n_c for csn, n_c in zip(x.num_distinct_csns, x.num_times_covered_by_dr) ])) df_miss_rates.to_csv(fname, index=None)
# w.write("Clinician miss rate:%s\n" % c) # w.write("Optimized miss rate:%s\n" % l) # w.write("Relative Reduction Miss Rate Optimized to Random:%s\n" % lr) # w.write("Relative Reduction Miss Rate Optimized to Clinician:%s\n" % lc) # plot_select_sweeps() # plot_distribution_of_allocated_abx() # bootstrap_miss_rates() abx_settings = { "Ceftriaxone": 404, "Vancomycin_Zosyn": 149, "Zosyn": 102, "Vancomycin_Ceftriaxone": 31, "Vancomycin_Cefepime": 23, "Cefepime": 14, "Vancomycin": 13, "Vancomycin_Meropenem": 9, "Meropenem": 9, "Cefazolin": 8, "Ciprofloxacin": 8, "Ampicillin": 0, } f_name_missrates = 'individual_sweep_test.txt' df_predictions = load_predictions() df_drugs = get_clinician_prescribing_patterns() opt = AbxDecisionMaker(df_predictions, df_drugs, abx_settings) plot_sweeps(opt) # perform_sweep(opt, abx_1='Vancomycin_Meropenem', abx_2='Vancomycin', ax=ax, fname=f_name_missrates, legend=True) # plt.show()