Source code for policy_modules.cost_sharing_subsidy

#!/usr/bin/env python

from utility_modules.get_parameters import get_params
from utility_modules.get_parameters import get_parse_params
from utility_modules.av_module import oop_av
import numpy as np
import pandas as pd
import pdb

[docs]class CostSharing: # Borg singleton config __shared_state = {} def __init__(self, policy_params = None): # implement the borg pattern self.__dict__ = self.__shared_state if policy_params != None: gid_cost_sharing = policy_params['prem_sub'] gid_firm_behavior=policy_params['firm_behavior'] self.cost_sharing = get_params(gid_cost_sharing) self.firm_behavior=get_parse_params(gid_firm_behavior) self.elasticity=self.firm_behavior.AV_elasticity av_sheet=get_params(policy_params['xc_admin_loading']) self.silver_av=av_sheet[av_sheet['type']==6].av.min()
[docs] def set_year(self, curr_year): """ return slice of pertinant year allows this to be reset at begining of each simulation year """ if curr_year not in self.cost_sharing.year.values: return else: # subset to only values in designated year self.cost_sharing_subset = self.cost_sharing[self.cost_sharing.year == curr_year] self.cost_sharing_subset = self.cost_sharing_subset.reset_index() self.cost_fpl_lower = self.cost_sharing_subset['fpl_lower'].tolist() self.cost_fpl_upper = self.cost_sharing_subset['fpl_upper'].tolist() self.max_oop_single = self.cost_sharing_subset[ 'silver_oop_max_s'].tolist() # OOP for single as y-axis for interpolation self.max_oop_family = self.cost_sharing_subset[ 'silver_oop_max_f'].tolist() # OOP for family as y-axis for interpolation self.silver_cs = self.cost_sharing_subset['cost_sharing'].tolist() self.fpl_bracket=[self.cost_fpl_lower[0]] self.cost_sharing_bracket=[] self.oop_single_bracket=[] self.oop_family_bracket=[] for i in range(1,len(self.cost_fpl_lower)): self.fpl_bracket=self.fpl_bracket+[self.cost_fpl_lower[i]]+[self.cost_fpl_lower[i]] self.cost_sharing_bracket=self.cost_sharing_bracket+[self.silver_cs[i-1]]+[self.silver_cs[i-1]] self.oop_single_bracket = self.oop_single_bracket + [self.max_oop_single[i - 1]] + [self.max_oop_single[i - 1]] self.oop_family_bracket = self.oop_family_bracket + [self.max_oop_family[i - 1]] + [self.max_oop_family[i - 1]] self.cost_sharing_bracket=self.cost_sharing_bracket+[self.silver_cs[-1]] self.oop_single_bracket = self.oop_single_bracket + [self.max_oop_single[-1]] self.oop_family_bracket = self.oop_family_bracket + [self.max_oop_family[-1]]
[docs] def oop_update(self, choice_table, pop_df): """ updates OOP for those on a silver plan with cost sharing subsidy values assuming that pop_df has subsidy_elig column already """ #manifest constants: choices people = ['adult_1', 'adult_2', 'child_1', 'child_2', 'adult_child_1', \ 'adult_child_2', 'adult_child_3','adult_child_4'] people_indices = [0, 1, 2, 3, 4, 5, 6, 7] # oop columns oop_cols = ['oop0','oop2','oop2','oop3','oop4','oop5','oop6', 'oop7'] # temp pop_df: calculating for each person and each choice, max oop amount temp_pop_df = pop_df temp_pop_df['cost_sharing']=np.interp(temp_pop_df['fpl'],self.fpl_bracket,self.cost_sharing_bracket) temp_pop_df['oop_single_max'] = np.interp(temp_pop_df['fpl'], self.fpl_bracket, self.oop_single_bracket) temp_pop_df['oop_family_max'] = np.interp(temp_pop_df['fpl'], self.fpl_bracket, self.oop_family_bracket) loc_ind_adult_child=np.where((temp_pop_df['person_type'] > 3) & (temp_pop_df['tax_dependent'] == 0))[0] temp_pop_df.loc[loc_ind_adult_child,'cost_sharing']=np.interp(temp_pop_df.loc[loc_ind_adult_child,'ind_fpl'],self.fpl_bracket,self.cost_sharing_bracket) temp_pop_df.loc[loc_ind_adult_child, 'oop_single_max'] = np.interp(temp_pop_df.loc[loc_ind_adult_child, 'ind_fpl'], self.fpl_bracket, self.oop_single_bracket) temp_pop_df.loc[loc_ind_adult_child, 'oop_family_max'] = np.interp(temp_pop_df.loc[loc_ind_adult_child, 'ind_fpl'], self.fpl_bracket, self.oop_family_bracket) # preparing for merging with choice table cost_sharing_df =pd.pivot_table(temp_pop_df,index='hieu_id', columns='person_type', values=['cost_sharing','oop_single_max','oop_family_max']) cost_sharing_df.columns = ['cost_sharing_' + str(i) for i in range(8)]+['oop_single_max_' + str(i) for i in range(8)]+['oop_family_max_' + str(i) for i in range(8)] cost_sharing_df= cost_sharing_df.reset_index() my_choices = pd.merge(choice_table, cost_sharing_df, on='hieu_id', how='left') #my_choices.reset_index(drop=True, inplace=True) ##### NOT DOING FAMILY OOP YET ###### cost_sharing_columns = ['cost_sharing_' + str(i) for i in range(8)] oop_single_columns = ['oop_single_max_' + str(i) for i in range(8)] oop_family_columns = ['oop_family_max_' + str(i) for i in range(8)] #adjust expenditure and count number of family members on silver(choice==6,subsidy_eligible and exclude tax_independent adult_child),also calculate their oop_sum my_choices['count']=0 my_choices['oop_family_sum']=0 my_choices['oop_family_sum_adj']=0 for index, person in enumerate(people): loc_exp_change=np.where((my_choices[person] == 6)&(my_choices['subsidy_elig_'+str(people_indices[index])]==1))[0] my_choices.loc[loc_exp_change, 'exp' + str(people_indices[index])] =my_choices.loc[loc_exp_change, 'exp' + str(people_indices[index])]+ my_choices.loc[loc_exp_change, 'exp' + str(people_indices[index])] \ * ((my_choices.loc[loc_exp_change, 'cost_sharing_' + str(people_indices[index])]-self.silver_av) / self.silver_av)*self.elasticity if people_indices[index]<4: my_choices['count']=my_choices['count']+((my_choices[person]==6).astype(int))*((my_choices['subsidy_elig_'+str(people_indices[index])]==1).astype(int)) my_choices['oop_family_sum']=my_choices['oop_family_sum']+((my_choices[person]==6).astype(int))*((my_choices['subsidy_elig_'+str(people_indices[index])]==1).astype(int)) \ *(my_choices['oop'+str(people_indices[index])])*((1.0-my_choices['cost_sharing_'+ str(people_indices[index])]).fillna(0))/(1-self.silver_av) my_choices['oop_family_sum_adj'] = my_choices['oop_family_sum_adj'] + ((my_choices[person] == 6).astype(int)) * ((my_choices['subsidy_elig_' + str(people_indices[index])] == 1).astype(int)) \ * (my_choices['oop' + str(people_indices[index])+'_adj']) * ((1.0 - my_choices['cost_sharing_' + str(people_indices[index])]).fillna(0)) / (1 - self.silver_av) else: my_choices['count'] = my_choices['count'] + ((my_choices[person] == 6).astype(int)) * ((my_choices['subsidy_elig_' + str(people_indices[index])] == 1).astype(int)) \ *((my_choices['tax_dependent_' + str(people_indices[index])] ==1).astype(int)) my_choices['oop_family_sum']=my_choices['oop_family_sum'] + ((my_choices[person] == 6).astype(int)) * ((my_choices['subsidy_elig_' + str(people_indices[index])] == 1).astype(int)) \ *((my_choices['tax_dependent_' + str(people_indices[index])] ==1).astype(int))*(my_choices['oop' + str(people_indices[index])]) \ * ((1 - my_choices['cost_sharing_' + str(people_indices[index])]).fillna(0)) / (1 - self.silver_av) my_choices['oop_family_sum_adj'] = my_choices['oop_family_sum_adj'] + ((my_choices[person] == 6).astype(int)) * ((my_choices['subsidy_elig_' + str(people_indices[index])] == 1).astype(int)) \ * ((my_choices['tax_dependent_' + str( people_indices[index])] == 1).astype(int)) * (my_choices['oop' + str(people_indices[index])+'_adj']) \ * ((1 - my_choices['cost_sharing_' + str(people_indices[index])]).fillna(0)) / (1 - self.silver_av) my_choices['oop_family_number']=0 my_choices['oop_family_number_adj'] = 0 my_choices.loc[my_choices['count']>1,'oop_family_number']=np.minimum( (my_choices.loc[my_choices['count']>1,'oop_family_sum']), (my_choices.loc[my_choices['count']>1,'oop_family_max_0'])) \ / my_choices.loc[my_choices['count']>1,'count'] my_choices.loc[my_choices['count'] > 1, 'oop_family_number_adj'] = np.minimum((my_choices.loc[my_choices['count'] > 1, 'oop_family_sum_adj']),(my_choices.loc[my_choices['count'] > 1, 'oop_family_max_0'])) \ / my_choices.loc[ my_choices['count'] > 1, 'count'] #update oop value for index, person in enumerate(people): #no need to consider tiac, count=1 means you must in oop_single,count>1 means you are in family if people_indices[index] < 4: loc_oop_single=np.where((my_choices['count']==1)&(my_choices[person] == 6)&(my_choices['subsidy_elig_'+str(people_indices[index])]==1))[0] loc_oop_family=np.where((my_choices['count']>1)&(my_choices[person] == 6)&(my_choices['subsidy_elig_'+str(people_indices[index])]==1))[0] my_choices.loc[loc_oop_single,'oop'+str(people_indices[index])]=np.minimum(my_choices.loc[loc_oop_single,'oop_family_sum'],my_choices.loc[loc_oop_single,'oop_single_max_'+str(people_indices[index])]) my_choices.loc[loc_oop_single, 'oop' + str(people_indices[index])+'_adj'] = np.minimum(my_choices.loc[loc_oop_single, 'oop_family_sum_adj'],my_choices.loc[loc_oop_single, 'oop_single_max_' + str(people_indices[index])]) my_choices.loc[loc_oop_family, 'oop' + str(people_indices[index])]=my_choices.loc[loc_oop_family,'oop_family_number'] my_choices.loc[loc_oop_family, 'oop' + str(people_indices[index])+'_adj'] = my_choices.loc[loc_oop_family, 'oop_family_number_adj'] # consider tiac situation, recalculate oop value for tiac silver else: loc_oop_single = np.where((my_choices['count'] == 1) & (my_choices[person] == 6) & (my_choices['subsidy_elig_' + str(people_indices[index])] == 1)&(my_choices['tax_dependent_' + str(people_indices[index])] == 1))[0] loc_oop_family = np.where((my_choices['count'] > 1) & (my_choices[person] == 6) & (my_choices['subsidy_elig_' + str(people_indices[index])] == 1&(my_choices['tax_dependent_' + str(people_indices[index])] == 1)))[0] my_choices.loc[loc_oop_single, 'oop' + str(people_indices[index])] = np.minimum(my_choices.loc[loc_oop_single, 'oop_family_sum'],my_choices.loc[loc_oop_single, 'oop_single_max_' + str(people_indices[index])]) my_choices.loc[loc_oop_single, 'oop' + str(people_indices[index]) + '_adj'] = np.minimum(my_choices.loc[loc_oop_single, 'oop_family_sum_adj'],my_choices.loc[loc_oop_single, 'oop_single_max_' + str(people_indices[index])]) my_choices.loc[loc_oop_family, 'oop' + str(people_indices[index])] = my_choices.loc[loc_oop_family, 'oop_family_number'] my_choices.loc[loc_oop_family, 'oop' + str(people_indices[index])+ '_adj'] = my_choices.loc[loc_oop_family, 'oop_family_number_adj'] loc_ind_adult_child=np.where( (my_choices[person] == 6) & (my_choices['subsidy_elig_' + str(people_indices[index])] == 1&(my_choices['tax_dependent_' + str(people_indices[index])] == 0)))[0] temp=my_choices.loc[loc_ind_adult_child, 'oop' + str(people_indices[index])]*((1-my_choices.loc[loc_ind_adult_child,'cost_sharing_'+str(people_indices[index])]).fillna(0))/(1 - self.silver_av) temp_adj=my_choices.loc[loc_ind_adult_child, 'oop' + str(people_indices[index])+'_adj']*((1-my_choices.loc[loc_ind_adult_child,'cost_sharing_'+str(people_indices[index])]).fillna(0))/(1 - self.silver_av) my_choices.loc[loc_ind_adult_child, 'oop' + str(people_indices[index])]=np.minimum(temp,my_choices.loc[loc_ind_adult_child,'oop_single_max_'+str(people_indices[index])]) my_choices.loc[loc_ind_adult_child, 'oop' + str(people_indices[index])+'_adj'] = np.minimum(temp_adj, my_choices.loc[loc_ind_adult_child, 'oop_single_max_' + str(people_indices[index])]) cols_to_drop = cost_sharing_columns + oop_single_columns + oop_family_columns+['count','oop_family_sum','oop_family_number','oop_family_sum_adj','oop_family_number_adj'] my_choices.drop(cols_to_drop, axis=1, inplace = True) return my_choices