Source code for policy_modules.mcaid_elig

    #!/usr/bin/env python

import numpy as np
import pandas as pd
import math
import pdb
from utility_modules.get_parameters import get_params
from policy_modules.fpl import Fpl
from policy_modules.calculate_regression import FplRegression
from utility_modules.exceptions.year_exceptions import YearException as YearException

"""
    creating a new column to store medicaid eligibility
    related criteria, except fpl, because only fpl depends on iteration.
    Everything else is fixed. So this function should be in set-up part.
    variables to be merged on: adult, doc, lprle5, having_kids
    mcaid_types: pd.DataFrame of mcaid
    df:          pd.DataFrame of person (0/1) and age
"""

[docs]class McaidEligibility(): # borg singleton config object __shared_state = {} def __init__(self, policy_dict = None, sys_params = None): # implement the borg pattern self.__dict__ = self.__shared_state if policy_dict != None: gid_mcaid = policy_dict['mcaid_elig'] gid_fpl = policy_dict['fpl'] max_year = int(sys_params.max_year) #read in mcaid data self.data = get_params(gid_mcaid) self.wb = self.data[self.data['year']==max_year] #read in fpl data self.fpl = get_params(gid_fpl) self.regression_model= FplRegression(policy_dict) if (max(self.fpl.year) < max_year): #make a dataframe for prediction future = pd.DataFrame(range(max(self.fpl.year)+1, max_year+1)) future.columns = ['year'] #predict new years and return data future['base'] = self.regression_model.calculate_regression_line(self.fpl.year, self.fpl.base, future[['year']]) future['inc'] = self.regression_model.calculate_regression_line(self.fpl.year, self.fpl.inc, future[['year']]) self.fpl = self.fpl.append(future) #read in mcaid data mcaid = get_params(gid_mcaid) mcaid.index.name = 'type' mcaid.reset_index(inplace=True) self.mcaid_types = mcaid[['type','max_age','adult']] self.mcaid_elig = mcaid[['type','fpl_thresh']] self.mcaid_threshold = sys_params.medicaid_elig_threshold
[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 in self.fpl.year.values: self.curr_data = self.fpl[self.fpl.year == curr_year][['base','inc']] self.curr_data_me = self.data[self.data['year']==curr_year] else: raise YearException(str(curr_year)+ " is not a valid year.")
[docs] def pass_threshold(self, threshold, prob): """ checks if the probability passed in exceeds the threshold level specified in the configuration file """ return (prob >= threshold).astype(int)
[docs] def produce_elig_exante(self, df): """ create column of previously medicaid eligible based on 2013 medicaid eligibility requirements """ rules = self.data[self.data['year'] == 2013] # this can be hard-coded, since it doesn't change mcaid_elig = False if 'having_kids' in df: df = df.drop('having_kids', axis=1) determine_kids = df.loc[(df['person_type'] == 2) | (df['person_type'] == 3)] determine_kids['having_kids'] = determine_kids['person_id'].notnull() kid_fams = determine_kids.loc[determine_kids['having_kids'] == True].drop_duplicates('hieu_id') df = pd.merge(df, kid_fams[['hieu_id','having_kids']], on='hieu_id', how='left') for index, row in rules.iterrows(): # true medicaid eligibility if (row['doc'] == 1) & (row['adult'] == 0): eligTemp = (df['doc_status'] <= 2) & (df['age']>=row['min_age']) & (df['age'] <= row['max_age']) & \ (df['fpl'] <= row['fpl_thresh']) & (df['coverage']!=4) loc_ind_adult_child = np.where((df['person_type'] > 3) & (df['tax_dependent'] == 0))[0] eligTemp[loc_ind_adult_child] = (df.loc[loc_ind_adult_child,'doc_status'] <= 2) & (df.loc[loc_ind_adult_child,'age']>=row['min_age']) & (df.loc[loc_ind_adult_child,'age'] <= row['max_age']) & \ (df.loc[loc_ind_adult_child,'ind_fpl'] <= row['fpl_thresh']) & (df.loc[loc_ind_adult_child,'coverage']!=4) elif (row['doc']==1) & (row['adult'] == 1): eligTemp = (df['doc_status'] <= 2) & (df['age']>=row['min_age']) & (df['age'] <= row['max_age']) & \ (df['fpl'] <= row['fpl_thresh']) & (df['having_kids'] == 1) & (df['coverage']!=4) loc_ind_adult_child = np.where((df['person_type'] > 3) & (df['tax_dependent'] == 0))[0] eligTemp[loc_ind_adult_child] = (df.loc[loc_ind_adult_child, 'doc_status'] <= 2) & (df.loc[loc_ind_adult_child, 'age'] >= row['min_age']) & ( df.loc[loc_ind_adult_child, 'age'] <= row['max_age']) & \ (df.loc[loc_ind_adult_child, 'ind_fpl'] <= row['fpl_thresh']) & (df.loc[loc_ind_adult_child, 'coverage'] != 4) & (df.loc[loc_ind_adult_child,'having_kids'] == 1) # calculate newly eligible persons mcaid_elig = mcaid_elig | eligTemp mcaid_elig =mcaid_elig & (df['coverage'] != 3) & (df['coverage'] != 4) & (df['coverage'] != 5) df['mcaid_elig_exante'] = (mcaid_elig).astype(int) return df['mcaid_elig_exante']
[docs] def determine_elig(self, df): """ input : a form of hieu_table, with fpl variable available output: the data frame of the same hieu_table with mcaid_elig column and medicaid premium as well # adjusted_prev_elig = previously elig, without ACA, from input data # predicted_elig = predicted probability, from input data # mcaid_elig = everyone who eligible post-ACA without prediction model # newly_elig = with ACA, calculated """ mcaid_elig = False for index, row in self.curr_data_me.iterrows(): # true medicaid eligibility if row['doc']==1: eligTemp = (df['doc_status'] <= 2) & (df['age']>=row['min_age']) & (df['age'] <= row['max_age']) & \ (df['fpl'] <= row['fpl_thresh']) loc_ind_adult_child = np.where((df['person_type'] > 3) & (df['tax_dependent'] == 0))[0] eligTemp[loc_ind_adult_child] = (df.loc[loc_ind_adult_child, 'doc_status'] <= 2) & ( df.loc[loc_ind_adult_child, 'age'] >= row['min_age']) & (df.loc[loc_ind_adult_child, 'age'] <= row['max_age']) & \ (df.loc[loc_ind_adult_child, 'ind_fpl'] <= row['fpl_thresh']) else: eligTemp = (df['age']>=row['min_age']) & (df['age'] <= row['max_age']) & (df['fpl']<=row['fpl_thresh']) loc_ind_adult_child = np.where((df['person_type'] > 3) & (df['tax_dependent'] == 0))[0] eligTemp[loc_ind_adult_child]= ( df.loc[loc_ind_adult_child, 'age'] >= row['min_age']) & (df.loc[loc_ind_adult_child, 'age'] <= row['max_age']) & (df.loc[loc_ind_adult_child, 'ind_fpl'] <= row['fpl_thresh']) # calculate newly eligible persons mcaid_elig = mcaid_elig | eligTemp df['new_mcaid_elig'] = (mcaid_elig & (df['coverage'] != 3) & (df['coverage'] != 4) & (df['coverage'] != 5) \ & (df['mcaid_elig_exante']==0)).fillna(False).astype(int) # total eligible persons include newly eligible + previously eligible persons df['mcaid_elig'] = (df['new_mcaid_elig'] | df['mcaid_elig_exante'] | df['gvmt_insurance']==1).astype(int) # disable the individuals who are subisdy eligible on mcaid #if 'subsidy_elig' in df: # df['mcaid_elig'] = df['mcaid_elig'] & (~df['subsidy_elig']) # calculate eligible persons based on prediction model df['pass_threshold'] = self.pass_threshold(self.mcaid_threshold, df['mcaid_predict']) df['predicted_elig'] = ( (df['doc_status'] <= 2) & (df['pass_threshold'] == True) & (df['coverage'] != 3) & (df['coverage'] != 4) & ( df['coverage'] != 5) & (df['age'] > 18)).astype(int) elig_fam = np.array(df.loc[df['predicted_elig'] == 1]['hieu_id'].drop_duplicates()) # make their family members eligible IF they are documented and not on other public, medicare df_prdt = df.loc[(df['hieu_id'].isin(elig_fam)) & (df['doc_status'] <= 2) & (df['coverage'] != 3) & (df['coverage'] != 4) & (df['coverage'] != 5)] df_prdt['predicted_elig'] = 1 df['predicted_exante_elig'] = False # make children exante predicted eligible df['predicted_exante_elig']=False df_prdt2 = df_prdt.loc[(df_prdt['person_type'] == 2) | (df_prdt['person_type'] == 3)& (df_prdt['coverage'] != 3) & (df_prdt['coverage'] != 4) & (df_prdt['coverage'] != 5)] df_prdt2['predicted_exante_elig'] = True df.update(df_prdt2['predicted_exante_elig']) df.update(df_prdt['predicted_elig']) return df
[docs] def calculate_premium(self, df, shadow_premium): """ assuming df has mcaid_elig variable # pseudo-code: if xc_sub then msp = a0 else if newly_elig then msp = a1 else if prev_elig then msp = a2 else if predicted elig then msp = a3 """ # for xc_sub elig, shadow premium applied will be a0 xc_sub_elig = df.loc[df['subsidy_elig'] == 1] xc_sub_elig['shadow_premium'] = shadow_premium[0] # for the rest: a1, a2, a3 xc_not_elig = df.loc[df['subsidy_elig'] == 0] xc_sub1 = xc_not_elig.loc[xc_not_elig['new_mcaid_elig'] == 1] xc_sub1['shadow_premium'] = shadow_premium[1] xc_sub2 = xc_not_elig.loc[(xc_not_elig['new_mcaid_elig'] == 0) & (xc_not_elig['mcaid_elig_exante'] == 1)] xc_sub2['shadow_premium'] = shadow_premium[2] xc_sub3 = xc_not_elig.loc[(xc_not_elig['new_mcaid_elig'] == 0) & (xc_not_elig['mcaid_elig_exante'] == 0) & \ (xc_not_elig['predicted_elig'] == 1)] xc_sub3['shadow_premium'] = shadow_premium[3] updated_df = pd.concat([xc_sub_elig, xc_sub1, xc_sub2, xc_sub3]) df['shadow_premium'] = 0 df.update(updated_df) df['mcaid_prem'] = 0 for index, row in self.curr_data_me.iterrows(): if not math.isnan(row['premium']): premFlag = ((df['mcaid_elig'] == 1) & (df['age'] >= row['min_age']) & (df['age'] <= row['max_age']) & \ (df['fpl'] <= row['fpl_thresh']) & (df['fpl'] >= row['premium_thresh'])).astype(int) premTemp = premFlag * row['premium']*12 # premium is presented as monthly, need to convert to annual [xc, 4/19/2018] df['mcaid_prem'] = df['mcaid_prem'] + premTemp + df['shadow_premium'] return df['mcaid_prem']