Source code for ogcore.output_tables

import numpy as np
import pandas as pd
import os
from ogcore.constants import VAR_LABELS, DEFAULT_START_YEAR
from ogcore import tax
from ogcore.utils import save_return_table, Inequality
from ogcore.utils import pct_change_unstationarized

cur_path = os.path.split(os.path.abspath(__file__))[0]


[docs] def macro_table( base_tpi, base_params, reform_tpi=None, reform_params=None, var_list=["Y", "C", "K", "L", "r", "w"], output_type="pct_diff", stationarized=True, num_years=10, include_SS=True, include_overall=True, start_year=DEFAULT_START_YEAR, table_format=None, path=None, ): """ Create a table of macro aggregates. Args: base_tpi (dictionary): TPI output from baseline run base_params (OG-Core Specifications class): baseline parameters object reform_tpi (dictionary): TPI output from reform run reform_params (OG-Core Specifications class): reform parameters object var_list (list): names of variable to use in table output_type (string): type of plot, can be: 'pct_diff': plots percentage difference between baselien and reform ((reform-base)/base) 'diff': plots difference between baseline and reform (reform-base) 'levels': variables in model units stationarized (bool): whether used stationarized variables (False only affects pct_diff right now) num_years (integer): number of years to include in table include_SS (bool): whether to include the steady-state results in the table include_overall (bool): whether to include results over the entire budget window as a column in the table start_year (integer): year to start table table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk """ assert isinstance(start_year, (int, np.integer)) assert isinstance(num_years, (int, np.integer)) # Make sure both runs cover same time period if reform_tpi is not None: assert base_params.start_year == reform_params.start_year year_vec = np.arange(start_year, start_year + num_years) start_index = start_year - base_params.start_year # Check that reform included if doing pct_diff or diff plot if output_type == "pct_diff" or output_type == "diff": assert reform_tpi is not None year_list = year_vec.tolist() if include_overall: year_list.append(str(year_vec[0]) + "-" + str(year_vec[-1])) if include_SS: year_list.append("SS") table_dict = {"Year": year_list} for i, v in enumerate(var_list): if output_type == "pct_diff": # multiple by 100 so in percentage points if stationarized: results = ((reform_tpi[v] - base_tpi[v]) / base_tpi[v]) * 100 else: pct_changes = pct_change_unstationarized( base_tpi, base_params, reform_tpi, reform_params, output_vars=[v], ) results = pct_changes[v] * 100 results_years = results[start_index : start_index + num_years] results_overall = ( ( reform_tpi[v][start_index : start_index + num_years].sum() - base_tpi[v][start_index : start_index + num_years].sum() ) / base_tpi[v][start_index : start_index + num_years].sum() ) * 100 results_SS = results[-1] results_for_table = results_years if include_overall: results_for_table = np.append( results_for_table, results_overall ) if include_SS: results_for_table = np.append(results_for_table, results_SS) table_dict[VAR_LABELS[v]] = results_for_table elif output_type == "diff": results = reform_tpi[v] - base_tpi[v] results_years = results[start_index : start_index + num_years] results_overall = ( reform_tpi[v][start_index : start_index + num_years].sum() - base_tpi[v][start_index : start_index + num_years].sum() ) results_SS = results[-1] results_for_table = results_years if include_overall: results_for_table = np.append( results_for_table, results_overall ) if include_SS: results_for_table = np.append(results_for_table, results_SS) table_dict[VAR_LABELS[v]] = results_for_table else: results_years = base_tpi[v][start_index : start_index + num_years] results_overall = results_years.sum() results_SS = base_tpi[v][-1] results_for_table = results_years if include_overall: results_for_table = np.append( results_for_table, results_overall ) if include_SS: results_for_table = np.append(results_for_table, results_SS) table_dict[VAR_LABELS[v] + " Baseline"] = results_for_table if reform_tpi is not None: results_years = reform_tpi[v][ start_index : start_index + num_years ] results_overall = results_years.sum() results_SS = reform_tpi[v][-1] results_for_table = results_years if include_overall: results_for_table = np.append( results_for_table, results_overall ) if include_SS: results_for_table = np.append( results_for_table, results_SS ) table_dict[VAR_LABELS[v] + " Reform"] = results_for_table # Make df with dict so can use pandas functions table_df = ( pd.DataFrame.from_dict(table_dict, orient="columns") .set_index("Year") .transpose() ) table_df.reset_index(inplace=True) table_df.rename(columns={"index": "Variable"}, inplace=True) table = save_return_table(table_df, table_format, path) return table
[docs] def macro_table_SS( base_ss, reform_ss, var_list=["Yss", "Css", "Kss", "Lss", "rss", "wss"], table_format=None, path=None, ): """ Create a table of macro aggregates from the steady-state solutions. Args: base_ss (dictionary): SS output from baseline run reform_ss (dictionary): SS output from reform run var_list (list): names of variable to use in table table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk """ table_dict = { "Variable": [], "Baseline": [], "Reform": [], "% Change (or pp diff)": [], } for i, v in enumerate(var_list): table_dict["Variable"].append(VAR_LABELS[v]) table_dict["Baseline"].append(base_ss[v]) table_dict["Reform"].append(reform_ss[v]) if v != "D/Y": diff = ((reform_ss[v] - base_ss[v]) / base_ss[v]) * 100 else: diff = ( reform_ss["Dss"] / reform_ss["Yss"] - base_ss["Dss"] / base_ss["Yss"] ) table_dict["% Change (or pp diff)"].append(diff) # Make df with dict so can use pandas functions table_df = pd.DataFrame.from_dict( table_dict, orient="columns" ).set_index("Variable") table = save_return_table(table_df, table_format, path, precision=3) return table
[docs] def ineq_table( base_ss, base_params, reform_ss=None, reform_params=None, var_list=["cssmat"], table_format=None, path=None, ): """ Creates table with various inequality measures in the model steady-state. Args: base_ss (dictionary): SS output from baseline run base_params (OG-Core Specifications class): baseline parameters object reform_ss (dictionary): SS output from reform run reform_params (OG-Core Specifications class): reform parameters object var_list (list): names of variable to use in table table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk """ table_dict = { "Steady-State Variable": [], "Inequality Measure": [], "Baseline": [], } if reform_ss: table_dict["Reform"] = [] table_dict["% Change"] = [] for i, v in enumerate(var_list): base_ineq = Inequality( base_ss[v], base_params.omega_SS, base_params.lambdas, base_params.S, base_params.J, ) if reform_ss: reform_ineq = Inequality( reform_ss[v], reform_params.omega_SS, reform_params.lambdas, reform_params.S, reform_params.J, ) table_dict["Steady-State Variable"].extend( [VAR_LABELS[v], "", "", "", ""] ) table_dict["Inequality Measure"].extend( [ "Gini Coefficient", "Var of Logs", "90/10 Ratio", "Top 10% Share", "Top 1% Share", ] ) base_values = np.array( [ base_ineq.gini(), base_ineq.var_of_logs(), base_ineq.ratio_pct1_pct2(0.90, 0.10), base_ineq.top_share(0.1), base_ineq.top_share(0.01), ] ) table_dict["Baseline"].extend(list(base_values)) if reform_ss: reform_values = np.array( [ reform_ineq.gini(), reform_ineq.var_of_logs(), reform_ineq.ratio_pct1_pct2(0.90, 0.10), reform_ineq.top_share(0.1), reform_ineq.top_share(0.01), ] ) table_dict["Reform"].extend(list(reform_values)) table_dict["% Change"].extend( list(((reform_values - base_values) / base_values) * 100) ) # Make df with dict so can use pandas functions table_df = pd.DataFrame.from_dict(table_dict) table = save_return_table(table_df, table_format, path, precision=3) return table
[docs] def gini_table( base_ss, base_params, reform_ss=None, reform_params=None, var_list=["cssmat"], table_format=None, path=None, ): """ Creates table with measures of the Gini coefficient: overall, across lifetime earnings group, and across age. Args: base_ss (dictionary): SS output from baseline run base_params (OG-Core Specifications class): baseline parameters object reform_ss (dictionary): SS output from reform run reform_params (OG-Core Specifications class): reform parameters object var_list (list): names of variable to use in table table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk """ table_dict = {"Steady-State Variable": [], "Gini Type": [], "Baseline": []} if reform_ss: table_dict["Reform"] = [] table_dict["% Change"] = [] for i, v in enumerate(var_list): base_ineq = Inequality( base_ss[v], base_params.omega_SS, base_params.lambdas, base_params.S, base_params.J, ) if reform_ss: reform_ineq = Inequality( reform_ss[v], reform_params.omega_SS, reform_params.lambdas, reform_params.S, reform_params.J, ) table_dict["Steady-State Variable"].extend([VAR_LABELS[v], "", ""]) table_dict["Gini Type"].extend( ["Overall", "Lifetime Income Group, $j$", "Age , $s$"] ) base_values = np.array( [ base_ineq.gini(), base_ineq.gini(type="ability"), base_ineq.gini(type="age"), ] ) table_dict["Baseline"].extend(list(base_values)) if reform_ss: reform_values = np.array( [ reform_ineq.gini(), reform_ineq.gini(type="ability"), reform_ineq.gini(type="age"), ] ) table_dict["Reform"].extend(list(reform_values)) table_dict["% Change"].extend( list(((reform_values - base_values) / base_values) * 100) ) # Make df with dict so can use pandas functions table_df = pd.DataFrame.from_dict(table_dict) table = save_return_table(table_df, table_format, path, precision=3) return table
[docs] def wealth_moments_table( base_ss, base_params, data_moments=None, table_format=None, path=None ): """ Creates table with moments of the wealth distribution from the model and SCF data. Args: base_ss (dictionary): SS output from baseline run base_params (OG-Core Specifications class): baseline parameters object table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk """ table_dict = { "Moment": [ "Share 0-25%", "Share 25-50%", "Share 50-70%", "Share 70-80%", "Share 80-90%", "Share 90-99%", "Share 99-100%", "Gini Coefficient", "var(ln(Wealth))", ], "Data": [], "Model": [], } base_ineq = Inequality( base_ss["bssmat_splus1"], base_params.omega_SS, base_params.lambdas, base_params.S, base_params.J, ) base_values = [ 1 - base_ineq.top_share(0.75), base_ineq.top_share(0.75) - base_ineq.top_share(0.5), base_ineq.top_share(0.5) - base_ineq.top_share(0.3), base_ineq.top_share(0.3) - base_ineq.top_share(0.2), base_ineq.top_share(0.2) - base_ineq.top_share(0.1), base_ineq.top_share(0.1) - base_ineq.top_share(0.01), base_ineq.top_share(0.01), base_ineq.gini(), base_ineq.var_of_logs(), ] table_dict["Model"].extend(base_values) # Add moments from the data if data_moments is not None: table_dict["Data"] = data_moments # Make df with dict so can use pandas functions table_df = pd.DataFrame.from_dict(table_dict) table = save_return_table(table_df, table_format, path, precision=3) return table
[docs] def tp_output_dump_table( base_params, base_tpi, reform_params=None, reform_tpi=None, table_format=None, path=None, ): """ This function dumps many of the macro time series from the transition path into an output table. Args: base_params (OG-Core Specifications class): baseline parameters object base_tpi (dictionary): TP output from baseline run reform_params (OG-Core Specifications class): reform parameters object reform_tpi (dictionary): TP output from reform run table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk """ T = base_params.T # keep just items of interest for final table vars_to_keep = [ "Y", "L", "G", "TR", "B", "K", "K_d", "K_f", "D", "D_d", "D_f", "r", "r_gov", "r_p", "w", "total_tax_revenue", "business_tax_revenue", ] base_dict = {k: base_tpi[k] for k in vars_to_keep} # update key names base_dict_final = dict( (VAR_LABELS[k] + ": Baseline", v[:T]) for (k, v) in base_dict.items() ) # create df table_df = pd.DataFrame.from_dict(base_dict_final) if reform_tpi is not None: assert base_params.start_year == reform_params.start_year assert base_params.T == reform_params.T reform_dict = {k: reform_tpi[k] for k in vars_to_keep} # update key names reform_dict_final = dict( (VAR_LABELS[k] + ": Reform", v[:T]) for (k, v) in reform_dict.items() ) df_reform = pd.DataFrame.from_dict(reform_dict_final) # merge dfs table_df = table_df.merge(df_reform, left_index=True, right_index=True) # rename index to year table_df.reset_index(inplace=True) table_df.rename(columns={"index": "Year"}, inplace=True) # update index to reflect years table_df["Year"] = table_df["Year"] + base_params.start_year table = save_return_table(table_df, table_format, path) return table
[docs] def dynamic_revenue_decomposition( base_params, base_tpi, base_ss, reform_params, reform_tpi, reform_ss, num_years=10, include_SS=True, include_overall=True, include_business_tax=True, full_break_out=False, start_year=DEFAULT_START_YEAR, table_format=None, path=None, ): """ This function decomposes the source of changes in tax revenues to determine the percentage change in tax revenues that can be attributed to macroeconomic feedback effects. Args: base_params (OG-Core Specifications class): baseline parameters object base_tpi (dictionary): TP output from baseline run base_ss (dictionary): SS output from baseline run reform_params (OG-Core Specifications class): reform parameters object reform_tpi (dictionary): TP output from reform run reform_ss (dictionary): SS output from reform run num_years (integer): number of years to include in table include_SS (bool): whether to include the steady-state results in the table include_overall (bool): whether to include results over the entire budget window as a column in the table include_business_tax (bool): whether to include business tax revenue changes in result full_break_out (bool): whether to break out behavioral and macro effects start_year (integer): year to start table table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk .. note:: The decomposition is the following: 1. Simulate the baseline and reform in OG-Core. Save the resulting series of tax revenues. Call these series for the baseline and reform A and D, respectively. 2. Create a third revenue series that is computed using the baseline behavior (i.e., `bmat_s` and `n_mat`) and macro variables (`tr`, `bq`, `r`, `w`), but with the tax function parameter estimates from the reform policy. Call this series B. 3. Create a fourth revenue series that is computed using the reform behavior (i.e., `bmat_s` and `n_mat`) and tax functions estimated on the reform tax policy, but the macro variables (`tr`, `bq`, `r`, `w`) from the baseline. Call this series C. 3. Calculate the percentage difference between B and A -- call this the "static" change from the macro model. Calculate the percentage difference between C and B -- call this the behavioral effects. Calculate the percentage difference between D and C -- call this the macroeconomic effect. The full dynamic effect is difference between C and A. One can apply the percentage difference from the macro feedback effect to ("static") revenue estimates from the policy change to produce an estimate of the revenue including macro feedback. """ assert isinstance(start_year, (int, np.integer)) assert isinstance(num_years, (int, np.integer)) # Make sure both runs cover same time period assert base_params.start_year == reform_params.start_year year_vec = np.arange(start_year, start_year + num_years) start_index = start_year - base_params.start_year year_list = year_vec.tolist() if include_overall: year_list.append(str(year_vec[0]) + "-" + str(year_vec[-1])) if include_SS: year_list.append("SS") table_dict = {"Year": year_list} T, S, J = base_params.T, base_params.S, base_params.J num_params = len(base_params.etr_params[0][0]) base_etr_params_4D = [ [ [ [base_params.etr_params[t][s][i] for i in range(num_params)] for j in range(J) ] for s in range(S) ] for t in range(T) ] reform_etr_params_4D = [ [ [ [reform_params.etr_params[t][s][i] for i in range(num_params)] for j in range(J) ] for s in range(S) ] for t in range(T) ] tax_rev_dict = {"indiv": {}, "biz": {}, "total": {}} indiv_liab = {} # Baseline IIT + payroll tax liability indiv_liab["A"] = tax.income_tax_liab( base_tpi["r_p"][:T], base_tpi["w"][:T], base_tpi["bmat_s"], base_tpi["n_mat"][:T, :, :], base_ss["factor_ss"], 0, None, "TPI", base_params.e, base_etr_params_4D, base_params, ) # IIT + payroll tax liability using baseline behavior and macros # with the reform tax functions (this is the OG-Core static estimate) indiv_liab["B"] = tax.income_tax_liab( base_tpi["r_p"][:T], base_tpi["w"][:T], base_tpi["bmat_s"], base_tpi["n_mat"][:T, :, :], base_ss["factor_ss"], 0, None, "TPI", base_params.e, reform_etr_params_4D, base_params, ) # IIT + payroll tax liability using reform behavior and baseline # macros indiv_liab["C"] = tax.income_tax_liab( base_tpi["r_p"][:T], base_tpi["w"][:T], reform_tpi["bmat_s"], reform_tpi["n_mat"][:T, :, :], base_ss["factor_ss"], 0, None, "TPI", reform_params.e, reform_etr_params_4D, reform_params, ) # IIT + payroll tax liability from the reform simulation indiv_liab["D"] = tax.income_tax_liab( reform_tpi["r_p"][:T], reform_tpi["w"][:T], reform_tpi["bmat_s"], reform_tpi["n_mat"][:T, :, :], base_ss["factor_ss"], 0, None, "TPI", reform_params.e, reform_etr_params_4D, reform_params, ) # Business tax revenue from the baseline simulation tax_rev_dict["biz"]["A"] = tax.get_biz_tax( base_tpi["w"][:T], base_tpi["Y_vec"][:T, :], base_tpi["L_vec"][:T, :], base_tpi["K_vec"][:T, :], base_tpi["p_m"][:T], base_params, None, "TPI", ).sum(axis=-1) # Business tax revenue found using baseline behavior and macros with # the reform tax rates tax_rev_dict["biz"]["B"] = tax.get_biz_tax( base_tpi["w"][:T], base_tpi["Y_vec"][:T, :], base_tpi["L_vec"][:T, :], base_tpi["K_vec"][:T, :], base_tpi["p_m"][:T], reform_params, None, "TPI", ).sum(axis=-1) # Business tax revenue found using the reform behavior and baseline # macros with the reform tax rates tax_rev_dict["biz"]["C"] = tax.get_biz_tax( base_tpi["w"][:T], reform_tpi["Y_vec"][:T, :], reform_tpi["L_vec"][:T, :], reform_tpi["K_vec"][:T, :], reform_tpi["p_m"][:T], reform_params, None, "TPI", ).sum(axis=-1) # Business tax revenue from the reform tax_rev_dict["biz"]["D"] = tax.get_biz_tax( reform_tpi["w"][:T], reform_tpi["Y_vec"][:T, :], reform_tpi["L_vec"][:T, :], reform_tpi["K_vec"][:T, :], reform_tpi["p_m"][:T], reform_params, None, "TPI", ).sum(axis=-1) pop_weights = np.squeeze(base_params.lambdas) * np.tile( np.reshape(base_params.omega[:T, :], (T, S, 1)), (1, 1, J) ) for k in indiv_liab.keys(): tax_rev_dict["indiv"][k] = (indiv_liab[k] * pop_weights).sum(1).sum(1) tax_rev_dict["total"][k] = ( tax_rev_dict["indiv"][k] + tax_rev_dict["biz"][k] ) results_for_table = {"indiv": {}, "biz": {}, "total": {}} for type in ["indiv", "biz", "total"]: # Rate change effect pct_change1 = ( (tax_rev_dict[type]["B"] - tax_rev_dict[type]["A"]) / tax_rev_dict[type]["A"] ) * 100 # Behavior effect pct_change2 = ( (tax_rev_dict[type]["C"] - tax_rev_dict[type]["B"]) / tax_rev_dict[type]["A"] ) * 100 # Macro effect pct_change3 = ( (tax_rev_dict[type]["D"] - tax_rev_dict[type]["C"]) / tax_rev_dict[type]["A"] ) * 100 # Dynamic effect (behavior + macro) pct_change4 = ( (tax_rev_dict[type]["D"] - tax_rev_dict[type]["B"]) / tax_rev_dict[type]["A"] ) * 100 # Total change in tax revenue (rates + behavior + macro) pct_change5 = ( (tax_rev_dict[type]["D"] - tax_rev_dict[type]["A"]) / tax_rev_dict[type]["A"] ) * 100 pct_change_overall1 = ( ( tax_rev_dict[type]["B"][ start_index : start_index + num_years ].sum() - tax_rev_dict[type]["A"][ start_index : start_index + num_years ].sum() ) / tax_rev_dict[type]["A"][ start_index : start_index + num_years ].sum() ) * 100 pct_change_overall2 = ( ( tax_rev_dict[type]["C"][ start_index : start_index + num_years ].sum() - tax_rev_dict[type]["B"][ start_index : start_index + num_years ].sum() ) / tax_rev_dict[type]["A"][ start_index : start_index + num_years ].sum() ) * 100 pct_change_overall3 = ( ( tax_rev_dict[type]["D"][ start_index : start_index + num_years ].sum() - tax_rev_dict[type]["C"][ start_index : start_index + num_years ].sum() ) / tax_rev_dict[type]["A"][ start_index : start_index + num_years ].sum() ) * 100 pct_change_overall4 = ( ( tax_rev_dict[type]["D"][ start_index : start_index + num_years ].sum() - tax_rev_dict[type]["B"][ start_index : start_index + num_years ].sum() ) / tax_rev_dict[type]["A"][ start_index : start_index + num_years ].sum() ) * 100 pct_change_overall5 = ( ( tax_rev_dict[type]["D"][ start_index : start_index + num_years ].sum() - tax_rev_dict[type]["A"][ start_index : start_index + num_years ].sum() ) / tax_rev_dict[type]["A"][ start_index : start_index + num_years ].sum() ) * 100 if include_overall: results_for_table[type][1] = np.append( pct_change1[start_index : start_index + num_years], pct_change_overall1, ) results_for_table[type][2] = np.append( pct_change2[start_index : start_index + num_years], pct_change_overall2, ) results_for_table[type][3] = np.append( pct_change3[start_index : start_index + num_years], pct_change_overall3, ) results_for_table[type][4] = np.append( pct_change4[start_index : start_index + num_years], pct_change_overall4, ) results_for_table[type][5] = np.append( pct_change5[start_index : start_index + num_years], pct_change_overall5, ) if include_SS: results_for_table[type][1] = np.append( results_for_table[type][1], pct_change1[-1] ) results_for_table[type][2] = np.append( results_for_table[type][2], pct_change2[-1] ) results_for_table[type][3] = np.append( results_for_table[type][3], pct_change3[-1] ) results_for_table[type][4] = np.append( results_for_table[type][4], pct_change4[-1] ) results_for_table[type][5] = np.append( results_for_table[type][5], pct_change5[-1] ) if full_break_out: if include_business_tax: table_dict = { "Year": year_list, # IIT and Payroll Taxes "IIT: Pct Change due to tax rates": results_for_table["indiv"][ 1 ], "IIT: Pct Change due to behavior": results_for_table["indiv"][ 2 ], "IIT: Pct Change due to macro": results_for_table["indiv"][3], "IIT: Overall Pct Change in taxes": results_for_table["indiv"][ 5 ], # Business Taxes "CIT: Pct Change due to tax rates": results_for_table["biz"][ 1 ], "CIT: Pct Change due to behavior": results_for_table["biz"][2], "CIT: Pct Change due to macro": results_for_table["biz"][3], "CIT: Overall Pct Change in taxes": results_for_table["biz"][ 5 ], # All Taxes "All: Pct Change due to tax rates": results_for_table["total"][ 1 ], "All: Pct Change due to behavior": results_for_table["total"][ 2 ], "All: Pct Change due to macro": results_for_table["total"][3], "All: Overall Pct Change in taxes": results_for_table["total"][ 5 ], } else: table_dict = { "Year": year_list, "Pct Change due to tax rates": results_for_table["indiv"][1], "Pct Change due to behavior": results_for_table["indiv"][2], "Pct Change due to macro": results_for_table["indiv"][3], "Overall Pct Change in taxes": results_for_table["indiv"][5], } else: if include_business_tax: table_dict = { "Year": year_list, # 'IIT and Payroll Taxes:': # np.ones(results_for_table['indiv'][1].shape[0]) * np.nan, "IIT: Pct Change due to tax rates": results_for_table["indiv"][ 1 ], "IIT: Pct Change due to dynamics": results_for_table["indiv"][ 4 ], "IIT: Overall Pct Change in taxes": results_for_table["indiv"][ 5 ], # 'Business Taxes:': # np.ones(results_for_table['biz'][1].shape[0]) * np.nan, "CIT: Pct Change due to tax rates": results_for_table["biz"][ 1 ], "CIT: Pct Change due to dynamics": results_for_table["biz"][4], "CIT: Overall Pct Change in taxes": results_for_table["biz"][ 5 ], # 'All Taxes:': # np.ones(results_for_table['total'][1].shape[0]) * np.nan, "All: Pct Change due to tax rates": results_for_table["total"][ 1 ], "All: Pct Change due to dynamics": results_for_table["total"][ 4 ], "All: Overall Pct Change in taxes": results_for_table["total"][ 5 ], } else: table_dict = { "Year": year_list, "Pct Change due to tax rates": results_for_table["indiv"][1], "Pct Change due to dynamics": results_for_table["indiv"][4], "Overall Pct Change in taxes": results_for_table["indiv"][5], } # Make df with dict so can use pandas functions table_df = ( pd.DataFrame.from_dict(table_dict, orient="columns") .set_index("Year") .transpose() ) table_df.reset_index(inplace=True) table_df.rename(columns={"index": "Variable"}, inplace=True) table = save_return_table(table_df, table_format, path) return table