Created
January 31, 2026 20:32
-
-
Save MaxGhenis/1d4f3b573d0ffbede880b05be1281b6a to your computer and use it in GitHub Desktop.
Impact of unemployment insurance on child poverty: repeal vs. doubling (PolicyEngine-US 2026)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "id": "80dbc76f", | |
| "metadata": {}, | |
| "source": [ | |
| "# Impact of unemployment insurance on child poverty: repeal vs. doubling\n", | |
| "\n", | |
| "This notebook analyzes how repealing and doubling UI benefits would each affect child poverty in 2026 using PolicyEngine-US microsimulation.\n", | |
| "\n", | |
| "**Methodology:**\n", | |
| "- Compare baseline (with UI) to two counterfactuals: UI zeroed out (repeal) and UI doubled\n", | |
| "- Changes cascade through tax calculations and other benefits\n", | |
| "- Uses SPM (Supplemental Poverty Measure) for poverty measurement" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "id": "436044c2", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-01-31T20:31:47.251532Z", | |
| "iopub.status.busy": "2026-01-31T20:31:47.251447Z", | |
| "iopub.status.idle": "2026-01-31T20:31:51.550637Z", | |
| "shell.execute_reply": "2026-01-31T20:31:51.550081Z" | |
| } | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "from policyengine_us import Microsimulation\n", | |
| "import numpy as np\n", | |
| "import pandas as pd\n", | |
| "\n", | |
| "year = 2026" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "a2fb0b4b", | |
| "metadata": {}, | |
| "source": [ | |
| "## Setup simulations" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "id": "548e8501", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-01-31T20:31:51.555630Z", | |
| "iopub.status.busy": "2026-01-31T20:31:51.555332Z", | |
| "iopub.status.idle": "2026-01-31T20:31:52.441895Z", | |
| "shell.execute_reply": "2026-01-31T20:31:52.441394Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "Simulations initialized for 2026\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# Baseline simulation (current law with UI)\n", | |
| "baseline = Microsimulation()\n", | |
| "\n", | |
| "# Counterfactual 1: zero out unemployment compensation (repeal)\n", | |
| "repeal = Microsimulation()\n", | |
| "repeal.set_input(\n", | |
| " \"unemployment_compensation\",\n", | |
| " year,\n", | |
| " repeal.calc(\"unemployment_compensation\", period=year).values * 0,\n", | |
| ")\n", | |
| "\n", | |
| "# Counterfactual 2: double unemployment compensation\n", | |
| "doubled = Microsimulation()\n", | |
| "doubled.set_input(\n", | |
| " \"unemployment_compensation\",\n", | |
| " year,\n", | |
| " doubled.calc(\"unemployment_compensation\", period=year).values * 2,\n", | |
| ")\n", | |
| "\n", | |
| "print(f\"Simulations initialized for {year}\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "f1f30b45", | |
| "metadata": {}, | |
| "source": [ | |
| "## Child poverty impact" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "id": "d682a8ad", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-01-31T20:31:52.443442Z", | |
| "iopub.status.busy": "2026-01-31T20:31:52.443346Z", | |
| "iopub.status.idle": "2026-01-31T20:32:39.530885Z", | |
| "shell.execute_reply": "2026-01-31T20:32:39.530206Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "=== CHILD POVERTY IMPACT ===\n", | |
| "Baseline child poverty rate (current UI): 22.20%\n", | |
| "\n", | |
| "Repealing UI:\n", | |
| " Child poverty rate: 22.42%\n", | |
| " Increase: +0.22% (1.0% increase)\n", | |
| " Children pushed into poverty: 159,849\n", | |
| "\n", | |
| "Doubling UI:\n", | |
| " Child poverty rate: 22.14%\n", | |
| " Reduction: -0.06% (0.3% reduction)\n", | |
| " Children lifted from poverty: 41,023\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# Get child indicator\n", | |
| "is_child = baseline.calc(\"is_child\", period=year)\n", | |
| "total_children = float(is_child.sum())\n", | |
| "\n", | |
| "# Calculate SPM poverty status for each person\n", | |
| "baseline_in_poverty = baseline.calc(\"person_in_poverty\", period=year)\n", | |
| "repeal_in_poverty = repeal.calc(\"person_in_poverty\", period=year)\n", | |
| "doubled_in_poverty = doubled.calc(\"person_in_poverty\", period=year)\n", | |
| "\n", | |
| "# Filter to children only\n", | |
| "baseline_child_poverty = baseline_in_poverty[is_child.values == 1]\n", | |
| "repeal_child_poverty = repeal_in_poverty[is_child.values == 1]\n", | |
| "doubled_child_poverty = doubled_in_poverty[is_child.values == 1]\n", | |
| "\n", | |
| "# Calculate rates (MicroSeries .mean() is weighted automatically)\n", | |
| "baseline_rate = float(baseline_child_poverty.mean())\n", | |
| "repeal_rate = float(repeal_child_poverty.mean())\n", | |
| "doubled_rate = float(doubled_child_poverty.mean())\n", | |
| "\n", | |
| "# Repeal metrics\n", | |
| "repeal_increase_pp = repeal_rate - baseline_rate\n", | |
| "repeal_increase_pct = repeal_increase_pp / baseline_rate if baseline_rate > 0 else 0\n", | |
| "repeal_children_into_poverty = total_children * repeal_increase_pp\n", | |
| "\n", | |
| "# Doubling metrics\n", | |
| "doubled_reduction_pp = baseline_rate - doubled_rate\n", | |
| "doubled_reduction_pct = doubled_reduction_pp / baseline_rate if baseline_rate > 0 else 0\n", | |
| "doubled_children_lifted = total_children * doubled_reduction_pp\n", | |
| "\n", | |
| "print(\"=== CHILD POVERTY IMPACT ===\")\n", | |
| "print(f\"Baseline child poverty rate (current UI): {baseline_rate:.2%}\")\n", | |
| "print()\n", | |
| "print(f\"Repealing UI:\")\n", | |
| "print(f\" Child poverty rate: {repeal_rate:.2%}\")\n", | |
| "print(f\" Increase: +{repeal_increase_pp:.2%} ({repeal_increase_pct:.1%} increase)\")\n", | |
| "print(f\" Children pushed into poverty: {repeal_children_into_poverty:,.0f}\")\n", | |
| "print()\n", | |
| "print(f\"Doubling UI:\")\n", | |
| "print(f\" Child poverty rate: {doubled_rate:.2%}\")\n", | |
| "print(f\" Reduction: -{doubled_reduction_pp:.2%} ({doubled_reduction_pct:.1%} reduction)\")\n", | |
| "print(f\" Children lifted from poverty: {doubled_children_lifted:,.0f}\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "f22bc6c4", | |
| "metadata": {}, | |
| "source": [ | |
| "## Fiscal impacts" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "id": "90f63ec0", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-01-31T20:32:39.536289Z", | |
| "iopub.status.busy": "2026-01-31T20:32:39.536145Z", | |
| "iopub.status.idle": "2026-01-31T20:32:39.545106Z", | |
| "shell.execute_reply": "2026-01-31T20:32:39.544372Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "=== FISCAL IMPACTS: Repeal UI ===\n", | |
| "UI outlays change: $-41.57B\n", | |
| "Federal tax revenue change: $-5.90B\n", | |
| "State/local tax revenue change: $-1.05B\n", | |
| "Other benefits change (SNAP, etc.): $0.74B\n", | |
| "Net income change: $-33.88B\n", | |
| "\n", | |
| "=== FISCAL IMPACTS: Double UI ===\n", | |
| "UI outlays change: $41.57B\n", | |
| "Federal tax revenue change: $7.09B\n", | |
| "State/local tax revenue change: $1.06B\n", | |
| "Other benefits change (SNAP, etc.): $-0.48B\n", | |
| "Net income change: $32.93B\n", | |
| "\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "def calc_fiscal(sim, label):\n", | |
| " ui = float((sim.calc(\"unemployment_compensation\", period=year) - baseline.calc(\"unemployment_compensation\", period=year)).sum())\n", | |
| " fed_tax = float((sim.calc(\"spm_unit_federal_tax\", period=year) - baseline.calc(\"spm_unit_federal_tax\", period=year)).sum())\n", | |
| " state_tax = float((sim.calc(\"spm_unit_state_tax\", period=year) - baseline.calc(\"spm_unit_state_tax\", period=year)).sum())\n", | |
| " benefits = float((sim.calc(\"spm_unit_benefits\", period=year) - baseline.calc(\"spm_unit_benefits\", period=year)).sum())\n", | |
| " net_income = float((sim.calc(\"spm_unit_net_income\", period=year) - baseline.calc(\"spm_unit_net_income\", period=year)).sum())\n", | |
| " other_benefits = benefits - ui\n", | |
| " return {\n", | |
| " \"label\": label,\n", | |
| " \"ui_change\": ui,\n", | |
| " \"fed_tax_change\": fed_tax,\n", | |
| " \"state_tax_change\": state_tax,\n", | |
| " \"other_benefits_change\": other_benefits,\n", | |
| " \"net_income_change\": net_income,\n", | |
| " }\n", | |
| "\n", | |
| "repeal_fiscal = calc_fiscal(repeal, \"Repeal UI\")\n", | |
| "doubled_fiscal = calc_fiscal(doubled, \"Double UI\")\n", | |
| "\n", | |
| "for f in [repeal_fiscal, doubled_fiscal]:\n", | |
| " print(f\"=== FISCAL IMPACTS: {f['label']} ===\")\n", | |
| " print(f\"UI outlays change: ${f['ui_change']/1e9:.2f}B\")\n", | |
| " print(f\"Federal tax revenue change: ${f['fed_tax_change']/1e9:.2f}B\")\n", | |
| " print(f\"State/local tax revenue change: ${f['state_tax_change']/1e9:.2f}B\")\n", | |
| " print(f\"Other benefits change (SNAP, etc.): ${f['other_benefits_change']/1e9:.2f}B\")\n", | |
| " print(f\"Net income change: ${f['net_income_change']/1e9:.2f}B\")\n", | |
| " print()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "2aa6031b", | |
| "metadata": {}, | |
| "source": [ | |
| "## Summary table" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "id": "5db7cae4", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-01-31T20:32:39.547771Z", | |
| "iopub.status.busy": "2026-01-31T20:32:39.547627Z", | |
| "iopub.status.idle": "2026-01-31T20:32:39.553932Z", | |
| "shell.execute_reply": "2026-01-31T20:32:39.553647Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Metric</th>\n", | |
| " <th>Baseline</th>\n", | |
| " <th>Repeal UI</th>\n", | |
| " <th>Double UI</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>0</th>\n", | |
| " <td>Child poverty rate</td>\n", | |
| " <td>22.20%</td>\n", | |
| " <td>22.42%</td>\n", | |
| " <td>22.14%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>1</th>\n", | |
| " <td>Change vs baseline (pp)</td>\n", | |
| " <td>-</td>\n", | |
| " <td>+0.22%</td>\n", | |
| " <td>-0.06%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2</th>\n", | |
| " <td>Change vs baseline (%)</td>\n", | |
| " <td>-</td>\n", | |
| " <td>+1.0%</td>\n", | |
| " <td>-0.3%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>3</th>\n", | |
| " <td>Children affected</td>\n", | |
| " <td>-</td>\n", | |
| " <td>+159,849 into poverty</td>\n", | |
| " <td>41,023 lifted from poverty</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>4</th>\n", | |
| " <td>UI outlays change ($B)</td>\n", | |
| " <td>-</td>\n", | |
| " <td>$-41.6B</td>\n", | |
| " <td>$41.6B</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>5</th>\n", | |
| " <td>Federal tax change ($B)</td>\n", | |
| " <td>-</td>\n", | |
| " <td>$-5.9B</td>\n", | |
| " <td>$7.1B</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>6</th>\n", | |
| " <td>State/local tax change ($B)</td>\n", | |
| " <td>-</td>\n", | |
| " <td>$-1.1B</td>\n", | |
| " <td>$1.1B</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>7</th>\n", | |
| " <td>Other benefits change ($B)</td>\n", | |
| " <td>-</td>\n", | |
| " <td>$0.7B</td>\n", | |
| " <td>$-0.5B</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>8</th>\n", | |
| " <td>Net income change ($B)</td>\n", | |
| " <td>-</td>\n", | |
| " <td>$-33.9B</td>\n", | |
| " <td>$32.9B</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Metric Baseline Repeal UI \\\n", | |
| "0 Child poverty rate 22.20% 22.42% \n", | |
| "1 Change vs baseline (pp) - +0.22% \n", | |
| "2 Change vs baseline (%) - +1.0% \n", | |
| "3 Children affected - +159,849 into poverty \n", | |
| "4 UI outlays change ($B) - $-41.6B \n", | |
| "5 Federal tax change ($B) - $-5.9B \n", | |
| "6 State/local tax change ($B) - $-1.1B \n", | |
| "7 Other benefits change ($B) - $0.7B \n", | |
| "8 Net income change ($B) - $-33.9B \n", | |
| "\n", | |
| " Double UI \n", | |
| "0 22.14% \n", | |
| "1 -0.06% \n", | |
| "2 -0.3% \n", | |
| "3 41,023 lifted from poverty \n", | |
| "4 $41.6B \n", | |
| "5 $7.1B \n", | |
| "6 $1.1B \n", | |
| "7 $-0.5B \n", | |
| "8 $32.9B " | |
| ] | |
| }, | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "summary = pd.DataFrame({\n", | |
| " \"Metric\": [\n", | |
| " \"Child poverty rate\",\n", | |
| " \"Change vs baseline (pp)\",\n", | |
| " \"Change vs baseline (%)\",\n", | |
| " \"Children affected\",\n", | |
| " \"UI outlays change ($B)\",\n", | |
| " \"Federal tax change ($B)\",\n", | |
| " \"State/local tax change ($B)\",\n", | |
| " \"Other benefits change ($B)\",\n", | |
| " \"Net income change ($B)\",\n", | |
| " ],\n", | |
| " \"Baseline\": [\n", | |
| " f\"{baseline_rate:.2%}\",\n", | |
| " \"-\",\n", | |
| " \"-\",\n", | |
| " \"-\",\n", | |
| " \"-\",\n", | |
| " \"-\",\n", | |
| " \"-\",\n", | |
| " \"-\",\n", | |
| " \"-\",\n", | |
| " ],\n", | |
| " \"Repeal UI\": [\n", | |
| " f\"{repeal_rate:.2%}\",\n", | |
| " f\"+{repeal_increase_pp:.2%}\",\n", | |
| " f\"+{repeal_increase_pct:.1%}\",\n", | |
| " f\"+{repeal_children_into_poverty:,.0f} into poverty\",\n", | |
| " f\"${repeal_fiscal['ui_change']/1e9:.1f}B\",\n", | |
| " f\"${repeal_fiscal['fed_tax_change']/1e9:.1f}B\",\n", | |
| " f\"${repeal_fiscal['state_tax_change']/1e9:.1f}B\",\n", | |
| " f\"${repeal_fiscal['other_benefits_change']/1e9:.1f}B\",\n", | |
| " f\"${repeal_fiscal['net_income_change']/1e9:.1f}B\",\n", | |
| " ],\n", | |
| " \"Double UI\": [\n", | |
| " f\"{doubled_rate:.2%}\",\n", | |
| " f\"-{doubled_reduction_pp:.2%}\",\n", | |
| " f\"-{doubled_reduction_pct:.1%}\",\n", | |
| " f\"{doubled_children_lifted:,.0f} lifted from poverty\",\n", | |
| " f\"${doubled_fiscal['ui_change']/1e9:.1f}B\",\n", | |
| " f\"${doubled_fiscal['fed_tax_change']/1e9:.1f}B\",\n", | |
| " f\"${doubled_fiscal['state_tax_change']/1e9:.1f}B\",\n", | |
| " f\"${doubled_fiscal['other_benefits_change']/1e9:.1f}B\",\n", | |
| " f\"${doubled_fiscal['net_income_change']/1e9:.1f}B\",\n", | |
| " ],\n", | |
| "})\n", | |
| "\n", | |
| "summary" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "id": "5dfe4060", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-01-31T20:32:39.555272Z", | |
| "iopub.status.busy": "2026-01-31T20:32:39.555192Z", | |
| "iopub.status.idle": "2026-01-31T20:32:39.557852Z", | |
| "shell.execute_reply": "2026-01-31T20:32:39.557392Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "PolicyEngine-US version: 1.525.0\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "from importlib.metadata import version\n", | |
| "print(f\"PolicyEngine-US version: {version('policyengine-us')}\")" | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "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.14.0" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 5 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment