diff --git a/us/states/ny/budget_agreement/household_impacts.ipynb b/us/states/ny/budget_agreement/household_impacts.ipynb new file mode 100644 index 0000000..763cfd8 --- /dev/null +++ b/us/states/ny/budget_agreement/household_impacts.ipynb @@ -0,0 +1,519 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# NY Budget Agreement - Household Impacts\n", + "\n", + "Analysis of household impacts for a single parent (age 40) with a child (age 6) for years 2025, 2026, and 2027." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'matplotlib'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[2], line 9\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mIPython\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdisplay\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m Markdown, Image\n\u001b[0;32m 8\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mpandas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mpd\u001b[39;00m\n\u001b[1;32m----> 9\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpyplot\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mplt\u001b[39;00m\n\u001b[0;32m 10\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mticker\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mticker\u001b[39;00m\n", + "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'matplotlib'" + ] + } + ], + "source": [ + "# Restart kernel if you see an AttributeError and run this cell first\n", + "import sys\n", + "sys.path.insert(0, r'C:\\Users\\dtsax\\PolicyEngine\\policyengine-us')\n", + "\n", + "from policyengine_us import Simulation\n", + "from policyengine_core.reforms import Reform\n", + "from IPython.display import Markdown, Image\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.ticker as ticker" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define Reform\n", + "\n", + "Baseline represents repealed reforms (pre-2026 rates and no new programs). We compare this against current law." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "baseline = Reform.from_dict({\n", + " \"gov.states.ny.tax.income.main.joint[0].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.04\n", + " },\n", + " \"gov.states.ny.tax.income.main.joint[1].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.045\n", + " },\n", + " \"gov.states.ny.tax.income.main.joint[2].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.0525\n", + " },\n", + " \"gov.states.ny.tax.income.main.joint[3].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.055\n", + " },\n", + " \"gov.states.ny.tax.income.main.joint[4].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.06\n", + " },\n", + " \"gov.states.ny.tax.income.main.single[0].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.04\n", + " },\n", + " \"gov.states.ny.tax.income.main.single[1].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.045\n", + " },\n", + " \"gov.states.ny.tax.income.main.single[2].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.0525\n", + " },\n", + " \"gov.states.ny.tax.income.main.single[3].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.055\n", + " },\n", + " \"gov.states.ny.tax.income.main.single[4].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.06\n", + " },\n", + " \"gov.states.ny.tax.income.main.separate[0].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.04\n", + " },\n", + " \"gov.states.ny.tax.income.main.separate[1].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.045\n", + " },\n", + " \"gov.states.ny.tax.income.main.separate[2].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.0525\n", + " },\n", + " \"gov.states.ny.tax.income.main.separate[3].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.055\n", + " },\n", + " \"gov.states.ny.tax.income.main.separate[4].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.06\n", + " },\n", + " \"gov.states.ny.tax.income.main.surviving_spouse[0].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.04\n", + " },\n", + " \"gov.states.ny.tax.income.main.surviving_spouse[1].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.045\n", + " },\n", + " \"gov.states.ny.tax.income.main.surviving_spouse[2].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.0525\n", + " },\n", + " \"gov.states.ny.tax.income.main.surviving_spouse[3].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.055\n", + " },\n", + " \"gov.states.ny.tax.income.main.surviving_spouse[4].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.06\n", + " },\n", + " \"gov.states.ny.tax.income.main.head_of_household[0].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.04\n", + " },\n", + " \"gov.states.ny.tax.income.main.head_of_household[1].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.045\n", + " },\n", + " \"gov.states.ny.tax.income.main.head_of_household[2].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.0525\n", + " },\n", + " \"gov.states.ny.tax.income.main.head_of_household[3].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.055\n", + " },\n", + " \"gov.states.ny.tax.income.main.head_of_household[4].rate\": {\n", + " \"2026-01-01.2100-12-31\": 0.06\n", + " },\n", + " \"gov.states.ny.tax.income.credits.ctc.post_2024.in_effect\": {\n", + " \"2025-01-01.2027-12-31\": False\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.joint[0].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.joint[1].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.single[0].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.single[1].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.separate[0].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.separate[1].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.joint[2].amount\": {\n", + " \"2027-01-01.2100-12-31\": 1140\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.joint[3].amount\": {\n", + " \"2026-01-01.2100-12-31\": 3887\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.joint[4].amount\": {\n", + " \"2026-01-01.2100-12-31\": 64237\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.single[1].amount\": {\n", + " \"2026-01-01.2026-12-31\": 568\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.single[2].amount\": {\n", + " \"2026-01-01.2100-12-31\": 2399\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.single[3].amount\": {\n", + " \"2026-01-01.2100-12-31\": 32571\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.separate[1].amount\": {\n", + " \"2026-01-01.2026-12-31\": 568\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.separate[2].amount\": {\n", + " \"2026-01-01.2100-12-31\": 2399\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.separate[3].amount\": {\n", + " \"2026-01-01.2100-12-31\": 32571\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.joint[1].amount\": {\n", + " \"2027-01-01.2100-12-31\": 807\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.joint[2].amount\": {\n", + " \"2026-01-01.2100-12-31\": 2747\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.joint[3].amount\": {\n", + " \"2033-01-01.2100-12-31\": 60350\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.single[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 568\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.single[1].amount\": {\n", + " \"2026-01-01.2100-12-31\": 1831\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.single[2].amount\": {\n", + " \"2033-01-01.2100-12-31\": 30172\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.surviving_spouse[0].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.surviving_spouse[1].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.separate[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 568\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.separate[1].amount\": {\n", + " \"2026-01-01.2100-12-31\": 1831\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.separate[2].amount\": {\n", + " \"2033-01-01.2100-12-31\": 30172\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.head_of_household[0].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.credits.inflation_refund.head_of_household[1].amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.surviving_spouse[2].amount\": {\n", + " \"2027-01-01.2100-12-31\": 1140\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.surviving_spouse[3].amount\": {\n", + " \"2026-01-01.2100-12-31\": 3887\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.surviving_spouse[4].amount\": {\n", + " \"2026-01-01.2100-12-31\": 64237\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.head_of_household[2].amount\": {\n", + " \"2026-01-01.2100-12-31\": 3076\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.recapture_base.head_of_household[3].amount\": {\n", + " \"2026-01-01.2100-12-31\": 48337\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.surviving_spouse[1].amount\": {\n", + " \"2027-01-01.2100-12-31\": 807\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.surviving_spouse[2].amount\": {\n", + " \"2026-01-01.2100-12-31\": 2747\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.surviving_spouse[3].amount\": {\n", + " \"2033-01-01.2100-12-31\": 60350\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.head_of_household[1].amount\": {\n", + " \"2026-01-01.2100-12-31\": 2289\n", + " },\n", + " \"gov.states.ny.tax.income.supplemental.incremental_benefit.head_of_household[2].amount\": {\n", + " \"2026-01-01.2100-12-31\": 45261\n", + " }\n", + "}, country_id=\"us\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define Household Situation\n", + "\n", + "Single parent (age 40) with one child (age 6)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# PolicyEngine color palette\n", + "BLACK = \"#000000\"\n", + "BLUE_PRIMARY = \"#2C6496\"\n", + "DARK_GRAY = \"#616161\"\n", + "\n", + "def create_situation(year):\n", + " return {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {year: 40}},\n", + " \"child\": {\"age\": {year: 6}},\n", + " },\n", + " \"families\": {\n", + " \"family\": {\"members\": [\"parent\", \"child\"]}\n", + " },\n", + " \"spm_units\": {\n", + " \"spm_unit\": {\"members\": [\"parent\", \"child\"]}\n", + " },\n", + " \"tax_units\": {\n", + " \"tax_unit\": {\"members\": [\"parent\", \"child\"]}\n", + " },\n", + " \"households\": {\n", + " \"household\": {\n", + " \"members\": [\"parent\", \"child\"],\n", + " \"state_name\": {year: \"NY\"},\n", + " }\n", + " },\n", + " \"marital_units\": {\n", + " \"parent_marital_unit\": {\"members\": [\"parent\"]},\n", + " \"child_marital_unit\": {\n", + " \"members\": [\"child\"],\n", + " \"marital_unit_id\": {year: 1},\n", + " },\n", + " },\n", + " \"axes\": [\n", + " [\n", + " {\n", + " \"name\": \"employment_income\",\n", + " \"count\": 401,\n", + " \"min\": 0,\n", + " \"max\": 200000,\n", + " \"period\": year,\n", + " }\n", + " ]\n", + " ],\n", + " }" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2025 Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create simulations for 2025\n", + "situation_2025 = create_situation(2025)\n", + "sim_baseline_2025 = Simulation(situation=situation_2025, reform=baseline)\n", + "sim_reformed_2025 = Simulation(situation=situation_2025)\n", + "\n", + "# Calculate net income at household level\n", + "baseline_income_2025 = sim_baseline_2025.calculate(\"household_net_income\", 2025)\n", + "reformed_income_2025 = sim_reformed_2025.calculate(\"household_net_income\", 2025)\n", + "\n", + "# Calculate change\n", + "change_2025 = reformed_income_2025 - baseline_income_2025\n", + "\n", + "# Get employment income values - calculate at person level for parent\n", + "employment_income_2025 = sim_baseline_2025.calculate(\"employment_income\", 2025, map_to=\"person\")\n", + "# Get just the parent's values (first person in household)\n", + "employment_income_2025 = employment_income_2025[::2] # Every other value (parent, skipping child)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create DataFrame for 2025\n", + "df_2025 = pd.DataFrame(\n", + " {\n", + " \"Employment Income\": employment_income_2025,\n", + " \"Change in Net Income\": change_2025,\n", + " }\n", + ")\n", + "\n", + "# Create matplotlib plot for 2025\n", + "fig, ax = plt.subplots(figsize=(12, 7))\n", + "ax.plot(df_2025[\"Employment Income\"], df_2025[\"Change in Net Income\"], color=\"#2C6496\", linewidth=2)\n", + "ax.set_xlabel(\"Household head employment income ($)\", fontfamily=\"serif\", fontsize=12)\n", + "ax.set_ylabel(\"Change in net income ($)\", fontfamily=\"serif\", fontsize=12)\n", + "ax.set_title(\"Change in Net Income for a Single Parent (Age 40) with Child (Age 6) in 2025\", \n", + " fontfamily=\"serif\", fontsize=14, pad=20)\n", + "ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'${x:,.0f}'))\n", + "ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'${x:,.0f}'))\n", + "ax.grid(True, alpha=0.3)\n", + "ax.text(1.0, -0.15, 'Source: PolicyEngine US', transform=ax.transAxes, \n", + " fontsize=9, color='#616161', ha='right', fontfamily=\"serif\")\n", + "plt.tight_layout()\n", + "plt.savefig(\"ny_household_impact_2025.png\", dpi=150, bbox_inches='tight')\n", + "print(\"Saved ny_household_impact_2025.png\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2026 Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create simulations for 2026\n", + "situation_2026 = create_situation(2026)\n", + "sim_baseline_2026 = Simulation(situation=situation_2026, reform=baseline)\n", + "sim_reformed_2026 = Simulation(situation=situation_2026)\n", + "\n", + "# Calculate net income at household level\n", + "baseline_income_2026 = sim_baseline_2026.calculate(\"household_net_income\", 2026)\n", + "reformed_income_2026 = sim_reformed_2026.calculate(\"household_net_income\", 2026)\n", + "\n", + "# Calculate change\n", + "change_2026 = reformed_income_2026 - baseline_income_2026\n", + "\n", + "# Get employment income values - calculate at person level for parent\n", + "employment_income_2026 = sim_baseline_2026.calculate(\"employment_income\", 2026, map_to=\"person\")\n", + "# Get just the parent's values (first person in household)\n", + "employment_income_2026 = employment_income_2026[::2] # Every other value (parent, skipping child)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create DataFrame for 2026\n", + "df_2026 = pd.DataFrame(\n", + " {\n", + " \"Employment Income\": employment_income_2026,\n", + " \"Change in Net Income\": change_2026,\n", + " }\n", + ")\n", + "\n", + "# Create matplotlib plot for 2026\n", + "fig, ax = plt.subplots(figsize=(12, 7))\n", + "ax.plot(df_2026[\"Employment Income\"], df_2026[\"Change in Net Income\"], color=\"#2C6496\", linewidth=2)\n", + "ax.set_xlabel(\"Household head employment income ($)\", fontfamily=\"serif\", fontsize=12)\n", + "ax.set_ylabel(\"Change in net income ($)\", fontfamily=\"serif\", fontsize=12)\n", + "ax.set_title(\"Change in Net Income for a Single Parent (Age 40) with Child (Age 6) in 2026\", \n", + " fontfamily=\"serif\", fontsize=14, pad=20)\n", + "ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'${x:,.0f}'))\n", + "ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'${x:,.0f}'))\n", + "ax.grid(True, alpha=0.3)\n", + "ax.text(1.0, -0.15, 'Source: PolicyEngine US', transform=ax.transAxes, \n", + " fontsize=9, color='#616161', ha='right', fontfamily=\"serif\")\n", + "plt.tight_layout()\n", + "plt.savefig(\"ny_household_impact_2026.png\", dpi=150, bbox_inches='tight')\n", + "print(\"Saved ny_household_impact_2026.png\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create simulations for 2027\n", + "situation_2027 = create_situation(2027)\n", + "sim_baseline_2027 = Simulation(situation=situation_2027, reform=baseline)\n", + "sim_reformed_2027 = Simulation(situation=situation_2027)\n", + "\n", + "# Calculate net income at household level\n", + "baseline_income_2027 = sim_baseline_2027.calculate(\"household_net_income\", 2027)\n", + "reformed_income_2027 = sim_reformed_2027.calculate(\"household_net_income\", 2027)\n", + "\n", + "# Calculate change\n", + "change_2027 = reformed_income_2027 - baseline_income_2027\n", + "\n", + "# Get employment income values - calculate at person level for parent\n", + "employment_income_2027 = sim_baseline_2027.calculate(\"employment_income\", 2027, map_to=\"person\")\n", + "# Get just the parent's values (first person in household)\n", + "employment_income_2027 = employment_income_2027[::2] # Every other value (parent, skipping child)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create DataFrame for 2027\n", + "df_2027 = pd.DataFrame(\n", + " {\n", + " \"Employment Income\": employment_income_2027,\n", + " \"Change in Net Income\": change_2027,\n", + " }\n", + ")\n", + "\n", + "# Create matplotlib plot for 2027\n", + "fig, ax = plt.subplots(figsize=(12, 7))\n", + "ax.plot(df_2027[\"Employment Income\"], df_2027[\"Change in Net Income\"], color=\"#2C6496\", linewidth=2)\n", + "ax.set_xlabel(\"Household head employment income ($)\", fontfamily=\"serif\", fontsize=12)\n", + "ax.set_ylabel(\"Change in net income ($)\", fontfamily=\"serif\", fontsize=12)\n", + "ax.set_title(\"Change in Net Income for a Single Parent (Age 40) with Child (Age 6) in 2027\", \n", + " fontfamily=\"serif\", fontsize=14, pad=20)\n", + "ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'${x:,.0f}'))\n", + "ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'${x:,.0f}'))\n", + "ax.grid(True, alpha=0.3)\n", + "ax.text(1.0, -0.15, 'Source: PolicyEngine US', transform=ax.transAxes, \n", + " fontsize=9, color='#616161', ha='right', fontfamily=\"serif\")\n", + "plt.tight_layout()\n", + "plt.savefig(\"ny_household_impact_2027.png\", dpi=150, bbox_inches='tight')\n", + "print(\"Saved ny_household_impact_2027.png\")\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pe", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.10" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/us/states/ny/budget_agreement/ny_household_impact_2025.html b/us/states/ny/budget_agreement/ny_household_impact_2025.html new file mode 100644 index 0000000..55d70f9 --- /dev/null +++ b/us/states/ny/budget_agreement/ny_household_impact_2025.html @@ -0,0 +1,14 @@ + + + +
+
+ + \ No newline at end of file diff --git a/us/states/ny/budget_agreement/ny_household_impact_2026.html b/us/states/ny/budget_agreement/ny_household_impact_2026.html new file mode 100644 index 0000000..21b8cfe --- /dev/null +++ b/us/states/ny/budget_agreement/ny_household_impact_2026.html @@ -0,0 +1,14 @@ + + + +
+
+ + \ No newline at end of file diff --git a/us/states/ny/budget_agreement/ny_household_impact_2027.html b/us/states/ny/budget_agreement/ny_household_impact_2027.html new file mode 100644 index 0000000..9335b04 --- /dev/null +++ b/us/states/ny/budget_agreement/ny_household_impact_2027.html @@ -0,0 +1,14 @@ + + + +
+
+ + \ No newline at end of file