New York State income tax#
New York households pay progressive tax rates on income, and have access to several refundable and non-refundable tax credits. Consider a set of New York family types, each with $1,000 monthly rent and $50 monthly broadband costs, and varying in terms of marital status and number of children. Their net income—after state and federal taxes and benefits modeled by OpenFisca US—is shown in the graph below.
The cliff is due to New York’s emergency SNAP allotment, which entitles SNAP-eligible households to the maximum benefit for their household size; this also affects other benefits through categorical eligibility.
from policyengine_us import IndividualSim
import pandas as pd
import plotly.express as px
LIGHT_GRAY = "#F5F5F5"
GRAY = "#BDBDBD"
BLUE = "#5091cc"
LIGHT_BLUE = "lightblue"
DARK_BLUE = "darkblue"
def make_tax(adults, children):
sim = IndividualSim(year=2022)
sim.add_person(name="head", age=25, rent=12_000)
members = ["head"]
if adults == 2:
sim.add_person(name="spouse", age=25)
members += ["spouse"]
for i in range(children):
child = "child{}".format(i)
sim.add_person(name=child, age=6)
members += [child]
sim.add_tax_unit(name="tax_unit", members=members, premium_tax_credit=0)
# $1,000 monthly rent, $50 monthly broadband.
sim.add_spm_unit(name="spm_unit", members=members, broadband_cost=600)
sim.add_household(name="household", members=members, state_code="NY")
sim.vary("employment_income", max=100_000, step=100)
employment_income = sim.calc("employment_income")[0]
spm_unit_net_income = sim.calc("spm_unit_net_income")[0].round()
mtr = 1 - sim.deriv(
"spm_unit_net_income", "employment_income", wrt_target="head"
)
return pd.DataFrame(
dict(
employment_income=employment_income,
spm_unit_net_income=spm_unit_net_income,
mtr=mtr,
adults=adults,
children=str(children),
)
)
# Make a table of state taxes for different numbers of adults and children.
l = []
for adults in range(1, 3):
for children in range(0, 4):
l.append(make_tax(adults, children))
df = pd.concat(l)
LABELS = dict(
employment_income="Employment income",
spm_unit_net_income="Net income",
mtr="Marginal tax rate",
adults="Adults",
children="Children",
)
COLOR_MAP = {"0": GRAY, "1": LIGHT_BLUE, "2": BLUE, "3": DARK_BLUE}
fig = px.line(
df,
"employment_income",
"spm_unit_net_income",
color="children",
animation_frame="adults",
labels=LABELS,
title="Net income for a New York household",
color_discrete_map=COLOR_MAP,
)
fig.update_layout(
xaxis_tickformat="$,",
yaxis_tickformat="$,",
plot_bgcolor="white",
xaxis_gridcolor=LIGHT_GRAY,
yaxis_gridcolor=LIGHT_GRAY,
)
fig.show()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/individual_sim.py:261, in IndividualSim.calc(self, var, period, target, index, map_to, reform)
260 try:
--> 261 result = self.simulation.calculate(var, period)
262 except:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:684, in Simulation._run_formula(self, variable, population, period)
683 for added_variable in adds_list:
--> 684 values = values + self.calculate(
685 added_variable, period, map_to=variable.entity.key
686 )
687 if variable.subtracts is not None:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py:34, in spm_unit_benefits.formula(spm_unit, period, parameters)
33 BENEFITS.append("spm_unit_capped_housing_subsidy")
---> 34 return add(spm_unit, period, BENEFITS)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/commons/formulas.py:225, in add(entity, period, variables, options)
211 """Sums a list of variables.
212
213 Args:
(...)
223 ArrayLike: The result of the operation.
224 """
--> 225 return for_each_variable(
226 entity, period, variables, agg_func="add", options=options
227 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/commons/formulas.py:184, in for_each_variable(entity, period, variables, agg_func, group_agg_func, options)
182 elif variable_entity.is_person:
183 values = group_agg_func(
--> 184 entity.members(variable, period, options=options)
185 )
186 elif entity.entity.is_person:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi.py:16, in ssi.formula(person, period, parameters)
15 return 0
---> 16 return max_(0, person("uncapped_ssi", period))
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/uncapped_ssi.py:13, in uncapped_ssi.formula(person, period, parameters)
12 def formula(person, period, parameters):
---> 13 amount = person("ssi_amount_if_eligible", period)
14 meets_resource_test = person("meets_ssi_resource_test", period)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi_amount_if_eligible.py:16, in ssi_amount_if_eligible.formula(person, period, parameters)
13 ssi = parameters(period).gov.ssa.ssi.amount
14 return (
15 where(
---> 16 person("ssi_claim_is_joint", period),
17 ssi.couple,
18 ssi.individual,
19 )
20 * MONTHS_IN_YEAR
21 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi_claim_is_joint.py:12, in ssi_claim_is_joint.formula(person, period, parameters)
11 eligible = person("is_ssi_aged_blind_disabled", period)
---> 12 both_eligible = person.marital_unit.sum(eligible) == 2
13 income_is_deemed = (
14 person("ssi_income_deemed_from_ineligible_spouse", period) > 0
15 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/projector.py:28, in Projector.__getattr__.<locals>.projector_function(*args, **kwargs)
27 result = reference_attr(*args, **kwargs)
---> 28 return self.transform_and_bubble_up(result)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/projector.py:37, in Projector.transform_and_bubble_up(self, result)
36 def transform_and_bubble_up(self, result):
---> 37 transformed_result = self.transform(result)
38 if self.parent is None:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/entity_to_person_projector.py:19, in EntityToPersonProjector.transform(self, result)
18 def transform(self, result: ArrayLike) -> ArrayLike:
---> 19 return self.reference_entity.project(result)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/group_population.py:335, in GroupPopulation.project(self, array, role)
334 def project(self, array: ArrayLike, role: Role = None) -> ArrayLike:
--> 335 self.check_array_compatible_with_entity(array)
336 self.entity.check_role_validity(role)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:60, in Population.check_array_compatible_with_entity(self, array)
59 if not self.count == array.size:
---> 60 raise ValueError(
61 "Input {} is not a valid value for the entity {} (size = {} != {} = count)".format(
62 array, self.entity.key, array.size, self.count
63 )
64 )
ValueError: Input [0. 0. 0. ... 0. 0. 0.] is not a valid value for the entity marital_unit (size = 3002 != 3003 = count)
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/individual_sim.py:264, in IndividualSim.calc(self, var, period, target, index, map_to, reform)
263 try:
--> 264 result = self.sim.calculate_add(var, period)
265 except:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:597, in Simulation.calculate_add(self, variable_name, period, decode_enums)
591 raise ValueError(
592 "Unable to sum constant variable '{}' over period {}: only variables defined daily, monthly, or yearly can be summed over time.".format(
593 variable.name, period
594 )
595 )
--> 597 return sum(
598 self.calculate(variable_name, sub_period)
599 for sub_period in period.get_subperiods(variable.definition_period)
600 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:598, in <genexpr>(.0)
591 raise ValueError(
592 "Unable to sum constant variable '{}' over period {}: only variables defined daily, monthly, or yearly can be summed over time.".format(
593 variable.name, period
594 )
595 )
597 return sum(
--> 598 self.calculate(variable_name, sub_period)
599 for sub_period in period.get_subperiods(variable.definition_period)
600 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:684, in Simulation._run_formula(self, variable, population, period)
683 for added_variable in adds_list:
--> 684 values = values + self.calculate(
685 added_variable, period, map_to=variable.entity.key
686 )
687 if variable.subtracts is not None:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py:34, in spm_unit_benefits.formula(spm_unit, period, parameters)
33 BENEFITS.append("spm_unit_capped_housing_subsidy")
---> 34 return add(spm_unit, period, BENEFITS)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/commons/formulas.py:225, in add(entity, period, variables, options)
211 """Sums a list of variables.
212
213 Args:
(...)
223 ArrayLike: The result of the operation.
224 """
--> 225 return for_each_variable(
226 entity, period, variables, agg_func="add", options=options
227 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/commons/formulas.py:184, in for_each_variable(entity, period, variables, agg_func, group_agg_func, options)
182 elif variable_entity.is_person:
183 values = group_agg_func(
--> 184 entity.members(variable, period, options=options)
185 )
186 elif entity.entity.is_person:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi.py:16, in ssi.formula(person, period, parameters)
15 return 0
---> 16 return max_(0, person("uncapped_ssi", period))
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/uncapped_ssi.py:13, in uncapped_ssi.formula(person, period, parameters)
12 def formula(person, period, parameters):
---> 13 amount = person("ssi_amount_if_eligible", period)
14 meets_resource_test = person("meets_ssi_resource_test", period)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi_amount_if_eligible.py:16, in ssi_amount_if_eligible.formula(person, period, parameters)
13 ssi = parameters(period).gov.ssa.ssi.amount
14 return (
15 where(
---> 16 person("ssi_claim_is_joint", period),
17 ssi.couple,
18 ssi.individual,
19 )
20 * MONTHS_IN_YEAR
21 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi_claim_is_joint.py:12, in ssi_claim_is_joint.formula(person, period, parameters)
11 eligible = person("is_ssi_aged_blind_disabled", period)
---> 12 both_eligible = person.marital_unit.sum(eligible) == 2
13 income_is_deemed = (
14 person("ssi_income_deemed_from_ineligible_spouse", period) > 0
15 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/projector.py:28, in Projector.__getattr__.<locals>.projector_function(*args, **kwargs)
27 result = reference_attr(*args, **kwargs)
---> 28 return self.transform_and_bubble_up(result)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/projector.py:37, in Projector.transform_and_bubble_up(self, result)
36 def transform_and_bubble_up(self, result):
---> 37 transformed_result = self.transform(result)
38 if self.parent is None:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/entity_to_person_projector.py:19, in EntityToPersonProjector.transform(self, result)
18 def transform(self, result: ArrayLike) -> ArrayLike:
---> 19 return self.reference_entity.project(result)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/group_population.py:335, in GroupPopulation.project(self, array, role)
334 def project(self, array: ArrayLike, role: Role = None) -> ArrayLike:
--> 335 self.check_array_compatible_with_entity(array)
336 self.entity.check_role_validity(role)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:60, in Population.check_array_compatible_with_entity(self, array)
59 if not self.count == array.size:
---> 60 raise ValueError(
61 "Input {} is not a valid value for the entity {} (size = {} != {} = count)".format(
62 array, self.entity.key, array.size, self.count
63 )
64 )
ValueError: Input [0. 0. 0. ... 0. 0. 0.] is not a valid value for the entity marital_unit (size = 3002 != 3003 = count)
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
Cell In[1], line 48
46 for adults in range(1, 3):
47 for children in range(0, 4):
---> 48 l.append(make_tax(adults, children))
50 df = pd.concat(l)
52 LABELS = dict(
53 employment_income="Employment income",
54 spm_unit_net_income="Net income",
(...)
57 children="Children",
58 )
Cell In[1], line 29, in make_tax(adults, children)
27 sim.vary("employment_income", max=100_000, step=100)
28 employment_income = sim.calc("employment_income")[0]
---> 29 spm_unit_net_income = sim.calc("spm_unit_net_income")[0].round()
30 mtr = 1 - sim.deriv(
31 "spm_unit_net_income", "employment_income", wrt_target="head"
32 )
33 return pd.DataFrame(
34 dict(
35 employment_income=employment_income,
(...)
40 )
41 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/individual_sim.py:266, in IndividualSim.calc(self, var, period, target, index, map_to, reform)
264 result = self.sim.calculate_add(var, period)
265 except:
--> 266 result = self.simulation.calculate_divide(var, period)
267 if (
268 target is not None
269 and target not in self.situation_data[entity.plural]
270 ):
271 map_to = self.get_entity(target).key
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:634, in Simulation.calculate_divide(self, variable_name, period, decode_enums)
630 return (
631 self.calculate(variable_name, period=computation_period) / 12.0
632 )
633 elif period.unit == periods.YEAR:
--> 634 return self.calculate(variable_name, period)
636 raise ValueError(
637 "Unable to divide the value of '{}' to match period {}.".format(
638 variable_name, period
639 )
640 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
315 self.tracer.record_calculation_start(
316 variable_name, period, self.branch_name
317 )
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
322 result = result.decode_to_str()
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
479 try:
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
484 if array is None:
485 # Check if the variable has a previously defined value
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:684, in Simulation._run_formula(self, variable, population, period)
682 values = 0
683 for added_variable in adds_list:
--> 684 values = values + self.calculate(
685 added_variable, period, map_to=variable.entity.key
686 )
687 if variable.subtracts is not None:
688 if isinstance(variable.subtracts, str):
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
315 self.tracer.record_calculation_start(
316 variable_name, period, self.branch_name
317 )
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
322 result = result.decode_to_str()
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
479 try:
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
484 if array is None:
485 # Check if the variable has a previously defined value
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
719 array = formula(population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py:34, in spm_unit_benefits.formula(spm_unit, period, parameters)
32 if not parameters(period).gov.hud.abolition:
33 BENEFITS.append("spm_unit_capped_housing_subsidy")
---> 34 return add(spm_unit, period, BENEFITS)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/commons/formulas.py:225, in add(entity, period, variables, options)
205 def add(
206 entity: Population,
207 period: Period,
208 variables: List[str],
209 options: List[str] = None,
210 ):
211 """Sums a list of variables.
212
213 Args:
(...)
223 ArrayLike: The result of the operation.
224 """
--> 225 return for_each_variable(
226 entity, period, variables, agg_func="add", options=options
227 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/commons/formulas.py:184, in for_each_variable(entity, period, variables, agg_func, group_agg_func, options)
181 values = entity(variable, period, options=options)
182 elif variable_entity.is_person:
183 values = group_agg_func(
--> 184 entity.members(variable, period, options=options)
185 )
186 elif entity.entity.is_person:
187 raise ValueError(
188 f"You requested to aggregate {variable} (defined for {variable_entity.plural}) to {entity.entity.plural}, but this is not yet implemented."
189 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
130 return self.simulation.calculate_divide(
131 variable_name, period, **calculate_kwargs
132 )
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
315 self.tracer.record_calculation_start(
316 variable_name, period, self.branch_name
317 )
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
322 result = result.decode_to_str()
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
479 try:
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
484 if array is None:
485 # Check if the variable has a previously defined value
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
719 array = formula(population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi.py:16, in ssi.formula(person, period, parameters)
14 if parameters(period).gov.ssa.ssi.abolish_ssi:
15 return 0
---> 16 return max_(0, person("uncapped_ssi", period))
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
130 return self.simulation.calculate_divide(
131 variable_name, period, **calculate_kwargs
132 )
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
315 self.tracer.record_calculation_start(
316 variable_name, period, self.branch_name
317 )
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
322 result = result.decode_to_str()
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
479 try:
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
484 if array is None:
485 # Check if the variable has a previously defined value
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
719 array = formula(population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/uncapped_ssi.py:13, in uncapped_ssi.formula(person, period, parameters)
12 def formula(person, period, parameters):
---> 13 amount = person("ssi_amount_if_eligible", period)
14 meets_resource_test = person("meets_ssi_resource_test", period)
15 eligible = person("is_ssi_eligible_individual", period)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
130 return self.simulation.calculate_divide(
131 variable_name, period, **calculate_kwargs
132 )
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
315 self.tracer.record_calculation_start(
316 variable_name, period, self.branch_name
317 )
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
322 result = result.decode_to_str()
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
479 try:
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
484 if array is None:
485 # Check if the variable has a previously defined value
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
719 array = formula(population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi_amount_if_eligible.py:16, in ssi_amount_if_eligible.formula(person, period, parameters)
12 def formula(person, period, parameters):
13 ssi = parameters(period).gov.ssa.ssi.amount
14 return (
15 where(
---> 16 person("ssi_claim_is_joint", period),
17 ssi.couple,
18 ssi.individual,
19 )
20 * MONTHS_IN_YEAR
21 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:134, in Population.__call__(self, variable_name, period, options)
130 return self.simulation.calculate_divide(
131 variable_name, period, **calculate_kwargs
132 )
133 else:
--> 134 return self.simulation.calculate(
135 variable_name, period, **calculate_kwargs
136 )
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:320, in Simulation.calculate(self, variable_name, period, map_to, decode_enums)
315 self.tracer.record_calculation_start(
316 variable_name, period, self.branch_name
317 )
319 try:
--> 320 result = self._calculate(variable_name, period)
321 if isinstance(result, EnumArray) and decode_enums:
322 result = result.decode_to_str()
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:481, in Simulation._calculate(self, variable_name, period)
479 try:
480 self._check_for_cycle(variable.name, period)
--> 481 array = self._run_formula(variable, population, period)
483 # If no result, use the default value and cache it
484 if array is None:
485 # Check if the variable has a previously defined value
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/simulations/simulation.py:721, in Simulation._run_formula(self, variable, population, period)
719 array = formula(population, period)
720 else:
--> 721 array = formula(population, period, parameters_at)
723 return array
File ~/work/policyengine-us/policyengine-us/policyengine_us/variables/gov/ssa/ssi/ssi_claim_is_joint.py:12, in ssi_claim_is_joint.formula(person, period, parameters)
10 def formula(person, period, parameters):
11 eligible = person("is_ssi_aged_blind_disabled", period)
---> 12 both_eligible = person.marital_unit.sum(eligible) == 2
13 income_is_deemed = (
14 person("ssi_income_deemed_from_ineligible_spouse", period) > 0
15 )
16 return both_eligible | income_is_deemed
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/projector.py:28, in Projector.__getattr__.<locals>.projector_function(*args, **kwargs)
26 def projector_function(*args, **kwargs):
27 result = reference_attr(*args, **kwargs)
---> 28 return self.transform_and_bubble_up(result)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/projector.py:37, in Projector.transform_and_bubble_up(self, result)
36 def transform_and_bubble_up(self, result):
---> 37 transformed_result = self.transform(result)
38 if self.parent is None:
39 return transformed_result
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/projectors/entity_to_person_projector.py:19, in EntityToPersonProjector.transform(self, result)
18 def transform(self, result: ArrayLike) -> ArrayLike:
---> 19 return self.reference_entity.project(result)
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/group_population.py:335, in GroupPopulation.project(self, array, role)
334 def project(self, array: ArrayLike, role: Role = None) -> ArrayLike:
--> 335 self.check_array_compatible_with_entity(array)
336 self.entity.check_role_validity(role)
337 if role is None:
File /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/policyengine_core/populations/population.py:60, in Population.check_array_compatible_with_entity(self, array)
58 def check_array_compatible_with_entity(self, array: numpy.ndarray) -> None:
59 if not self.count == array.size:
---> 60 raise ValueError(
61 "Input {} is not a valid value for the entity {} (size = {} != {} = count)".format(
62 array, self.entity.key, array.size, self.count
63 )
64 )
ValueError: Input [0. 0. 0. ... 0. 0. 0.] is not a valid value for the entity marital_unit (size = 3002 != 3003 = count)
Marginal tax rates can reach as low as -84% and as high (excluding cliffs) as 65%.
fig = px.line(
df,
"employment_income",
"mtr",
color="children",
animation_frame="adults",
labels=LABELS,
title="Marginal tax rate for a New York household",
color_discrete_map=COLOR_MAP,
)
fig.update_layout(
xaxis_tickformat="$,",
yaxis_tickformat=".1%",
yaxis_range=[-1, 1],
plot_bgcolor="white",
xaxis_gridcolor=LIGHT_GRAY,
yaxis_gridcolor=LIGHT_GRAY,
)
fig.show()