def test_make_calculator_increment_years_first(cps_subsample): """ Test Calculator inflation indexing of policy parameters. """ # pylint: disable=too-many-locals # create Policy object with policy reform pol = Policy() reform = {2015: {}, 2016: {}} std5 = 2000 reform[2015]['_STD_Aged'] = [[std5, std5, std5, std5, std5]] reform[2015]['_II_em'] = [5000] reform[2016]['_II_em'] = [6000] reform[2016]['_II_em_cpi'] = False pol.implement_reform(reform) # create Calculator object with Policy object as modified by reform rec = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=pol, records=rec) # compare expected policy parameter values with those embedded in calc irates = pol.inflation_rates() syr = Policy.JSON_START_YEAR irate2015 = irates[2015 - syr] irate2016 = irates[2016 - syr] std6 = std5 * (1.0 + irate2015) std7 = std6 * (1.0 + irate2016) exp_STD_Aged = np.array([[1500, 1200, 1200, 1500, 1500], [1550, 1200, 1200, 1550, 1550], [std5, std5, std5, std5, std5], [std6, std6, std6, std6, std6], [std7, std7, std7, std7, std7]]) act_STD_Aged = calc.policy_param('_STD_Aged') assert np.allclose(act_STD_Aged[:5], exp_STD_Aged) exp_II_em = np.array([3900, 3950, 5000, 6000, 6000]) act_II_em = calc.policy_param('_II_em') assert np.allclose(act_II_em[:5], exp_II_em)
def test_make_Calculator_with_reform_after_start_year(): # create Policy object using custom indexing rates irates = {2013: 0.01, 2014: 0.01, 2015: 0.02, 2016: 0.01, 2017: 0.03} parm = Policy(start_year=2013, num_years=len(irates), inflation_rates=irates) # specify reform in 2015, which is two years after Policy start_year reform = {2015: {}, 2016: {}} reform[2015]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600, 1300]] reform[2015]['_II_em'] = [5000] reform[2016]['_II_em'] = [6000] reform[2016]['_II_em_cpi'] = False parm.implement_reform(reform) recs = Records(data=TAX_DTA, weights=WEIGHTS, start_year=2009) calc = Calculator(policy=parm, records=recs) # compare actual and expected parameter values over all years exp_STD_Aged = np.array([[1500, 1200, 1200, 1500, 1500, 1200], [1550, 1200, 1200, 1550, 1550, 1200], [1600, 1300, 1600, 1300, 1600, 1300], [1632, 1326, 1632, 1326, 1632, 1326], [1648, 1339, 1648, 1339, 1648, 1339]]) exp_II_em = np.array([3900, 3950, 5000, 6000, 6000]) assert_array_equal(calc.policy._STD_Aged, exp_STD_Aged) assert_array_equal(calc.policy._II_em, exp_II_em) # compare actual and expected values for 2015 calc.increment_year() calc.increment_year() assert calc.current_year == 2015 exp_2015_II_em = 5000 assert_array_equal(calc.policy.II_em, exp_2015_II_em) exp_2015_STD_Aged = np.array([1600, 1300, 1600, 1300, 1600, 1300]) assert_array_equal(calc.policy.STD_Aged, exp_2015_STD_Aged)
def test_calculator_mtr_when_PT_rates_differ(): """ Test Calculator mtr method in special case. """ reform = {2013: {'_II_rt1': [0.40], '_II_rt2': [0.40], '_II_rt3': [0.40], '_II_rt4': [0.40], '_II_rt5': [0.40], '_II_rt6': [0.40], '_II_rt7': [0.40], '_PT_rt1': [0.30], '_PT_rt2': [0.30], '_PT_rt3': [0.30], '_PT_rt4': [0.30], '_PT_rt5': [0.30], '_PT_rt6': [0.30], '_PT_rt7': [0.30]}} funit = ( u'RECID,MARS,FLPDYR,e00200,e00200p,e00900,e00900p,extraneous\n' u'1, 1, 2009, 200000,200000, 100000,100000, 9999999999\n' ) rec = Records(pd.read_csv(StringIO(funit))) pol = Policy() calc1 = Calculator(policy=pol, records=rec) (_, mtr1, _) = calc1.mtr(variable_str='p23250') pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) (_, mtr2, _) = calc2.mtr(variable_str='p23250') assert np.allclose(mtr1, mtr2, rtol=0.0, atol=1e-06)
def diff_in_revenue(reform_on_II, orig_reform): policy_func = Policy() puf = pd.read_csv("./puf.csv") records_func = Records(puf) calc_func = Calculator(policy = policy_func, records = records_func) policy_bench = Policy() records_bench = Records(puf) calc_bench = Calculator(policy = policy_bench, records = records_bench) reform = { CURRENT_YEAR:{ "_II_rt1":[max(policy_bench._II_rt1[0] *(1 - reform_on_II),0.0)], "_II_rt2":[max(policy_bench._II_rt2[0] *(1 - reform_on_II),0.0)], "_II_rt3":[max(policy_bench._II_rt3[0] *(1 - reform_on_II),0.0)], "_II_rt4":[max(policy_bench._II_rt4[0] *(1 - reform_on_II),0.0)], "_II_rt5":[max(policy_bench._II_rt5[0] *(1 - reform_on_II),0.0)], "_II_rt6":[max(policy_bench._II_rt6[0] *(1 - reform_on_II),0.0)], "_II_rt7":[max(policy_bench._II_rt7[0] *(1 - reform_on_II),0.0)]} } policy_func.implement_reform(reform) policy_func.implement_reform(orig_reform) calc_func.advance_to_year(CURRENT_YEAR) calc_bench.advance_to_year(CURRENT_YEAR) calc_func.calc_all() calc_bench.calc_all() ans = ((calc_bench.records._combined*calc_bench.records.s006).sum()-(calc_func.records._combined*calc_func.records.s006).sum()) print("diff in revenue is ", ans) return ans
def test_make_Calculator_with_reform_after_start_year(records_2009): # create Policy object using custom indexing rates irates = {2013: 0.01, 2014: 0.01, 2015: 0.02, 2016: 0.01, 2017: 0.03} parm = Policy(start_year=2013, num_years=len(irates), inflation_rates=irates) # specify reform in 2015, which is two years after Policy start_year reform = {2015: {}, 2016: {}} reform[2015]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600, 1300]] reform[2015]['_II_em'] = [5000] reform[2016]['_II_em'] = [6000] reform[2016]['_II_em_cpi'] = False parm.implement_reform(reform) calc = Calculator(policy=parm, records=records_2009) # compare actual and expected parameter values over all years assert np.allclose(calc.policy._STD_Aged, np.array([[1500, 1200, 1200, 1500, 1500, 1200], [1550, 1200, 1200, 1550, 1550, 1200], [1600, 1300, 1600, 1300, 1600, 1300], [1632, 1326, 1632, 1326, 1632, 1326], [1648, 1339, 1648, 1339, 1648, 1339]]), atol=0.5, rtol=0.0) # handles rounding to dollars assert np.allclose(calc.policy._II_em, np.array([3900, 3950, 5000, 6000, 6000])) # compare actual and expected values for 2015 calc.increment_year() calc.increment_year() assert calc.current_year == 2015 assert np.allclose(calc.policy.II_em, 5000) assert np.allclose(calc.policy.STD_Aged, np.array([1600, 1300, 1600, 1300, 1600, 1300]))
def test_write_graph_file(cps_subsample): recs = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=recs) mtr = 0.20 * np.ones_like(cps_subsample['e00200']) vdf = calc.dataframe(['s006', 'e00200', 'c00100']) vdf['mtr1'] = mtr vdf['mtr2'] = mtr gdata = mtr_graph_data(vdf, calc.current_year, mtr_measure='ptax', alt_e00200p_text='Taxpayer Earnings', income_measure='agi', dollar_weighting=False) gplot = xtr_graph_plot(gdata) assert gplot htmlfname = temporary_filename(suffix='.html') try: write_graph_file(gplot, htmlfname, 'title') except Exception: # pylint: disable=broad-except if os.path.isfile(htmlfname): try: os.remove(htmlfname) except OSError: pass # sometimes we can't remove a generated temporary file assert 'write_graph_file()_ok' == 'no' # if try was successful, try to remove the file if os.path.isfile(htmlfname): try: os.remove(htmlfname) except OSError: pass # sometimes we can't remove a generated temporary file
def test_Calculator_advance_to_year(records_2009): policy = Policy() calc = Calculator(policy=policy, records=records_2009) calc.advance_to_year(2016) assert calc.current_year == 2016 with pytest.raises(ValueError): calc.advance_to_year(2015)
def test_mtr_graph_data(cps_subsample): recs = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=recs) year = calc.current_year with pytest.raises(ValueError): mtr_graph_data(None, year, mars='bad', income_measure='agi', dollar_weighting=True) with pytest.raises(ValueError): mtr_graph_data(None, year, mars=0, income_measure='expanded_income', dollar_weighting=True) with pytest.raises(ValueError): mtr_graph_data(None, year, mars=list()) with pytest.raises(ValueError): mtr_graph_data(None, year, mars='ALL', mtr_variable='e00200s') with pytest.raises(ValueError): mtr_graph_data(None, year, mtr_measure='badtax') with pytest.raises(ValueError): mtr_graph_data(None, year, income_measure='badincome') mtr = 0.20 * np.ones_like(cps_subsample['e00200']) vdf = calc.dataframe(['s006', 'MARS', 'e00200']) vdf['mtr1'] = mtr vdf['mtr2'] = mtr vdf = vdf[vdf['MARS'] == 1] gdata = mtr_graph_data(vdf, year, mars=1, mtr_wrt_full_compen=True, income_measure='wages', dollar_weighting=True) assert isinstance(gdata, dict)
def test_Calculator_mtr_when_PT_rates_differ(): reform = {2013: {'_II_rt1': [0.40], '_II_rt2': [0.40], '_II_rt3': [0.40], '_II_rt4': [0.40], '_II_rt5': [0.40], '_II_rt6': [0.40], '_II_rt7': [0.40], '_PT_rt1': [0.30], '_PT_rt2': [0.30], '_PT_rt3': [0.30], '_PT_rt4': [0.30], '_PT_rt5': [0.30], '_PT_rt6': [0.30], '_PT_rt7': [0.30]}} funit = ( u'RECID,MARS,FLPDYR,e00200,e00200p,e00900,e00900p\n' u'1, 1, 2015, 200000,200000, 100000,100000\n' ) pol1 = Policy() rec1 = Records(pd.read_csv(StringIO(funit))) calc1 = Calculator(policy=pol1, records=rec1) (_, mtr1, _) = calc1.mtr(variable_str='p23250') pol2 = Policy() pol2.implement_reform(reform) rec2 = Records(pd.read_csv(StringIO(funit))) calc2 = Calculator(policy=pol2, records=rec2) (_, mtr2, _) = calc2.mtr(variable_str='p23250') assert np.allclose(mtr1, mtr2, rtol=0.0, atol=1e-06)
def test_Calculator_diagnostic_table(): puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=Records.PUF_YEAR) beh = Behavior() beh.update_behavior({2013: {'_BE_sub': [0.4]}}) assert beh.has_response() calc = Calculator(policy=Policy(), records=puf, behavior=beh) calc.diagnostic_table(base_calc=calc)
def test_make_calculator_with_policy_reform(cps_subsample): """ Test Calculator class ctor with policy reform. """ rec = Records.cps_constructor(data=cps_subsample) year = rec.current_year # create a Policy object and apply a policy reform pol = Policy() reform = {2013: {'_II_em': [4000], '_II_em_cpi': False, '_STD_Aged': [[1600, 1300, 1300, 1600, 1600]], '_STD_Aged_cpi': False}} pol.implement_reform(reform) # create a Calculator object using this policy reform calc = Calculator(policy=pol, records=rec) # check that Policy object embedded in Calculator object is correct assert calc.current_year == year assert calc.policy_param('II_em') == 4000 assert np.allclose(calc.policy_param('_II_em'), np.array([4000] * Policy.DEFAULT_NUM_YEARS)) exp_STD_Aged = [[1600, 1300, 1300, 1600, 1600]] * Policy.DEFAULT_NUM_YEARS assert np.allclose(calc.policy_param('_STD_Aged'), np.array(exp_STD_Aged)) assert np.allclose(calc.policy_param('STD_Aged'), np.array([1600, 1300, 1300, 1600, 1600]))
def test_json_reform_url(): """ Test reading a JSON reform from a URL. Results from the URL are expected to match the results from the string. """ reform_str = """ { "policy": { // raise FICA payroll tax rate in 2018 and 2020 "FICA_ss_trt": { "2018": 0.130, "2020": 0.140 }, // raise Medicare payroll tax rate in 2019 and 2021 "FICA_mc_trt": { "2019": 0.030, "2021": 0.032 } } } """ reform_url = ('https://raw.githubusercontent.com/PSLmodels/' 'Tax-Calculator/master/taxcalc/reforms/ptaxes0.json') params_str = Calculator.read_json_param_objects(reform_str, None) params_url = Calculator.read_json_param_objects(reform_url, None) assert params_str == params_url
def test_translate_json_reform_suffixes_eic(): """ Test read_json_param_objects method using EIC-indexed parameter suffixes. """ json1 = """{"policy": { "_II_em": {"2020": [20000], "2015": [15000]}, "_EITC_c_0kids": {"2018": [510], "2019": [510]}, "_EITC_c_1kid": {"2019": [3400], "2018": [3400]}, "_EITC_c_2kids": {"2018": [5616], "2019": [5616]}, "_EITC_c_3+kids": {"2019": [6318], "2018": [6318]} }}""" pdict1 = Calculator.read_json_param_objects(reform=json1, assump=None) rdict1 = pdict1['policy'] json2 = """{"policy": { "_EITC_c": {"2019": [[510, 3400, 5616, 6318]], "2018": [[510, 3400, 5616, 6318]]}, "_II_em": {"2020": [20000], "2015": [15000]} }}""" pdict2 = Calculator.read_json_param_objects(reform=json2, assump=None) rdict2 = pdict2['policy'] assert len(rdict2) == len(rdict1) for year in rdict2.keys(): if '_II_em' in rdict2[year].keys(): assert np.allclose(rdict1[year]['_II_em'], rdict2[year]['_II_em'], atol=0.01, rtol=0.0) if '_EITC_c' in rdict2[year].keys(): assert np.allclose(rdict1[year]['_EITC_c'], rdict2[year]['_EITC_c'], atol=0.01, rtol=0.0)
def test_translate_json_reform_suffixes_mars_non_indexed(): """ Test read_json_param_objects method using MARS-indexed parameter suffixes. """ json1 = """{"policy": { "_II_em": {"2020": [20000], "2015": [15000]}, "_AMEDT_ec_joint": {"2018": [400000], "2016": [300000]}, "_AMEDT_ec_separate": {"2017": [150000], "2019": [200000]} }}""" pdict1 = Calculator.read_json_param_objects(reform=json1, assump=None) rdict1 = pdict1['policy'] json2 = """{"policy": { "_AMEDT_ec": {"2016": [[200000, 300000, 125000, 200000, 200000]], "2017": [[200000, 300000, 150000, 200000, 200000]], "2018": [[200000, 400000, 150000, 200000, 200000]], "2019": [[200000, 400000, 200000, 200000, 200000]]}, "_II_em": {"2015": [15000], "2020": [20000]} }}""" pdict2 = Calculator.read_json_param_objects(reform=json2, assump=None) rdict2 = pdict2['policy'] assert len(rdict2) == len(rdict1) for year in rdict2.keys(): if '_II_em' in rdict2[year].keys(): assert np.allclose(rdict1[year]['_II_em'], rdict2[year]['_II_em'], atol=0.01, rtol=0.0) if '_AMEDT_ec' in rdict2[year].keys(): assert np.allclose(rdict1[year]['_AMEDT_ec'], rdict2[year]['_AMEDT_ec'], atol=0.01, rtol=0.0)
def test_noreform_documentation(): """ Test automatic documentation creation. """ reform_json = """ { "policy": {} } """ assump_json = """ { "consumption": {}, "growdiff_baseline": {}, "growdiff_response": {} } """ params = Calculator.read_json_param_objects(reform_json, assump_json) assert isinstance(params, dict) actual_doc = Calculator.reform_documentation(params) expected_doc = ( 'REFORM DOCUMENTATION\n' 'Baseline Growth-Difference Assumption Values by Year:\n' 'none: using default baseline growth assumptions\n' 'Policy Reform Parameter Values by Year:\n' 'none: using current-law policy parameters\n' ) assert actual_doc == expected_doc
def test_itax_compare(tests_path, using_puf, puf_fullsample, cps_fullsample): """ Conduct income tax comparisons using ITAX data. """ using_puf_adjust_ratios = True # generate 2015 estimates by AGI category using Tax-Calculator if using_puf: if using_puf_adjust_ratios: recs = Records(data=puf_fullsample) else: recs = Records(data=puf_fullsample, adjust_ratios=None) else: recs = Records.cps_constructor(data=cps_fullsample) calc = Calculator(policy=Policy(), records=recs, verbose=False) calc.advance_to_year(2015) calc.calc_all() # open actual output file if using_puf: afilename = os.path.join(tests_path, 'cmpi_puf_actual.txt') else: afilename = os.path.join(tests_path, 'cmpi_cps_actual.txt') afile = open(afilename, 'w') # write compare results to afile for cname in sorted(ITAX.keys()): comparison(cname, calc, ITAX, afile) # close actual output file afile.close() # check for differences between actual and expect output files efilename = afilename.replace('actual', 'expect') differences(afilename, efilename)
def test_consumption_response(puf_1991, weights_1991): consump = Consumption() mpc = 0.5 consumption_response = {2013: {"_MPC_e20400": [mpc]}} consump.update_consumption(consumption_response) # test incorrect call to response method with pytest.raises(ValueError): consump.response(list(), 1) # test correct call to response method recs = Records(data=puf_1991, weights=weights_1991, start_year=2009) pre = copy.deepcopy(recs.e20400) consump.response(recs, 1.0) post = recs.e20400 actual_diff = post - pre expected_diff = np.ones(recs.dim) * mpc assert np.allclose(actual_diff, expected_diff) # compute earnings mtr with no consumption response recs0 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc0 = Calculator(policy=Policy(), records=recs0, consumption=None) ided0 = copy.deepcopy(recs0.e20400) (mtr0_ptax, mtr0_itax, _) = calc0.mtr(variable_str="e00200p", wrt_full_compensation=False) assert np.allclose(calc0.records.e20400, ided0) # compute earnings mtr with consumption response recs1 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc1 = Calculator(policy=Policy(), records=recs1, consumption=None) assert np.allclose(calc1.records.e20400, ided0) calc1.consumption.update_consumption(consumption_response) (mtr1_ptax, mtr1_itax, _) = calc1.mtr(variable_str="e00200p", wrt_full_compensation=False) assert np.allclose(calc1.records.e20400, ided0) # confirm that payroll mtr values are no different assert np.allclose(mtr1_ptax, mtr0_ptax) # confirm that all mtr with cons-resp are no greater than without cons-resp assert np.all(np.less_equal(mtr1_itax, mtr0_itax)) # confirm that some mtr with cons-resp are less than without cons-resp assert np.any(np.less(mtr1_itax, mtr0_itax))
def test_n65(cps_subsample): """ Test n65 method. """ recs = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=recs) assert calc.n65().sum() > 1500
def test_diagnostic_table(cps_subsample): """ Test diagnostic_table method. """ recs = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=recs) adt = calc.diagnostic_table(3) assert isinstance(adt, pd.DataFrame)
def test_Calculator_advance_to_year(): policy = Policy() puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009) calc = Calculator(policy=policy, records=puf) calc.advance_to_year(2016) assert calc.current_year == 2016 with pytest.raises(ValueError): calc.advance_to_year(2015)
def test_mtr_plot(records_2009): pol = Policy() behv = Behavior() calc = Calculator(policy=pol, records=records_2009, behavior=behv) calc.calc_all() source = get_mtr_data(calc, calc, weighting='wage_weighted', weight_by_income_measure=True) plot = mtr_plot(source)
def test_Calculator_mtr(): policy = Policy() puf = Records(TAX_DTA, weights=WEIGHTS, start_year=2009) calc = Calculator(policy=policy, records=puf) (mtr_FICA, mtr_IIT, mtr) = calc.mtr() assert type(mtr) == np.ndarray assert np.array_equal(mtr, mtr_FICA) is False assert np.array_equal(mtr_FICA, mtr_IIT) is False
def test_dist_table_sum_row(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=rec) calc.calc_all() tb1 = create_distribution_table(calc.distribution_table_dataframe(), 'standard_income_bins', 'expanded_income') tb2 = create_distribution_table(calc.distribution_table_dataframe(), 'soi_agi_bins', 'expanded_income') assert np.allclose(tb1[-1:], tb2[-1:])
def test_convert_reform_dict(): with pytest.raises(ValueError): rdict = Calculator.convert_reform_dict({2013: {'2013': [40000]}}) with pytest.raises(ValueError): rdict = Calculator.convert_reform_dict({'_II_em': {2013: [40000]}}) with pytest.raises(ValueError): rdict = Calculator.convert_reform_dict({4567: {2013: [40000]}}) with pytest.raises(ValueError): rdict = Calculator.convert_reform_dict({'_II_em': 40000})
def test_Calculator_current_law_version(records_2009): policy = Policy() reform = {2013: {'_II_rt7': [0.45]}} policy.implement_reform(reform) calc = Calculator(policy=policy, records=records_2009) calc_clp = calc.current_law_version() assert isinstance(calc_clp, Calculator) assert calc.policy.II_rt6 == calc_clp.policy.II_rt6 assert calc.policy.II_rt7 != calc_clp.policy.II_rt7
def test_dist_table_sum_row(records_2009): # Create a default Policy object policy1 = Policy() # Create a Calculator calc1 = Calculator(policy=policy1, records=records_2009) calc1.calc_all() t1 = create_distribution_table(calc1.records, groupby="small_income_bins", result_type="weighted_sum") t2 = create_distribution_table(calc1.records, groupby="large_income_bins", result_type="weighted_sum") npt.assert_allclose(t1[-1:], t2[-1:]) t3 = create_distribution_table(calc1.records, groupby="small_income_bins", result_type="weighted_avg")
def test_atr_graph(cps_subsample): """ Test atr_graph method. """ recs = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=recs) fig = calc.atr_graph(calc, mars=2, atr_measure='itax') assert fig fig = calc.atr_graph(calc, atr_measure='ptax') assert fig
def test_distribution_tables(cps_subsample): """ Test distribution_tables method. """ pol = Policy() recs = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=recs) assert calc1.current_year == 2014 calc1.calc_all() dt1, dt2 = calc1.distribution_tables(None, 'weighted_deciles') assert isinstance(dt1, pd.DataFrame) assert dt2 is None dt1, dt2 = calc1.distribution_tables(calc1, 'weighted_deciles') assert isinstance(dt1, pd.DataFrame) assert isinstance(dt2, pd.DataFrame) reform = {2014: {'_UBI_u18': [1000], '_UBI_1820': [1000], '_UBI_21': [1000]}} pol.implement_reform(reform) assert not pol.parameter_errors calc2 = Calculator(policy=pol, records=recs) calc2.calc_all() dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles') assert isinstance(dt1, pd.DataFrame) assert isinstance(dt2, pd.DataFrame)
def test_calculator_using_nonstd_input(rawinputfile): """ Test Calculator using non-standard input records. """ # check Calculator handling of raw, non-standard input data with no aging pol = Policy() pol.set_year(RAWINPUTFILE_YEAR) # set policy params to input data year nonstd = Records(data=rawinputfile.name, gfactors=None, # keeps raw data unchanged weights=None, start_year=RAWINPUTFILE_YEAR) # set raw input data year assert nonstd.array_length == RAWINPUTFILE_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == RAWINPUTFILE_YEAR calc.calc_all() assert calc.weighted_total('e00200') == 0 assert calc.total_weight() == 0 varlist = ['RECID', 'MARS'] dframe = calc.dataframe(varlist) assert isinstance(dframe, pd.DataFrame) assert dframe.shape == (RAWINPUTFILE_FUNITS, len(varlist)) mars = calc.array('MARS') assert isinstance(mars, np.ndarray) assert mars.shape == (RAWINPUTFILE_FUNITS,) exp_iitax = np.zeros((nonstd.array_length,)) assert np.allclose(calc.array('iitax'), exp_iitax) mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False) exp_mtr_ptax = np.zeros((nonstd.array_length,)) exp_mtr_ptax.fill(0.153) assert np.allclose(mtr_ptax, exp_mtr_ptax)
def test_calculator_advance_to_year(cps_subsample): """ Test Calculator advance_to_year method. """ rec = Records.cps_constructor(data=cps_subsample) pol = Policy() calc = Calculator(policy=pol, records=rec) calc.advance_to_year(2016) assert calc.current_year == 2016 with pytest.raises(ValueError): calc.advance_to_year(2015)
def test_Calculator_attr_access_to_policy(records_2009): policy = Policy() calc = Calculator(policy=policy, records=records_2009) assert hasattr(calc.records, 'c01000') assert hasattr(calc.policy, '_AMT_Child_em') assert hasattr(calc, 'policy')
def test_create_tables(cps_subsample): # pylint: disable=too-many-statements,too-many-branches # create a current-law Policy object and Calculator object calc1 rec = Records.cps_constructor(data=cps_subsample) pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.calc_all() # create a policy-reform Policy object and Calculator object calc2 reform = {2013: {'_II_rt1': [0.15]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.calc_all() test_failure = False # test creating various difference tables diff = create_difference_table(calc1.dataframe(DIFF_VARIABLES), calc2.dataframe(DIFF_VARIABLES), 'standard_income_bins', 'combined') assert isinstance(diff, pd.DataFrame) tabcol = 'pc_aftertaxinc' expected = [ np.nan, np.nan, -0.16, -0.57, -0.72, -0.69, -0.82, -0.80, -0.75, -0.65, -0.23, -0.09, -0.06, -0.59 ] if not np.allclose( diff[tabcol].values, expected, atol=0.005, rtol=0.0, equal_nan=True): test_failure = True print('diff xbin', tabcol) for val in diff[tabcol].values: print('{:.2f},'.format(val)) diff = create_difference_table(calc1.dataframe(DIFF_VARIABLES), calc2.dataframe(DIFF_VARIABLES), 'weighted_deciles', 'combined') assert isinstance(diff, pd.DataFrame) tabcol = 'tot_change' expected = [ 0, 0, 1219678, 15503037, 25922077, 35000592, 48336897, 62637728, 79750078, 93136108, 116996252, 102458801, 580961247, 63156380, 33664610, 5637811 ] if not np.allclose(diff[tabcol].values, expected, atol=0.51, rtol=0.0): test_failure = True print('diff xdec', tabcol) for val in diff[tabcol].values: print('{:.0f},'.format(val)) tabcol = 'share_of_change' expected = [ 0.00, 0.00, 0.21, 2.67, 4.46, 6.02, 8.32, 10.78, 13.73, 16.03, 20.14, 17.64, 100.00, 10.87, 5.79, 0.97 ] if not np.allclose(diff[tabcol].values, expected, atol=0.005, rtol=0.0): test_failure = True print('diff xdec', tabcol) for val in diff[tabcol].values: print('{:.2f},'.format(val)) tabcol = 'pc_aftertaxinc' expected = [ np.nan, np.nan, -0.15, -0.62, -0.70, -0.73, -0.78, -0.80, -0.80, -0.74, -0.71, -0.30, -0.59, -0.55, -0.25, -0.06 ] if not np.allclose( diff[tabcol].values, expected, atol=0.005, rtol=0.0, equal_nan=True): test_failure = True print('diff xdec', tabcol) for val in diff[tabcol].values: print('{:.2f},'.format(val)) tabcol = 'pc_aftertaxinc' expected = [ np.nan, np.nan, -0.15, -0.62, -0.70, -0.73, -0.78, -0.80, -0.80, -0.74, -0.71, -0.30, -0.59, -0.55, -0.25, -0.06 ] if not np.allclose( diff[tabcol].values, expected, atol=0.005, rtol=0.0, equal_nan=True): test_failure = True print('diff xdec', tabcol) for val in diff[tabcol].values: print('{:.2f},'.format(val)) # test creating various distribution tables dist, _ = calc2.distribution_tables(None, 'weighted_deciles') assert isinstance(dist, pd.DataFrame) tabcol = 'iitax' expected = [ 0, 0, -53644343, -65258622, -57617119, 37391333, 200879230, 329784586, 553827330, 1015854407, 1731283600, 7090603505, 10783103907, 1638192777, 2213960052, 3238450675 ] if not np.allclose(dist[tabcol].values, expected, atol=0.5, rtol=0.0): test_failure = True print('dist xdec', tabcol) for val in dist[tabcol].values: print('{:.0f},'.format(val)) tabcol = 'num_returns_ItemDed' expected = [ 0, 0, 2561, 12610, 21936, 29172, 50890, 61563, 78247, 91823, 118523, 128886, 596211, 63986, 51634, 13266 ] if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0): test_failure = True print('dist xdec', tabcol) for val in dist[tabcol].values: print('{:.0f},'.format(val)) tabcol = 'expanded_income' expected = [ 0, 0, 835224673, 2639667638, 3940559051, 5286856071, 6972849344, 8881099529, 11467767759, 14761195525, 19832126806, 44213000235, 118830346631, 14399218059, 16868648076, 12945134101 ] if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0): test_failure = True print('dist xdec', tabcol) for val in dist[tabcol].values: print('{:.0f},'.format(val)) tabcol = 'aftertax_income' expected = [ 0, 0, 818813684, 2466000535, 3671150517, 4790979126, 6173998985, 7754183496, 9907604744, 12510477225, 16273592612, 33915377411, 98282178334, 11345456373, 13400757263, 9169163776 ] if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0): test_failure = True print('dist xdec', tabcol) for val in dist[tabcol].values: print('{:.0f},'.format(val)) dist, _ = calc2.distribution_tables(None, 'standard_income_bins') assert isinstance(dist, pd.DataFrame) tabcol = 'iitax' expected = [ 0, 0, -42244205, -76727831, -62581860, 53797887, 217016689, 723516183, 1108097059, 3272479928, 2818979541, 950296405, 1820474110, 10783103907 ] if not np.allclose(dist[tabcol], expected, atol=0.5, rtol=0.0): test_failure = True print('dist xbin', tabcol) for val in dist[tabcol].values: print('{:.0f},'.format(val)) tabcol = 'num_returns_ItemDed' expected = [ 0, 0, 1202, 13614, 27272, 34407, 48265, 117225, 103319, 181885, 61014, 5126, 2882, 596211 ] if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0): test_failure = True print('dist xbin', tabcol) for val in dist[tabcol].values: print('{:.0f},'.format(val)) if test_failure: assert 1 == 2
def test_Calculator_create_difference_table(puf_1991, weights_1991): # create current-law Policy object and use to create Calculator calc1 policy1 = Policy() puf1 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc1 = Calculator(policy=policy1, records=puf1) calc1.advance_to_year(2013) calc1.calc_all() # create policy-reform Policy object and use to create Calculator calc2 policy2 = Policy() reform = {2013: {'_II_rt7': [0.45]}} policy2.implement_reform(reform) puf2 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc2 = Calculator(policy=policy2, records=puf2) calc2.advance_to_year(2013) calc2.calc_all() # create difference table and check that it is a Pandas DataFrame dtable = create_difference_table(calc1.records, calc2.records, groupby="weighted_deciles") assert isinstance(dtable, pd.DataFrame)
def reform_results(reform_dict, puf_data): """ Return actual results of the reform specified in reform_dict. """ # pylint: disable=too-many-locals # create current-law-policy Calculator object pol = Policy() rec = Records(data=puf_data) calc1 = Calculator(policy=pol, records=rec, verbose=False, behavior=None) # create reform Calculator object with possible behavioral responses start_year = reform_dict['start_year'] beh = Behavior() if '_BE_cg' in reform_dict['value']: elasticity = reform_dict['value']['_BE_cg'] del reform_dict['value']['_BE_cg'] # in order to have a valid reform beh_assump = {start_year: {'_BE_cg': elasticity}} beh.update_behavior(beh_assump) reform = {start_year: reform_dict['value']} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec, verbose=False, behavior=beh) # increment both calculators to reform's start_year calc1.advance_to_year(start_year) calc2.advance_to_year(start_year) # calculate prereform and postreform output for several years output_type = reform_dict['output_type'] num_years = 4 results = list() for _ in range(0, num_years): calc1.calc_all() prereform = calc1.array(output_type) if calc2.behavior.has_response(): calc_clp = calc2.current_law_version() calc2_br = Behavior.response(calc_clp, calc2) postreform = calc2_br.array(output_type) else: calc2.calc_all() postreform = calc2.array(output_type) diff = postreform - prereform weighted_sum_diff = (diff * calc1.array('s006')).sum() * 1.0e-9 results.append(weighted_sum_diff) calc1.increment_year() calc2.increment_year() # write actual results to actual_str actual_str = 'Tax-Calculator' for iyr in range(0, num_years): actual_str += ',{:.1f}'.format(results[iyr]) return actual_str
def test_ID_HC_vs_BS(cps_subsample): """ Test that complete haircut of itemized deductions produces same results as a 100% benefit surtax with no benefit deduction. """ rec = Records.cps_constructor(data=cps_subsample) # specify complete-haircut reform policy and Calculator object hc_reform = {2013: {'_ID_Medical_hc': [1.0], '_ID_StateLocalTax_hc': [1.0], '_ID_RealEstate_hc': [1.0], '_ID_Casualty_hc': [1.0], '_ID_Miscellaneous_hc': [1.0], '_ID_InterestPaid_hc': [1.0], '_ID_Charity_hc': [1.0]}} hc_policy = Policy() hc_policy.implement_reform(hc_reform) hc_calc = Calculator(policy=hc_policy, records=rec) hc_calc.calc_all() # specify benefit-surtax reform policy and Calculator object bs_reform = {2013: {'_ID_BenefitSurtax_crt': [0.0], '_ID_BenefitSurtax_trt': [1.0]}} bs_policy = Policy() bs_policy.implement_reform(bs_reform) bs_calc = Calculator(policy=bs_policy, records=rec) bs_calc.calc_all() # compare calculated tax results generated by the two reforms assert np.allclose(hc_calc.array('payrolltax'), bs_calc.array('payrolltax')) assert np.allclose(hc_calc.array('iitax'), bs_calc.array('iitax'))
def test_agg(tests_path, cps_fullsample): """ Test current-law aggregate taxes using cps.csv file. """ # pylint: disable=too-many-statements,too-many-locals nyrs = 10 # create a baseline Policy object with current-law policy parameters baseline_policy = Policy() # create a Records object (rec) containing all cps.csv input records recs = Records.cps_constructor(data=cps_fullsample) # create a Calculator object using baseline policy and cps records calc = Calculator(policy=baseline_policy, records=recs) calc.advance_to_year(START_YEAR) calc_start_year = calc.current_year # create aggregate diagnostic table (adt) as a Pandas DataFrame object adt = calc.diagnostic_table(nyrs).round(1) # column labels are int taxes_fullsample = adt.loc["Combined Liability ($b)"] # compare actual DataFrame, adt, with the expected DataFrame, edt aggres_path = os.path.join(tests_path, 'cpscsv_agg_expect.csv') edt = pd.read_csv(aggres_path, index_col=False) # column labels are str edt.drop('Unnamed: 0', axis='columns', inplace=True) assert len(adt.columns.values) == len(edt.columns.values) diffs = False for icol in adt.columns.values: if not np.allclose(adt[icol], edt[str(icol)]): diffs = True if diffs: new_filename = '{}{}'.format(aggres_path[:-10], 'actual.csv') adt.to_csv(new_filename, float_format='%.1f') msg = 'CPSCSV AGG RESULTS DIFFER\n' msg += '-------------------------------------------------\n' msg += '--- NEW RESULTS IN cpscsv_agg_actual.csv FILE ---\n' msg += '--- if new OK, copy cpscsv_agg_actual.csv to ---\n' msg += '--- cpscsv_agg_expect.csv ---\n' msg += '--- and rerun test. ---\n' msg += '--- (both are in taxcalc/tests) ---\n' msg += '-------------------------------------------------\n' raise ValueError(msg) # create aggregate diagnostic table using unweighted sub-sample of records rn_seed = 180 # to ensure sub-sample is always the same subfrac = 0.07# 0.03 # sub-sample fraction subsample = cps_fullsample.sample(frac=subfrac, random_state=rn_seed) recs_subsample = Records.cps_constructor(data=subsample) calc_subsample = Calculator(policy=baseline_policy, records=recs_subsample) calc_subsample.advance_to_year(START_YEAR) adt_subsample = calc_subsample.diagnostic_table(nyrs) # compare combined tax liability from full and sub samples for each year taxes_subsample = adt_subsample.loc["Combined Liability ($b)"] print('taxes_submsampe = ', taxes_subsample) print('TAXES full sample = ', taxes_fullsample) msg = '' for cyr in range(calc_start_year, calc_start_year + nyrs): if cyr == calc_start_year: reltol = 0.0232 else: reltol = 0.0270 if not np.allclose(taxes_subsample[cyr], taxes_fullsample[cyr], atol=0.0, rtol=reltol): reldiff = (taxes_subsample[cyr] / taxes_fullsample[cyr]) - 1. line1 = '\nCPSCSV AGG SUB-vs-FULL RESULTS DIFFER IN {}' line2 = '\n when subfrac={:.3f}, rtol={:.4f}, seed={}' line3 = '\n with sub={:.3f}, full={:.3f}, rdiff={:.4f}' msg += line1.format(cyr) msg += line2.format(subfrac, reltol, rn_seed) msg += line3.format(taxes_subsample[cyr], taxes_fullsample[cyr], reldiff) if msg: raise ValueError(msg)
def test_make_calculator_raises_on_no_policy(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) with pytest.raises(ValueError): Calculator(records=rec)
def test_diagnostic_table(cps_subsample): recs = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=recs) adt = calc.diagnostic_table(3) assert isinstance(adt, pd.DataFrame)
def test_json_assump_url(): assump_str = """ { "consumption": { "_BEN_housing_value": {"2017": [1.0]}, "_BEN_snap_value": {"2017": [1.0]}, "_BEN_tanf_value": {"2017": [1.0]}, "_BEN_vet_value": {"2017": [1.0]}, "_BEN_wic_value": {"2017": [1.0]}, "_BEN_mcare_value": {"2017": [1.0]}, "_BEN_mcaid_value": {"2017": [1.0]}, "_BEN_other_value": {"2017": [1.0]}, "_MPC_e17500": {"2017": [0.0]}, "_MPC_e18400": {"2017": [0.0]}, "_MPC_e19800": {"2017": [0.0]}, "_MPC_e20400": {"2017": [0.0]} }, "behavior": { "_BE_inc": {"2017": [0.0]}, "_BE_sub": {"2017": [0.0]}, "_BE_cg": {"2017": [0.0]} }, "growdiff_baseline": { "_ABOOK": {"2017": [0.0]}, "_ACGNS": {"2017": [0.0]}, "_ACPIM": {"2017": [0.0]}, "_ACPIU": {"2017": [0.0]}, "_ADIVS": {"2017": [0.0]}, "_AINTS": {"2017": [0.0]}, "_AIPD": {"2017": [0.0]}, "_ASCHCI": {"2017": [0.0]}, "_ASCHCL": {"2017": [0.0]}, "_ASCHEI": {"2017": [0.0]}, "_ASCHEL": {"2017": [0.0]}, "_ASCHF": {"2017": [0.0]}, "_ASOCSEC": {"2017": [0.0]}, "_ATXPY": {"2017": [0.0]}, "_AUCOMP": {"2017": [0.0]}, "_AWAGE": {"2017": [0.0]}, "_ABENOTHER": {"2017": [0.0]}, "_ABENMCARE": {"2017": [0.0]}, "_ABENMCAID": {"2017": [0.0]}, "_ABENSSI": {"2017": [0.0]}, "_ABENSNAP": {"2017": [0.0]}, "_ABENWIC": {"2017": [0.0]}, "_ABENHOUSING": {"2017": [0.0]}, "_ABENTANF": {"2017": [0.0]}, "_ABENVET": {"2017": [0.0]} }, "growdiff_response": { "_ABOOK": {"2017": [0.0]}, "_ACGNS": {"2017": [0.0]}, "_ACPIM": {"2017": [0.0]}, "_ACPIU": {"2017": [0.0]}, "_ADIVS": {"2017": [0.0]}, "_AINTS": {"2017": [0.0]}, "_AIPD": {"2017": [0.0]}, "_ASCHCI": {"2017": [0.0]}, "_ASCHCL": {"2017": [0.0]}, "_ASCHEI": {"2017": [0.0]}, "_ASCHEL": {"2017": [0.0]}, "_ASCHF": {"2017": [0.0]}, "_ASOCSEC": {"2017": [0.0]}, "_ATXPY": {"2017": [0.0]}, "_AUCOMP": {"2017": [0.0]}, "_AWAGE": {"2017": [0.0]}, "_ABENOTHER": {"2017": [0.0]}, "_ABENMCARE": {"2017": [0.0]}, "_ABENMCAID": {"2017": [0.0]}, "_ABENSSI": {"2017": [0.0]}, "_ABENSNAP": {"2017": [0.0]}, "_ABENWIC": {"2017": [0.0]}, "_ABENHOUSING": {"2017": [0.0]}, "_ABENTANF": {"2017": [0.0]}, "_ABENVET": {"2017": [0.0]} }, "growmodel": { "_active": {"2017": [false]} } } """ assump_url = ('https://raw.githubusercontent.com/open-source-economics/' 'Tax-Calculator/master/taxcalc/assumptions/' 'economic_assumptions_template.json') params_str = Calculator.read_json_param_objects(None, assump_str) params_url = Calculator.read_json_param_objects(None, assump_url) assert params_str == params_url
def test_read_json_param_with_suffixes_and_errors(): # test interaction of policy parameter suffixes and reform errors # (fails without 0.10.2 bug fix as reported by Hank Doupe in PB PR#641) reform = { u'policy': { u'_II_brk4_separate': { u'2017': [5000.0] }, u'_STD_separate': { u'2017': [8000.0] }, u'_STD_single': { u'2018': [1000.0] }, u'_II_brk2_headhousehold': { u'2017': [1000.0] }, u'_II_brk4_single': { u'2017': [500.0] }, u'_STD_joint': { u'2017': [10000.0], u'2020': [150.0] }, u'_II_brk2_separate': { u'2017': [1000.0] }, u'_II_brk2_single': { u'2017': [1000.0] }, u'_II_brk2_joint': { u'2017': [1000.0] }, u'_FICA_ss_trt': { u'2017': [-1.0], u'2019': [0.1] }, u'_II_brk4_headhousehold': { u'2017': [500.0] }, u'_STD_headhousehold': { u'2017': [10000.0], u'2020': [150.0] }, u'_ID_Medical_frt': { u'2019': [0.06] }, u'_II_brk4_joint': { u'2017': [500.0] }, u'_ID_BenefitSurtax_Switch_medical': { u'2017': [True] } } } json_reform = json.dumps(reform) params = Calculator.read_json_param_objects(json_reform, None) assert isinstance(params, dict) pol = Policy() pol.ignore_reform_errors() pol.implement_reform(params['policy'], print_warnings=False, raise_errors=False) assert len(pol.parameter_errors) > 0 assert len(pol.parameter_warnings) > 0
def test_distribution_tables(cps_subsample): pol = Policy() recs = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=recs) assert calc1.current_year == 2014 calc1.calc_all() dt1, dt2 = calc1.distribution_tables(None, 'weighted_deciles') assert isinstance(dt1, pd.DataFrame) assert dt2 is None dt1, dt2 = calc1.distribution_tables(calc1, 'weighted_deciles') assert isinstance(dt1, pd.DataFrame) assert isinstance(dt2, pd.DataFrame) reform = { 2014: { '_UBI_u18': [1000], '_UBI_1820': [1000], '_UBI_21': [1000] } } pol.implement_reform(reform) assert not pol.parameter_errors calc2 = Calculator(policy=pol, records=recs) calc2.calc_all() dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles') assert isinstance(dt1, pd.DataFrame) assert isinstance(dt2, pd.DataFrame)
def test_make_calculator_deepcopy(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=rec) calc2 = copy.deepcopy(calc1) assert isinstance(calc2, Calculator)
def test_ID_RealEstate_HC_vs_CRT(cps_subsample): """ Test that a cap on all state, local, and foreign real estate tax deductions at 0 percent of AGI is equivalent to a complete haircut on the same real estate tax deductions. """ rec = Records.cps_constructor(data=cps_subsample) # specify real estate complete haircut reform policy and Calculator object hc_reform = {2013: {'_ID_RealEstate_hc': [1.0]}} hc_policy = Policy() hc_policy.implement_reform(hc_reform) hc_calc = Calculator(policy=hc_policy, records=rec) hc_calc.calc_all() # specify AGI cap reform policy and Calculator object crt_reform = {2013: {'_ID_RealEstate_crt': [0.0]}} crt_policy = Policy() crt_policy.implement_reform(crt_reform) crt_calc = Calculator(policy=crt_policy, records=rec) crt_calc.calc_all() # compare calculated tax results generated by the two reforms assert np.allclose(hc_calc.array('payrolltax'), crt_calc.array('payrolltax')) assert np.allclose(hc_calc.array('iitax'), crt_calc.array('iitax'))
def test_calculator_mtr(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) calcx = Calculator(policy=Policy(), records=rec) calcx.calc_all() combinedx = calcx.array('combined') c00100x = calcx.array('c00100') calc = Calculator(policy=Policy(), records=rec) recs_pre_e00200p = copy.deepcopy(calc.array('e00200p')) (mtr_ptx, mtr_itx, mtr_cmb) = calc.mtr(variable_str='e00200p', zero_out_calculated_vars=True) recs_post_e00200p = calc.array('e00200p') assert np.allclose(recs_post_e00200p, recs_pre_e00200p) assert np.allclose(calc.array('combined'), combinedx) assert np.allclose(calc.array('c00100'), c00100x) assert np.array_equal(mtr_cmb, mtr_ptx) is False assert np.array_equal(mtr_ptx, mtr_itx) is False with pytest.raises(ValueError): calc.mtr(variable_str='bad_income_type') (_, _, mtr_combined) = calc.mtr(variable_str='e00200s', calc_all_already_called=True) assert isinstance(mtr_combined, np.ndarray) (_, _, mtr_combined) = calc.mtr(variable_str='e00650', negative_finite_diff=True, calc_all_already_called=True) assert isinstance(mtr_combined, np.ndarray) (_, _, mtr_combined) = calc.mtr(variable_str='e00900p', calc_all_already_called=True) assert isinstance(mtr_combined, np.ndarray) (_, _, mtr_combined) = calc.mtr(variable_str='e01700', calc_all_already_called=True) assert isinstance(mtr_combined, np.ndarray) (_, _, mtr_combined) = calc.mtr(variable_str='e26270', calc_all_already_called=True) assert isinstance(mtr_combined, np.ndarray) (_, _, mtr_combined) = calc.mtr(variable_str='e00200p', calc_all_already_called=True) assert np.allclose(mtr_combined, mtr_cmb) assert np.allclose(calc.array('combined'), combinedx) assert np.allclose(calc.array('c00100'), c00100x)
def test_make_Calculator_raises_on_no_policy(records_2009): with pytest.raises(ValueError): calc = Calculator(records=records_2009)
def test_read_bad_json_reform_file(bad1reformfile, bad2reformfile, bad3reformfile): with pytest.raises(ValueError): Calculator.read_json_param_objects(bad1reformfile.name, None) with pytest.raises(ValueError): Calculator.read_json_param_objects(bad2reformfile.name, None) with pytest.raises(ValueError): Calculator.read_json_param_objects(bad3reformfile.name, None) with pytest.raises(ValueError): Calculator.read_json_param_objects(list(), None) with pytest.raises(ValueError): Calculator.read_json_param_objects(None, 'unknown_file_name') with pytest.raises(ValueError): Calculator.read_json_param_objects(None, list())
def test_ce_aftertax_income(cps_subsample): # test certainty_equivalent() function with con>cmin con = 5000 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) assert con > round(certainty_equivalent((math.log(con) - 0.1), 1, cmin), 6) # test certainty_equivalent() function with con<cmin con = 500 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) # test with require_no_agg_tax_change equal to False rec = Records.cps_constructor(data=cps_subsample, no_benefits=True) cyr = 2020 # specify calc1 and calc_all() for cyr pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.advance_to_year(cyr) calc1.calc_all() # specify calc2 and calc_all() for cyr reform = {2019: {'_II_em': [1000]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(cyr) calc2.calc_all() df1 = calc1.dataframe(['s006', 'combined', 'expanded_income']) df2 = calc2.dataframe(['s006', 'combined', 'expanded_income']) cedict = ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=False) assert isinstance(cedict, dict) np.allclose(cedict['ceeu1'], [55641, 27167, 5726, 2229, 1565], atol=0.5, rtol=0.0) np.allclose(cedict['ceeu2'], [54629, 26698, 5710, 2229, 1565], atol=0.5, rtol=0.0) # test with require_no_agg_tax_change equal to True with pytest.raises(ValueError): ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=True) # test with require_no_agg_tax_change equal to False and custom_params params = {'crra_list': [0, 2], 'cmin_value': 2000} with pytest.raises(ValueError): ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=True, custom_params=params)
def test_dec_graph_plots(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample, no_benefits=True) calc1 = Calculator(policy=pol, records=rec) year = 2020 calc1.advance_to_year(year) reform = { year: { '_SS_Earnings_c': [9e99], # OASDI FICA tax on all earnings '_FICA_ss_trt': [0.107484] # lower rate to keep revenue unchanged } } pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(year) assert calc1.current_year == calc2.current_year calc1.calc_all() calc2.calc_all() fig = calc1.decile_graph(calc2) assert fig dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles') dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=True, include_negative_incomes=False) assert isinstance(dta, dict) dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=False, include_negative_incomes=True) assert isinstance(dta, dict) dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=False, include_negative_incomes=False) assert isinstance(dta, dict)
def test_reform_json_and_output(tests_path): """ Check that each JSON reform file can be converted into a reform dictionary that can then be passed to the Policy class implement_reform method that generates no parameter_errors. Then use each reform to generate static tax results for small set of filing units in a single tax_year and compare those results with expected results from a CSV-formatted file. """ # pylint: disable=too-many-statements,too-many-locals # embedded function used only in test_reform_json_and_output def write_res_file(calc, resfilename): """ Write calc output to CSV-formatted file with resfilename. """ varlist = [ 'RECID', 'c00100', 'standard', 'c04800', 'iitax', 'payrolltax' ] # varnames AGI STD TaxInc ITAX PTAX stats = calc.dataframe(varlist) stats['RECID'] = stats['RECID'].astype(int) with open(resfilename, 'w') as resfile: stats.to_csv(resfile, index=False, float_format='%.2f') # embedded function used only in test_reform_json_and_output def res_and_out_are_same(base): """ Return True if base.res.csv and base.out.csv file contents are same; return False if base.res.csv and base.out.csv file contents differ. """ resdf = pd.read_csv(base + '.res.csv') outdf = pd.read_csv(base + '.out.csv') diffs = False for col in resdf: if col in outdf: if not np.allclose(resdf[col], outdf[col]): diffs = True else: diffs = True return not diffs # specify Records object containing cases data tax_year = 2020 cases_path = os.path.join(tests_path, '..', 'reforms', 'cases.csv') cases = Records( data=cases_path, start_year=tax_year, # set raw input data year gfactors=None, # keeps raw data unchanged weights=None, adjust_ratios=None) # specify list of reform failures failures = list() # specify current-law-policy Calculator object calc = Calculator(policy=Policy(), records=cases, verbose=False) calc.advance_to_year(tax_year) calc.calc_all() res_path = cases_path.replace('cases.csv', 'clp.res.csv') write_res_file(calc, res_path) if res_and_out_are_same(res_path.replace('.res.csv', '')): os.remove(res_path) else: failures.append(res_path) del calc # read 2017_law.json reform file and specify its parameters dictionary pre_tcja_jrf = os.path.join(tests_path, '..', 'reforms', '2017_law.json') pre_tcja = Policy.read_json_reform(pre_tcja_jrf) # check reform file contents and reform results for each reform reforms_path = os.path.join(tests_path, '..', 'reforms', '*.json') json_reform_files = glob.glob(reforms_path) for jrf in json_reform_files: # determine reform's baseline by reading contents of jrf with open(jrf, 'r') as rfile: jrf_text = rfile.read() pre_tcja_baseline = 'Reform_Baseline: 2017_law.json' in jrf_text # implement the reform relative to its baseline reform = Policy.read_json_reform(jrf_text) pol = Policy() # current-law policy if pre_tcja_baseline: pol.implement_reform(pre_tcja) assert not pol.parameter_errors pol.implement_reform(reform) assert not pol.parameter_errors calc = Calculator(policy=pol, records=cases, verbose=False) calc.advance_to_year(tax_year) calc.calc_all() res_path = jrf.replace('.json', '.res.csv') write_res_file(calc, res_path) if res_and_out_are_same(res_path.replace('.res.csv', '')): os.remove(res_path) else: failures.append(res_path) del calc if failures: msg = 'Following reforms have res-vs-out differences:\n' for ref in failures: msg += '{}\n'.format(os.path.basename(ref)) raise ValueError(msg)
def reform_results(rid, reform_dict, puf_data, reform_2017_law): """ Return actual results of the reform specified by rid and reform_dict. """ # pylint: disable=too-many-locals rec = Records(data=puf_data) # create baseline Calculator object, calc1 pol = Policy() if reform_dict['baseline'] == '2017_law.json': pol.implement_reform(reform_2017_law) elif reform_dict['baseline'] == 'policy_current_law.json': pass else: msg = 'illegal baseline value {}' raise ValueError(msg.format(reform_dict['baseline'])) calc1 = Calculator(policy=pol, records=rec, verbose=False) # create reform Calculator object, calc2 start_year = reform_dict['start_year'] reform = dict() for name, value in reform_dict['value'].items(): reform[name] = {start_year: value} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec, verbose=False) # increment both Calculator objects to reform's start_year calc1.advance_to_year(start_year) calc2.advance_to_year(start_year) # calculate baseline and reform output for several years output_type = reform_dict['output_type'] num_years = 4 results = list() for _ in range(0, num_years): calc1.calc_all() baseline = calc1.array(output_type) calc2.calc_all() reform = calc2.array(output_type) diff = reform - baseline weighted_sum_diff = (diff * calc1.array('s006')).sum() * 1.0e-9 results.append(weighted_sum_diff) calc1.increment_year() calc2.increment_year() # write actual results to actual_str actual_str = '{}'.format(rid) for iyr in range(0, num_years): actual_str += ',{:.1f}'.format(results[iyr]) return actual_str
def test_mtr(): """ Test Tax-Calculator marginal tax rates with no policy reform using puf.csv Compute histograms for each marginal tax rate income type using sample input from the puf.csv file and writing output to a string, which is then compared for differences with EXPECTED_MTR_RESULTS. """ # pylint: disable=too-many-locals assert len(FICA_MTR_BIN_EDGES) == len(IIT_MTR_BIN_EDGES) # construct actual results string, res res = '' if MTR_NEG_DIFF: res += 'MTR computed using NEGATIVE finite_diff.\n' else: res += 'MTR computed using POSITIVE finite_diff.\n' # create a Policy object (clp) containing current-law policy parameters clp = Policy() clp.set_year(MTR_TAX_YEAR) # create a Records object (puf) containing puf.csv input records puf = Records(data=PUFCSV_PATH) recid = puf.RECID # pylint: disable=no-member # create a Calculator object using clp policy and puf records calc = Calculator(policy=clp, records=puf) res += '{} = {}\n'.format('Total number of data records', puf.dim) res += 'FICA mtr histogram bin edges:\n' res += ' {}\n'.format(FICA_MTR_BIN_EDGES) res += 'IIT mtr histogram bin edges:\n' res += ' {}\n'.format(IIT_MTR_BIN_EDGES) inctype_header = 'FICA and IIT mtr histogram bin counts for' # compute marginal tax rate (mtr) histograms for each mtr income type for inctype in Calculator.MTR_VALID_INCOME_TYPES: (mtr_fica, mtr_iit, _) = calc.mtr(income_type_str=inctype, negative_finite_diff=MTR_NEG_DIFF, wrt_full_compensation=False) res += '{} {}:\n'.format(inctype_header, inctype) res += mtr_bin_counts(mtr_fica, FICA_MTR_BIN_EDGES, recid) res += mtr_bin_counts(mtr_iit, IIT_MTR_BIN_EDGES, recid) # generate differences between actual and expected results actual = res.splitlines(True) with open(MTRRES_PATH, 'r') as expected_file: txt = expected_file.read() expected_results = txt.rstrip('\n\t ') + '\n' # cleanup end of file txt expected = expected_results.splitlines(True) diff = difflib.unified_diff(expected, actual, fromfile='expected', tofile='actual', n=0) # convert diff generator into a list of lines: diff_lines = list() for line in diff: diff_lines.append(line) # test failure if there are any diff_lines if len(diff_lines) > 0: new_filename = '{}{}'.format(MTRRES_PATH[:-10], 'actual.txt') with open(new_filename, 'w') as new_file: new_file.write(res) sys.stdout.write('*************************************************\n') sys.stdout.write('*** NEW RESULTS IN pufcsv_mtr_actual.txt FILE ***\n') sys.stdout.write('*** if new OK, copy pufcsv_mtr_actual.txt to ***\n') sys.stdout.write('*** pufcsv_mtr_expect.txt ***\n') sys.stdout.write('*** and rerun test. ***\n') sys.stdout.write('*************************************************\n') assert False
def test_compatible_data(cps_subsample, puf_subsample, allparams, reform_xx, tc_objs, allparams_batch): """ Test that the compatible_data attribute in current_law_policy.json is accurate by implementing the min and max values of each parameter as reforms and ensuring that revenue differs from baseline when for at least one of these reforms when using datasets marked compatible and does not differ when using datasets marked as incompatible. """ # pylint: disable=too-many-arguments,too-many-locals # pylint: disable=too-many-statements,too-many-branches # Get taxcalc objects from tc_objs fixture rec_xx, c_xx, puftest = tc_objs # These parameters are exempt because they are not active under # current law and activating them would deactivate other parameters. exempt_from_testing = ['_CG_ec', '_CG_reinvest_ec_rt'] # Loop through the parameters in allparams_batch errmsg = 'ERROR: {} not {} for {}\n' errors = '' for pname in allparams_batch: param = allparams_batch[pname] max_listed = param['range']['max'] # handle links to other params or self if isinstance(max_listed, six.string_types): if max_listed == 'default': max_val = param['value'][-1] else: max_val = allparams[max_listed]['value'][0] if not isinstance(max_listed, six.string_types): if isinstance(param['value'][0], list): max_val = [max_listed] * len(param['value'][0]) else: max_val = max_listed min_listed = param['range']['min'] if isinstance(min_listed, six.string_types): if min_listed == 'default': min_val = param['value'][-1] else: min_val = allparams[min_listed]['value'][0] if not isinstance(min_listed, six.string_types): if isinstance(param['value'][0], list): min_val = [min_listed] * len(param['value'][0]) else: min_val = min_listed # create reform dictionaries max_reform = copy.deepcopy(reform_xx) min_reform = copy.deepcopy(reform_xx) max_reform[XX_YEAR][str(pname)] = [max_val] min_reform[XX_YEAR][str(pname)] = [min_val] # assess whether max reform changes results if puftest: rec_yy = Records(data=puf_subsample) else: rec_yy = Records.cps_constructor(data=cps_subsample) p_yy = Policy() p_yy.implement_reform(max_reform) c_yy = Calculator(policy=p_yy, records=rec_yy, verbose=False) c_yy.advance_to_year(TEST_YEAR) c_yy.calc_all() if pname.startswith('_BEN') and pname.endswith('_repeal'): max_reform_change = ( c_yy.weighted_total('benefit_cost_total') - c_xx.weighted_total('benefit_cost_total') ) else: max_reform_change = ( c_yy.weighted_total('combined') - c_xx.weighted_total('combined') ) min_reform_change = 0 # assess whether min reform changes results, if max reform did not if max_reform_change == 0: p_yy = Policy() p_yy.implement_reform(min_reform) c_yy = Calculator(policy=p_yy, records=rec_xx) c_yy.advance_to_year(TEST_YEAR) c_yy.calc_all() if pname.startswith('_BEN') and pname.endswith('_repeal'): min_reform_change = ( c_yy.weighted_total('benefit_cost_total') - c_xx.weighted_total('benefit_cost_total') ) else: min_reform_change = ( c_yy.weighted_total('combined') - c_xx.weighted_total('combined') ) if min_reform_change == 0 and pname not in exempt_from_testing: if puftest: if param['compatible_data']['puf'] is not False: errors += errmsg.format(pname, 'False', 'puf') else: if param['compatible_data']['cps'] is not False: errors += errmsg.format(pname, 'False', 'cps') if max_reform_change != 0 or min_reform_change != 0: if puftest: if param['compatible_data']['puf'] is not True: errors += errmsg.format(pname, 'True', 'puf') else: if param['compatible_data']['cps'] is not True: errors += errmsg.format(pname, 'True', 'cps') # test failure if any errors if errors: print(errors) assert 'compatible_data' == 'invalid'
def test_n65(cps_subsample): recs = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=Policy(), records=recs) assert calc.n65().sum() > 1500
def get_calculator(baseline, calculator_start_year, reform=None, data='cps', gfactors=None, weights=None, records_start_year=RECORDS_START_YEAR): ''' This function creates the tax calculator object for the microsim Args: baseline (bool): `True` if baseline tax policy calculator_start_year (integer): first year of budget window reform (dictionary): IIT reform parameters data (string or Pandas DataFrame): path to file or DataFrame for Tax-Calculator Records object (optional) weights (DataFrame): weights DataFrame for Tax-Calculator Records object (optional) records_start_year (integer): the start year for the data and weights dfs Returns: calc1 (Tax Calculator Calculator object): TC Calculator object with a current_year equal to calculator_start_year ''' # create a calculator policy1 = Policy() if data is not None and "cps" in data: records1 = Records.cps_constructor() # impute short and long term capital gains if using CPS data # in 2012 SOI data 6.587% of CG as short-term gains records1.p22250 = 0.06587 * records1.e01100 records1.p23250 = (1 - 0.06587) * records1.e01100 # set total capital gains to zero records1.e01100 = np.zeros(records1.e01100.shape[0]) elif data is not None: # pragma: no cover records1 = Records(data=data, gfactors=gfactors, weights=weights, start_year=records_start_year) # pragma: no cover else: records1 = Records() # pragma: no cover if baseline: # Should not be a reform if baseline is True assert not reform if not baseline: update_policy(policy1, reform) # the default set up increments year to 2013 calc1 = Calculator(records=records1, policy=policy1) print('Calculator initial year = ', calc1.current_year) # this increment_year function extrapolates all PUF variables to # the next year so this step takes the calculator to the start_year if calculator_start_year > TC_LAST_YEAR: raise RuntimeError("Start year is beyond data extrapolation.") while calc1.current_year < calculator_start_year: calc1.increment_year() return calc1
def test_reform_json_and_output(tests_path): """ Check that each JSON reform file can be converted into a reform dictionary that can then be passed to the Policy class implement_reform() method that generates no reform_errors. Then use each reform to generate static tax results for small set of filing units in a single tax_year and compare those results with expected results from a text file. """ # pylint: disable=too-many-statements,too-many-locals used_dist_stats = ['c00100', # AGI 'c04600', # personal exemptions 'standard', # standard deduction 'c04800', # regular taxable income 'c05800', # income tax before credits 'iitax', # income tax after credits 'payrolltax', # payroll taxes 'aftertax_income'] # aftertax expanded income unused_dist_stats = set(DIST_TABLE_COLUMNS) - set(used_dist_stats) renamed_columns = {'c00100': 'AGI', 'c04600': 'pexempt', 'standard': 'stdded', 'c04800': 'taxinc', 'c05800': 'tax-wo-credits', 'iitax': 'inctax', 'payrolltax': 'paytax', 'aftertax_income': 'ataxinc'} # embedded function used only in test_reform_json_and_output def write_distribution_table(calc, resfilename): """ Write abbreviated distribution table calc to file with resfilename. """ dist, _ = calc.distribution_tables(None, groupby='large_income_bins') for stat in unused_dist_stats: del dist[stat] dist = dist[used_dist_stats] dist.rename(mapper=renamed_columns, axis='columns', inplace=True) pd.options.display.float_format = '{:7.0f}'.format with open(resfilename, 'w') as resfile: dist.to_string(resfile) # embedded function used only in test_reform_json_and_output def res_and_out_are_same(base): """ Return true if base.res and base.out file contents are the same; return false if base.res and base.out file contents differ. """ with open(base + '.out') as outfile: exp_res = outfile.read() exp = exp_res.splitlines(True) with open(base + '.res') as resfile: act_res = resfile.read() act = act_res.splitlines(True) # assure act & exp line lists have differences less than "small" value epsilon = 1e-6 if sys.version_info.major == 2: small = epsilon # tighter test for Python 2.7 else: small = epsilon # looser test for Python 3.6 if necessary diff_lines = list() assert len(act) == len(exp) for actline, expline in zip(act, exp): if actline == expline: continue diffs = nonsmall_diff_line_list(actline, expline, small) if diffs: diff_lines.extend(diffs) if diff_lines: return False return True # specify Records object containing cases data tax_year = 2020 cases_path = os.path.join(tests_path, '..', 'reforms', 'cases.csv') cases = Records(data=cases_path, gfactors=None, # keeps raw data unchanged weights=None, adjust_ratios=None, start_year=tax_year) # set raw input data year # specify list of reform failures failures = list() # specify current-law-policy Calculator object calc1 = Calculator(policy=Policy(), records=cases, verbose=False) calc1.advance_to_year(tax_year) calc1.calc_all() res_path = cases_path.replace('cases.csv', 'clp.res') write_distribution_table(calc1, res_path) if res_and_out_are_same(res_path.replace('.res', '')): os.remove(res_path) else: failures.append(res_path) # check reform file contents and reform results for each reform reforms_path = os.path.join(tests_path, '..', 'reforms', '*.json') json_reform_files = glob.glob(reforms_path) for jrf in json_reform_files: # read contents of jrf (JSON reform file) with open(jrf, 'r') as jfile: jrf_text = jfile.read() # check that jrf_text has "policy" that can be implemented as a reform if '"policy"' in jrf_text: gdiffbase = {} gdiffresp = {} # pylint: disable=protected-access policy_dict = ( Calculator._read_json_policy_reform_text(jrf_text, gdiffbase, gdiffresp) ) pol = Policy() pol.implement_reform(policy_dict) assert not pol.reform_errors calc2 = Calculator(policy=pol, records=cases, verbose=False) calc2.advance_to_year(tax_year) calc2.calc_all() res_path = jrf.replace('.json', '.res') write_distribution_table(calc2, res_path) if res_and_out_are_same(res_path.replace('.res', '')): os.remove(res_path) else: failures.append(res_path) else: # jrf_text has no "policy" key msg = 'ERROR: missing policy key in file: {}' raise ValueError(msg.format(os.path.basename(jrf))) if failures: msg = 'Following reforms have res-vs-out differences:\n' for ref in failures: msg += '{}\n'.format(os.path.basename(ref)) raise ValueError(msg)
def test_make_Calculator_deepcopy(records_2009): parm = Policy() calc1 = Calculator(policy=parm, records=records_2009) calc2 = copy.deepcopy(calc1) assert isinstance(calc2, Calculator)
def test_behavioral_response_calculator(cps_subsample): # create Records object rec = Records.cps_constructor(data=cps_subsample) year = rec.current_year # create Policy object pol = Policy() # create current-law Calculator object calc1 = Calculator(policy=pol, records=rec) # implement policy reform reform = {year: {'_II_rt7': [0.496], '_PT_rt7': [0.496]}} pol.implement_reform(reform) # create reform Calculator object with no behavioral response behv = Behavior() calc2 = Calculator(policy=pol, records=rec, behavior=behv) # test incorrect use of Behavior._mtr_xy method with pytest.raises(ValueError): Behavior._mtr_xy(calc1, calc2, mtr_of='e00200p', tax_type='nonsense') # vary substitution and income effects in Behavior object behavior0 = {year: {'_BE_sub': [0.0], '_BE_cg': [0.0], '_BE_charity': [[0.0, 0.0, 0.0]]}} behv0 = Behavior() behv0.update_behavior(behavior0) calc2 = Calculator(policy=pol, records=rec, behavior=behv0) assert calc2.behavior.has_response() is False calc2_behv0 = Behavior.response(calc1, calc2) behavior1 = {year: {'_BE_sub': [0.3], '_BE_inc': [-0.1], '_BE_cg': [0.0], '_BE_subinc_wrt_earnings': [True]}} behv1 = Behavior() behv1.update_behavior(behavior1) calc2 = Calculator(policy=pol, records=rec, behavior=behv1) assert calc2.behavior.has_response() is True epsilon = 1e-9 assert abs(calc2.behavior.BE_sub - 0.3) < epsilon assert abs(calc2.behavior.BE_inc - -0.1) < epsilon assert abs(calc2.behavior.BE_cg - 0.0) < epsilon calc2_behv1 = Behavior.response(calc1, calc2) behavior2 = {year: {'_BE_sub': [0.5], '_BE_cg': [-0.8]}} behv2 = Behavior() behv2.update_behavior(behavior2) calc2 = Calculator(policy=pol, records=rec, behavior=behv2) assert calc2.behavior.has_response() is True calc2_behv2 = Behavior.response(calc1, calc2, trace=True) behavior3 = {year: {'_BE_inc': [-0.2], '_BE_cg': [-0.8]}} behv3 = Behavior() behv3.update_behavior(behavior3) calc2 = Calculator(policy=pol, records=rec, behavior=behv3) assert calc2.behavior.has_response() is True calc2_behv3 = Behavior.response(calc1, calc2) behavior4 = {year: {'_BE_cg': [-0.8]}} behv4 = Behavior() behv4.update_behavior(behavior4) calc2 = Calculator(policy=pol, records=rec, behavior=behv4) assert calc2.behavior.has_response() is True calc2_behv4 = Behavior.response(calc1, calc2) behavior5 = {year: {'_BE_charity': [[-0.5, -0.5, -0.5]]}} behv5 = Behavior() behv5.update_behavior(behavior5) calc2 = Calculator(policy=pol, records=rec, behavior=behv5) assert calc2.behavior.has_response() is True calc2_behv5 = Behavior.response(calc1, calc2) # check that total income tax liability differs across the # six sets of behavioral-response elasticities assert (calc2_behv0.records.iitax.sum() != calc2_behv1.records.iitax.sum() != calc2_behv2.records.iitax.sum() != calc2_behv3.records.iitax.sum() != calc2_behv4.records.iitax.sum() != calc2_behv5.records.iitax.sum())
def test_Calculator_create_diagnostic_table(records_2009): calc = Calculator(policy=Policy(), records=records_2009) calc.calc_all() adt = create_diagnostic_table(calc) assert isinstance(adt, pd.DataFrame)
def test_create_distribution_tables(pit_fullsample, gst_sample, cit_crosssample): # pylint: disable=too-many-statements,too-many-branches # create a current-law Policy object and Calculator object calc1 rec = Records(data=pit_fullsample) grec = GSTRecords(data=gst_sample) crec = CorpRecords(data=cit_crosssample) pol = Policy() calc1 = Calculator(policy=pol, records=rec, gstrecords=grec, corprecords=crec) calc1.calc_all() # create a policy-reform Policy object and Calculator object calc2 reform = {2017: {'_rate2': [0.06]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec, gstrecords=grec, corprecords=crec) calc2.calc_all() test_failure = False # test creating various distribution tables dist, _ = calc2.distribution_tables(None, 'weighted_deciles') assert isinstance(dist, pd.DataFrame) tabcol = 'pitax' expected = [ 0.000, 0.000, 0.000, 0.000, 0.000, 1.962, 5.711, 14.602, 45.503, 163.177, 397.795, 1018.520, 1647.270, 331.218, 384.399, 302.903 ] if not np.allclose(dist[tabcol].values, expected): test_failure = True print('dist xdec', tabcol) for val in dist[tabcol].values: print('{:.3f},'.format(val)) tabcol = 'GTI' expected = [ 0.000, 0.000, 688.359, 893.687, 1107.005, 1332.670, 1605.580, 1824.545, 2327.660, 2818.092, 3848.954, 6071.569, 22518.121, 2490.655, 2119.235, 1461.678 ] if not np.allclose(dist[tabcol].tolist(), expected): test_failure = True print('dist xdec', tabcol) for val in dist[tabcol].values: print('{:.3f},'.format(val)) dist, _ = calc2.distribution_tables(None, 'standard_income_bins') assert isinstance(dist, pd.DataFrame) tabcol = 'pitax' expected = [ 0.000, 0.000, 8.334, 279.113, 542.762, 401.310, 415.751, 0.000, 0.000, 0.000, 0.000, 1647.270 ] if not np.allclose(dist[tabcol], expected): test_failure = True print('dist xbin', tabcol) for val in dist[tabcol].values: print('{:.3f},'.format(val)) tabcol = 'GTI' expected = [ 0.000, 0.000, 5884.790, 7399.792, 4810.526, 2392.643, 2030.370, 0.000, 0.000, 0.000, 0.000, 22518.121 ] if not np.allclose(dist[tabcol].tolist(), expected): test_failure = True print('dist xdec', tabcol) for val in dist[tabcol].values: print('{:.3f},'.format(val)) """
def test_diff_table_sum_row(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) # create a current-law Policy object and Calculator calc1 pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.calc_all() # create a policy-reform Policy object and Calculator calc2 reform = {2013: {'_II_rt4': [0.56]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.calc_all() # create two difference tables and compare their content tdiff1 = create_difference_table(calc1.dataframe(DIFF_VARIABLES), calc2.dataframe(DIFF_VARIABLES), 'standard_income_bins', 'iitax') tdiff2 = create_difference_table(calc1.dataframe(DIFF_VARIABLES), calc2.dataframe(DIFF_VARIABLES), 'soi_agi_bins', 'iitax') non_digit_cols = ['perc_inc', 'perc_cut'] digit_cols = [c for c in list(tdiff1) if c not in non_digit_cols] assert np.allclose(tdiff1[digit_cols][-1:], tdiff2[digit_cols][-1:]) np.testing.assert_array_equal(tdiff1[non_digit_cols][-1:], tdiff2[non_digit_cols][-1:])