From 4054ebf3ebfc3fa855fba469fa6a6fd39c2b744f Mon Sep 17 00:00:00 2001 From: martinholmer Date: Sun, 4 Mar 2018 07:38:40 -0500 Subject: [PATCH] Revise Calculator.decile_graph and associated utility functions --- taxcalc/calculate.py | 18 ++++++++++++++---- taxcalc/tests/test_utils.py | 8 ++++---- taxcalc/utils.py | 14 ++++++++++++-- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/taxcalc/calculate.py b/taxcalc/calculate.py index c1bc9db9c..14f34ee48 100644 --- a/taxcalc/calculate.py +++ b/taxcalc/calculate.py @@ -990,7 +990,7 @@ def pch_graph(self, calc): title='') return fig - def decile_graph(self, calc): + def decile_graph(self, calc, hide_negative_incomes=True): """ Create graph that shows percentage change in aftertax expanded income (from going from policy in self to policy in calc) for @@ -1000,8 +1000,6 @@ def decile_graph(self, calc): immediately in an interactive or notebook session (following the instructions in the documentation of the xtr_graph_plot utility function). - Note that the bottom decile result omits filing units with - negative or zero baseline (self) expanded income. Parameters ---------- @@ -1010,6 +1008,17 @@ def decile_graph(self, calc): where both self and calc have calculated taxes for this year before being used by this method + hide_negative_incomes : boolean + if True (which is the default), the bottom table bin containing + filing units with non-positive expanded_income is not shown in + the graph and the table bin containing filing units with positive + expanded_income in the bottom decile is shown with its bar width + adjusted to the number of weighted filing units in bottom decile + who have positive expanded_income; if False, the bottom table bin + containing filing units with non-positive expanded_income is shown, + which may be misleading because the percentage change is correctly + calculated with a negative divisor. + Returns ------- graph that is a bokeh.plotting figure object @@ -1023,7 +1032,8 @@ def decile_graph(self, calc): income_measure='expanded_income', tax_to_diff='combined') # construct data for graph - data = dec_graph_data(diff_table, year=self.current_year) + data = dec_graph_data(diff_table, year=self.current_year, + hide_negative_incomes=hide_negative_incomes) # construct figure from data fig = dec_graph_plot(data, width=850, diff --git a/taxcalc/tests/test_utils.py b/taxcalc/tests/test_utils.py index 93268558c..e362847e7 100644 --- a/taxcalc/tests/test_utils.py +++ b/taxcalc/tests/test_utils.py @@ -988,10 +988,10 @@ def test_dec_qin_graph_plots(cps_subsample): assert calc1.current_year == calc2.current_year calc1.calc_all() calc2.calc_all() - fig_dec = calc1.decile_graph(calc2) - assert fig_dec - fig_qin = calc1.quintile_graph(calc2) - assert fig_qin + fig_dec_hide = calc1.decile_graph(calc2) + assert fig_dec_hide + fig_dec_show = calc1.decile_graph(calc2, hide_negative_incomes=False) + assert fig_dec_show def test_nonsmall_diffs(): diff --git a/taxcalc/utils.py b/taxcalc/utils.py index 638859953..4ba7ea2db 100644 --- a/taxcalc/utils.py +++ b/taxcalc/utils.py @@ -1445,7 +1445,7 @@ def bootstrap_se_ci(data, seed, num_samples, statistic, alpha): return bsest -def dec_graph_data(diff_table, year): +def dec_graph_data(diff_table, year, hide_negative_incomes=True): """ Prepare data needed by dec_graph_plot utility function. @@ -1464,7 +1464,14 @@ def dec_graph_data(diff_table, year): # construct dictionary containing the bar data required by dec_graph_plot bars = dict() nbins = len(DECILE_ROW_NAMES) - for idx in range(0, nbins): + if hide_negative_incomes: + first_bin = 1 + bottom_size = (diff_table['count'][1] / + (diff_table['count'][0] + diff_table['count'][1])) + else: + first_bin = 0 + bottom_size = 1.0 + for idx in range(first_bin, nbins): info = dict() info['label'] = DECILE_ROW_NAMES[idx] info['value'] = diff_table['pc_aftertaxinc'][idx] @@ -1475,6 +1482,7 @@ def dec_graph_data(diff_table, year): # construct dictionary containing bar data and auto-generated labels data = dict() data['bars'] = bars + data['bottom_bar_size'] = bottom_size xlabel = 'Reform-Induced Percentage Change in After-Tax Expanded Income' data['xlabel'] = xlabel ylabel = 'Expanded Income Percentile Group' @@ -1576,6 +1584,8 @@ def dec_graph_plot(data, bval = data['bars'][idx]['value'] blabel = data['bars'][idx]['label'] bheight = barheight + if yidx == 0: + bheight *= data['bottom_bar_size'] if blabel == '90-95': bheight *= 0.5 bcolor = 'red'