Simulations

Poverty has a lasting impact on children. Growing up in poverty increases stress and incarceration rates and decreases educational and health outcomes. These negative consequences not only impact the nation’s poor, but the entire economy as well–child poverty shrinks GDP by more than $1 trillion annually.

Research has shown that giving money to families with children, as most developed countries do, can reduce each of these issues. Programs that provide cash to families with children are called a child allowance, and are typically paid out on a monthly basis.

Here you can explore the impact of a potential child allowance of various amounts in each state. We show impacts across three funding mechanisms:

  • Federal tax as a flat rate on taxable income. For each child allowance amount the total cost is calculated by multiplying the annual child allowance by the total number of children. To calculate the revenue neutral tax rate, the total cost is divided by the nation’s total taxable income. For example, a child allowance of $100 per month would cost about $88 billion annually and require a new flat tax of 1.1 percent.

  • State tax as a flat rate on taxable income. The state tax is calculated in the same manner as the federal tax, but at the state level. This shows how states can fund their own child allowances. Because states vary in child population and income, different states have different tax rates. A $100 monthly child allowance in DC is offset by a 0.5 percent tax on taxable income while the same amount requires a 1.3 percent tax in Alabama.

  • No funding does not impose any new taxes.

These static analyses (they do not consider labor supply effects) are based on data from the Current Population Survey March Supplement representing income from 2017 to 2019, and preserve existing benefits such as the Child Tax Credit.

# Imports.
import pandas as pd
import numpy as np
import math
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import copy

# Load data.
summary = pd.read_csv('https://github.com/ngpsu22/Child_Allowance_States/raw/main/poverty_gini_tax_child_allowance')

deciles = pd.read_csv('data/deciles.csv')

deciles.funding = deciles.funding.map({'deficit': 'No funding',
                                       'fed': 'Federal tax',
                                       'state': 'State tax'})

# General configs.
LABELS = {'monthly_ca': 'Monthly child allowance',
          'decile': 'Decile',
          'net_chg': 'Net change',
          'pct_chg': 'Net change',
          'child_allowance':'Monthly child allowance',
          'code': 'State',
          'state': 'State',
          'fed_tax_rate': 'Tax rate',
          'state_tax_rate': 'Tax rate',
          'non_funded_poverty_rate': 'Poverty rate',
          'fed_poverty_rate': 'Poverty rate',
          'state_poverty_rate': 'Poverty rate',
          'non_funded_gini': 'Gini index',
          'fed_gini': 'Gini index',
          'state_gini': 'Gini index'}

CONFIG = {'displayModeBar': False}

# Preprocess data.
summary.drop('Unnamed: 0', 1, inplace = True)
tax = summary[(summary.race == 'All') & (summary.age_group == 'all')]

state_names = tax.state.unique()
state_names = np.insert(state_names[:-1], 0, 'US')
default_state = 'US'
state_dict = summary[['code', 'state']].set_index('code').to_dict()['state']

# Colors from https://material.io/design/color/the-color-system.html
DARK_BLUE = '#1565C0'
LIGHT_BLUE = '#42A5F5'
GRAY = '#BDBDBD'
GRAY_SHADOW = '#EEEEEE'
COLOR_MAP = {
    'Federal tax rate': DARK_BLUE,
    'State tax rate': LIGHT_BLUE,
    'Federal tax': DARK_BLUE,
    'State tax': LIGHT_BLUE,
    'No funding': GRAY,
    'No funding, out of poverty': GRAY_SHADOW
}

# data labels
REFORM = {'state_tax_rate': 'State tax rate', 
          'fed_tax_rate': 'Federal tax rate'}

# reformat data
data_list = []
for state in state_names:
    state_data = tax[tax.state == state]
    state_list = []
    for reform in REFORM:
        state_list.append(state_data[reform])
    data_list.append(state_list)

# generate first graph
data_columns = list(REFORM.keys())
data = pd.DataFrame(data_list, columns = data_columns)
data['State'] = state_names
data = data.set_index('State')

def getDataList(state):
    data_list = []
    for dc in data_columns:
        data_list.append(data.loc[state][dc])
    return data_list

# initialize figure
fig = go.Figure()

# add traces
x = tax.child_allowance.unique()
for reform in REFORM:
    fig.add_trace(go.Scatter(
        x=x, 
        y=data[reform][default_state],
        name=REFORM[reform],
        marker = dict(color = COLOR_MAP[REFORM[reform]]),
        hoverlabel = dict(namelength = -1)
#         hovertemplate=
#                 REFORM[reform] + ': %{y}' + 
#                 '<extra></extra>',
    ))

# generate buttons
buttons = []
for state in state_names:
    new_button = {'method': 'update',
                  'label': state,
                  'args': [{'y': getDataList(state), 
                            'visible': ['legendonly' if state == 'US' 
                                        else True, True]}
                          ]}
    buttons.append(new_button)
    
# construct menus
updatemenus = [{'buttons': buttons,
                'direction': 'down',
                'showactive': True,
                'pad':{'l': 10, 'r': 25},
               }]

# update layout with buttons, and show the figure
fig.update_layout(updatemenus=updatemenus)

fig.update_xaxes(title_text='Monthly child allowance')

tax_values = tax.state_tax_rate.tolist() + tax.fed_tax_rate.tolist() 
ymin = math.floor(min(tax_values) * 100) / 100 - 0.1
ymax = math.ceil(max(tax_values) * 100) / 100
fig.update_yaxes(title_text='Tax rate on taxable income', range=[ymin, ymax])

fig.update_layout(height=600, 
                  margin=dict(l=0, r=0, t=80, b=0),
                  yaxis_ticksuffix='%',
                  font=dict(family='Roboto'),
                  hovermode='x', 
                  xaxis_tickprefix='$',
                  xaxis_ticksuffix='',
                  plot_bgcolor='white',
                  legend_title_text='',
                  title={
                    'text': 'Income tax required to fund child allowances',
                    'y':0.95,
                    'x':0.01,
                    'xanchor': 'left',
                    'yanchor': 'top'},
                  title_font_size=20,
                 )

fig.update_layout(hovermode="x unified")

# hide state tax rate for US only
hide_line = ['State tax rate']
fig.for_each_trace(lambda trace: trace.update(visible="legendonly")
                   if trace.name in hide_line else ())

fig.show(config=CONFIG)