diff --git a/dc_council_tax_reforms_2025_2026.ipynb b/dc_council_tax_reforms_2025_2026.ipynb new file mode 100644 index 0000000..df1765d --- /dev/null +++ b/dc_council_tax_reforms_2025_2026.ipynb @@ -0,0 +1,1183 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DC Council Tax Reforms Analysis (2025-2026)\n", + "\n", + "This notebook analyzes the tax reforms approved by the DC City Council:\n", + "\n", + "## Reform 1: EITC Enhancement (2025)\n", + "- Increase DC EITC match from 85% to 100% of federal EITC\n", + "- Effective: Tax year 2025\n", + "\n", + "## Reform 2: Child Tax Credit (2026)\n", + "- $1,000 per qualifying child under 18\n", + "- Income thresholds:\n", + " - Single/HOH/Widow: $55,000\n", + " - Joint filers: $70,000\n", + " - Married filing separately: $35,000\n", + "- Phase-out: $50 reduction per $1,000 over threshold\n", + "- Fully refundable\n", + "- Effective: Tax year 2026\n", + "\n", + "## Two Baseline Scenarios\n", + "\n", + "### Baseline A: Current Law\n", + "Keeps existing DC CTC ($420/child under 6, higher income thresholds)\n", + "\n", + "### Baseline B: Zeroed Out\n", + "Eliminates existing DC CTC (reflects budget removal before this amendment)\n", + "\n", + "## Analysis Structure\n", + "For each baseline:\n", + "1. 2025: EITC reform only\n", + "2. 2026: CTC reform only\n", + "3. 2026: Combined EITC + CTC impact" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper Functions for Impact Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": "def calculate_child_poverty(sim, period=2025):\n \"\"\"\n Calculate overall child poverty rate (children under 18).\n Returns poverty rate, count in poverty, and total children.\n \"\"\"\n # Get person-level data\n age = sim.calculate(\"age\", period=period)\n is_in_poverty = sim.calculate(\"person_in_poverty\", period=period)\n \n # Filter for children under 18\n mask = age < 18\n \n # Calculate poverty count and total children (unweighted)\n children_in_poverty = is_in_poverty[mask].sum()\n total_children = mask.sum()\n \n # Calculate poverty rate\n poverty_rate = children_in_poverty / total_children if total_children > 0 else 0\n \n return {\n \"poverty_rate\": poverty_rate,\n \"children_in_poverty\": children_in_poverty,\n \"total_children\": total_children\n }\n\ndef calculate_budgetary_impact(baseline_sim, reform_sim, variable, period=2025):\n \"\"\"\n Calculate the budgetary impact of a reform.\n \"\"\"\n baseline_value = baseline_sim.calculate(variable, period=period, map_to=\"household\").sum()\n reform_value = reform_sim.calculate(variable, period=period, map_to=\"household\").sum()\n \n return {\n \"baseline\": baseline_value,\n \"reform\": reform_value,\n \"net_cost\": reform_value - baseline_value\n }\n\ndef format_currency(value):\n \"\"\"Format value as currency in millions.\"\"\"\n return f\"${value/1e6:.2f}M\"\n\ndef format_percent(value):\n \"\"\"Format value as percentage.\"\"\"\n return f\"{value*100:.2f}%\"" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup Baselines" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading Baseline A: Current Law (keeps existing DC CTC)...\n", + " Current DC CTC cost: $16.70M\n", + " Baseline A loaded!\n" + ] + } + ], + "source": [ + "# Baseline A: Current Law (default - keeps existing DC CTC)\n", + "print(\"Loading Baseline A: Current Law (keeps existing DC CTC)...\")\n", + "baseline_current_law = Microsimulation(dataset='hf://policyengine/test/DC.h5')\n", + "\n", + "# Check current CTC cost\n", + "current_ctc = baseline_current_law.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "print(f\" Current DC CTC cost: {format_currency(current_ctc.sum())}\")\n", + "print(\" Baseline A loaded!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading Baseline B: Zeroed Out (eliminates existing DC CTC)...\n", + " Zeroed DC CTC cost: $0.00M\n", + " Baseline B loaded!\n" + ] + } + ], + "source": [ + "# Baseline B: Zeroed Out (eliminates existing DC CTC)\n", + "def create_zero_ctc_baseline():\n", + " \"\"\"Zero out the existing DC CTC (reflects budget removal)\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "print(\"Loading Baseline B: Zeroed Out (eliminates existing DC CTC)...\")\n", + "zero_ctc_reform = create_zero_ctc_baseline()\n", + "baseline_zeroed_out = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=zero_ctc_reform)\n", + "\n", + "# Verify CTC is zeroed out\n", + "zeroed_ctc = baseline_zeroed_out.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "print(f\" Zeroed DC CTC cost: {format_currency(zeroed_ctc.sum())}\")\n", + "print(\" Baseline B loaded!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define Reform Functions" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform functions defined!\n" + ] + } + ], + "source": [ + "def create_eitc_reform():\n", + " \"\"\"Increase DC EITC match from 85% to 100%\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.eitc.with_children.match\": {\n", + " \"2025-01-01.2100-12-31\": 1.0 # 100% match\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "def create_new_ctc_reform():\n", + " \"\"\"Create the new DC CTC as specified in the amendment\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " # Set amount to $1,000 per child\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2026-01-01.2100-12-31\": 1000\n", + " },\n", + " # Age threshold: under 18\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2026-01-01.2100-12-31\": 18\n", + " },\n", + " # No child cap (unlimited)\n", + " \"gov.states.dc.tax.income.credits.ctc.child.child_cap\": {\n", + " \"2026-01-01.2100-12-31\": 999\n", + " },\n", + " # Phase-out: $50 per $1,000 over threshold\n", + " \"gov.states.dc.tax.income.credits.ctc.phase_out.amount\": {\n", + " \"2026-01-01.2100-12-31\": 50\n", + " },\n", + " # Income thresholds by filing status\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2026-01-01.2100-12-31\": 70_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2026-01-01.2100-12-31\": 35_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "def create_combined_reform():\n", + " \"\"\"Create combined EITC + CTC reform\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " # EITC: 100% match\n", + " \"gov.states.dc.tax.income.credits.eitc.with_children.match\": {\n", + " \"2025-01-01.2100-12-31\": 1.0\n", + " },\n", + " # CTC: $1,000 per child\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2026-01-01.2100-12-31\": 1000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2026-01-01.2100-12-31\": 18\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.child_cap\": {\n", + " \"2026-01-01.2100-12-31\": 999\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.phase_out.amount\": {\n", + " \"2026-01-01.2100-12-31\": 50\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2026-01-01.2100-12-31\": 70_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2026-01-01.2100-12-31\": 35_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "def create_eitc_and_zero_ctc():\n", + " \"\"\"EITC enhancement + zero out CTC (for zeroed baseline scenario)\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " # EITC: 100% match\n", + " \"gov.states.dc.tax.income.credits.eitc.with_children.match\": {\n", + " \"2025-01-01.2100-12-31\": 1.0\n", + " },\n", + " # Zero out CTC\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "print(\"Reform functions defined!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BASELINE A: CURRENT LAW\n", + "\n", + "Analysis assuming the existing DC CTC ($420/child under 6) remains in place" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A1. EITC Reform (2025) vs Current Law" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating EITC reform simulation (current law baseline)...\n", + "Done!\n" + ] + } + ], + "source": [ + "print(\"Creating EITC reform simulation (current law baseline)...\")\n", + "eitc_reform = create_eitc_reform()\n", + "eitc_reform_currentlaw = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=eitc_reform)\n", + "print(\"Done!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "BASELINE A - EITC REFORM IMPACTS (2025)\n", + "================================================================================\n", + "\n", + "EITC Budgetary Impact:\n", + " Baseline DC EITC cost: $57.63M\n", + " Reform DC EITC cost: $64.15M\n", + " Net cost: $6.52M\n", + "\n", + "CTC Budgetary Impact (unchanged):\n", + " DC CTC cost: $16.70M\n", + "\n", + "Poverty Impact (Children Under 18):\n", + " Baseline poverty rate: 28.71%\n", + " Reform poverty rate: 28.71%\n", + " Absolute reduction: 0.00%\n", + " Relative reduction: 0.00%\n", + " Children lifted out: 0\n" + ] + } + ], + "source": [ + "print(\"=\" * 80)\n", + "print(\"BASELINE A - EITC REFORM IMPACTS (2025)\")\n", + "print(\"=\" * 80)\n", + "\n", + "# Budgetary impact\n", + "a1_eitc_budget = calculate_budgetary_impact(baseline_current_law, eitc_reform_currentlaw, \"dc_eitc\", period=2025)\n", + "print(f\"\\nEITC Budgetary Impact:\")\n", + "print(f\" Baseline DC EITC cost: {format_currency(a1_eitc_budget['baseline'])}\")\n", + "print(f\" Reform DC EITC cost: {format_currency(a1_eitc_budget['reform'])}\")\n", + "print(f\" Net cost: {format_currency(a1_eitc_budget['net_cost'])}\")\n", + "\n", + "# CTC remains unchanged in 2025\n", + "a1_ctc_budget = calculate_budgetary_impact(baseline_current_law, eitc_reform_currentlaw, \"dc_ctc\", period=2025)\n", + "print(f\"\\nCTC Budgetary Impact (unchanged):\")\n", + "print(f\" DC CTC cost: {format_currency(a1_ctc_budget['baseline'])}\")\n", + "\n", + "# Poverty impact\n", + "a1_baseline_poverty = calculate_child_poverty(baseline_current_law, period=2025)\n", + "a1_eitc_poverty = calculate_child_poverty(eitc_reform_currentlaw, period=2025)\n", + "\n", + "a1_poverty_reduction = a1_baseline_poverty['poverty_rate'] - a1_eitc_poverty['poverty_rate']\n", + "a1_poverty_pct_reduction = (a1_poverty_reduction / a1_baseline_poverty['poverty_rate']) * 100\n", + "\n", + "print(f\"\\nPoverty Impact (Children Under 18):\")\n", + "print(f\" Baseline poverty rate: {format_percent(a1_baseline_poverty['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(a1_eitc_poverty['poverty_rate'])}\")\n", + "print(f\" Absolute reduction: {format_percent(a1_poverty_reduction)}\")\n", + "print(f\" Relative reduction: {a1_poverty_pct_reduction:.2f}%\")\n", + "print(f\" Children lifted out: {int(a1_baseline_poverty['children_in_poverty'] - a1_eitc_poverty['children_in_poverty']):,}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A2. New CTC Only (2026) vs Current Law" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating new CTC reform simulation (current law baseline)...\n", + "Done!\n" + ] + } + ], + "source": [ + "print(\"Creating new CTC reform simulation (current law baseline)...\")\n", + "new_ctc_reform = create_new_ctc_reform()\n", + "new_ctc_reform_currentlaw = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=new_ctc_reform)\n", + "print(\"Done!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "BASELINE A - NEW CTC REFORM IMPACTS (2026) - CTC Only\n", + "================================================================================\n", + "\n", + "EITC Budgetary Impact (unchanged at 85%):\n", + " DC EITC cost: $57.78M\n", + "\n", + "CTC Budgetary Impact:\n", + " Baseline DC CTC cost: $16.82M (old CTC: $420, under 6)\n", + " Reform DC CTC cost: $85.78M (new CTC: $1000, under 18)\n", + " Net cost: $68.96M\n", + "\n", + "Poverty Impact (Children Under 18):\n", + " Baseline poverty rate: 28.29%\n", + " Reform poverty rate: 27.69%\n", + " Absolute reduction: 0.60%\n", + " Relative reduction: 2.11%\n", + " Children lifted out: 223,716\n" + ] + } + ], + "source": [ + "print(\"=\" * 80)\n", + "print(\"BASELINE A - NEW CTC REFORM IMPACTS (2026) - CTC Only\")\n", + "print(\"=\" * 80)\n", + "\n", + "# Budgetary impact - EITC (baseline 85%)\n", + "a2_eitc_budget = calculate_budgetary_impact(baseline_current_law, new_ctc_reform_currentlaw, \"dc_eitc\", period=2026)\n", + "print(f\"\\nEITC Budgetary Impact (unchanged at 85%):\")\n", + "print(f\" DC EITC cost: {format_currency(a2_eitc_budget['baseline'])}\")\n", + "\n", + "# Budgetary impact - CTC\n", + "a2_ctc_budget = calculate_budgetary_impact(baseline_current_law, new_ctc_reform_currentlaw, \"dc_ctc\", period=2026)\n", + "print(f\"\\nCTC Budgetary Impact:\")\n", + "print(f\" Baseline DC CTC cost: {format_currency(a2_ctc_budget['baseline'])} (old CTC: $420, under 6)\")\n", + "print(f\" Reform DC CTC cost: {format_currency(a2_ctc_budget['reform'])} (new CTC: $1000, under 18)\")\n", + "print(f\" Net cost: {format_currency(a2_ctc_budget['net_cost'])}\")\n", + "\n", + "# Poverty impact\n", + "a2_baseline_poverty = calculate_child_poverty(baseline_current_law, period=2026)\n", + "a2_ctc_poverty = calculate_child_poverty(new_ctc_reform_currentlaw, period=2026)\n", + "\n", + "a2_poverty_reduction = a2_baseline_poverty['poverty_rate'] - a2_ctc_poverty['poverty_rate']\n", + "a2_poverty_pct_reduction = (a2_poverty_reduction / a2_baseline_poverty['poverty_rate']) * 100\n", + "\n", + "print(f\"\\nPoverty Impact (Children Under 18):\")\n", + "print(f\" Baseline poverty rate: {format_percent(a2_baseline_poverty['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(a2_ctc_poverty['poverty_rate'])}\")\n", + "print(f\" Absolute reduction: {format_percent(a2_poverty_reduction)}\")\n", + "print(f\" Relative reduction: {a2_poverty_pct_reduction:.2f}%\")\n", + "print(f\" Children lifted out: {int(a2_baseline_poverty['children_in_poverty'] - a2_ctc_poverty['children_in_poverty']):,}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A3. Combined EITC + New CTC (2026) vs Current Law" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating combined EITC + CTC reform simulation (current law baseline)...\n", + "Done!\n" + ] + } + ], + "source": [ + "print(\"Creating combined EITC + CTC reform simulation (current law baseline)...\")\n", + "combined_reform = create_combined_reform()\n", + "combined_reform_currentlaw = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=combined_reform)\n", + "print(\"Done!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "BASELINE A - COMBINED REFORM IMPACTS (2026) - EITC + CTC\n", + "================================================================================\n", + "\n", + "EITC Budgetary Impact:\n", + " Baseline DC EITC cost: $57.78M (85% match)\n", + " Reform DC EITC cost: $64.33M (100% match)\n", + " Net cost: $6.55M\n", + "\n", + "CTC Budgetary Impact:\n", + " Baseline DC CTC cost: $16.82M (old CTC: $420, under 6)\n", + " Reform DC CTC cost: $85.78M (new CTC: $1000, under 18)\n", + " Net cost: $68.96M\n", + "\n", + "Total Combined Net Cost: $75.51M\n", + "\n", + "Poverty Impact (Children Under 18):\n", + " Baseline poverty rate: 28.29%\n", + " Reform poverty rate: 27.69%\n", + " Absolute reduction: 0.60%\n", + " Relative reduction: 2.11%\n", + " Children lifted out: 223,716\n" + ] + } + ], + "source": [ + "print(\"=\" * 80)\n", + "print(\"BASELINE A - COMBINED REFORM IMPACTS (2026) - EITC + CTC\")\n", + "print(\"=\" * 80)\n", + "\n", + "# Budgetary impact - EITC\n", + "a3_eitc_budget = calculate_budgetary_impact(baseline_current_law, combined_reform_currentlaw, \"dc_eitc\", period=2026)\n", + "print(f\"\\nEITC Budgetary Impact:\")\n", + "print(f\" Baseline DC EITC cost: {format_currency(a3_eitc_budget['baseline'])} (85% match)\")\n", + "print(f\" Reform DC EITC cost: {format_currency(a3_eitc_budget['reform'])} (100% match)\")\n", + "print(f\" Net cost: {format_currency(a3_eitc_budget['net_cost'])}\")\n", + "\n", + "# Budgetary impact - CTC\n", + "a3_ctc_budget = calculate_budgetary_impact(baseline_current_law, combined_reform_currentlaw, \"dc_ctc\", period=2026)\n", + "print(f\"\\nCTC Budgetary Impact:\")\n", + "print(f\" Baseline DC CTC cost: {format_currency(a3_ctc_budget['baseline'])} (old CTC: $420, under 6)\")\n", + "print(f\" Reform DC CTC cost: {format_currency(a3_ctc_budget['reform'])} (new CTC: $1000, under 18)\")\n", + "print(f\" Net cost: {format_currency(a3_ctc_budget['net_cost'])}\")\n", + "\n", + "# Total budgetary impact\n", + "a3_total_cost = a3_eitc_budget['net_cost'] + a3_ctc_budget['net_cost']\n", + "print(f\"\\nTotal Combined Net Cost: {format_currency(a3_total_cost)}\")\n", + "\n", + "# Poverty impact\n", + "a3_baseline_poverty = calculate_child_poverty(baseline_current_law, period=2026)\n", + "a3_combined_poverty = calculate_child_poverty(combined_reform_currentlaw, period=2026)\n", + "\n", + "a3_poverty_reduction = a3_baseline_poverty['poverty_rate'] - a3_combined_poverty['poverty_rate']\n", + "a3_poverty_pct_reduction = (a3_poverty_reduction / a3_baseline_poverty['poverty_rate']) * 100\n", + "\n", + "print(f\"\\nPoverty Impact (Children Under 18):\")\n", + "print(f\" Baseline poverty rate: {format_percent(a3_baseline_poverty['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(a3_combined_poverty['poverty_rate'])}\")\n", + "print(f\" Absolute reduction: {format_percent(a3_poverty_reduction)}\")\n", + "print(f\" Relative reduction: {a3_poverty_pct_reduction:.2f}%\")\n", + "print(f\" Children lifted out: {int(a3_baseline_poverty['children_in_poverty'] - a3_combined_poverty['children_in_poverty']):,}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BASELINE B: ZEROED OUT\n", + "\n", + "Analysis assuming the existing DC CTC was eliminated (as in the recent budget)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## B1. EITC Reform (2025) vs Zeroed Out Baseline" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating EITC reform simulation (zeroed out baseline)...\n", + "Done!\n" + ] + } + ], + "source": [ + "print(\"Creating EITC reform simulation (zeroed out baseline)...\")\n", + "eitc_and_zero_reform = create_eitc_and_zero_ctc()\n", + "eitc_reform_zeroed = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=eitc_and_zero_reform)\n", + "print(\"Done!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "BASELINE B - EITC REFORM IMPACTS (2025)\n", + "================================================================================\n", + "\n", + "EITC Budgetary Impact:\n", + " Baseline DC EITC cost: $57.63M\n", + " Reform DC EITC cost: $64.15M\n", + " Net cost: $6.52M\n", + "\n", + "CTC Budgetary Impact (eliminated):\n", + " DC CTC cost: $0.00M\n", + "\n", + "Poverty Impact (Children Under 18):\n", + " Baseline poverty rate: 28.71%\n", + " Reform poverty rate: 28.71%\n", + " Absolute reduction: 0.00%\n", + " Relative reduction: 0.00%\n", + " Children lifted out: 0\n" + ] + } + ], + "source": [ + "print(\"=\" * 80)\n", + "print(\"BASELINE B - EITC REFORM IMPACTS (2025)\")\n", + "print(\"=\" * 80)\n", + "\n", + "# Budgetary impact\n", + "b1_eitc_budget = calculate_budgetary_impact(baseline_zeroed_out, eitc_reform_zeroed, \"dc_eitc\", period=2025)\n", + "print(f\"\\nEITC Budgetary Impact:\")\n", + "print(f\" Baseline DC EITC cost: {format_currency(b1_eitc_budget['baseline'])}\")\n", + "print(f\" Reform DC EITC cost: {format_currency(b1_eitc_budget['reform'])}\")\n", + "print(f\" Net cost: {format_currency(b1_eitc_budget['net_cost'])}\")\n", + "\n", + "# CTC is zero in both scenarios\n", + "b1_ctc_budget = calculate_budgetary_impact(baseline_zeroed_out, eitc_reform_zeroed, \"dc_ctc\", period=2025)\n", + "print(f\"\\nCTC Budgetary Impact (eliminated):\")\n", + "print(f\" DC CTC cost: {format_currency(b1_ctc_budget['baseline'])}\")\n", + "\n", + "# Poverty impact\n", + "b1_baseline_poverty = calculate_child_poverty(baseline_zeroed_out, period=2025)\n", + "b1_eitc_poverty = calculate_child_poverty(eitc_reform_zeroed, period=2025)\n", + "\n", + "b1_poverty_reduction = b1_baseline_poverty['poverty_rate'] - b1_eitc_poverty['poverty_rate']\n", + "b1_poverty_pct_reduction = (b1_poverty_reduction / b1_baseline_poverty['poverty_rate']) * 100\n", + "\n", + "print(f\"\\nPoverty Impact (Children Under 18):\")\n", + "print(f\" Baseline poverty rate: {format_percent(b1_baseline_poverty['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(b1_eitc_poverty['poverty_rate'])}\")\n", + "print(f\" Absolute reduction: {format_percent(b1_poverty_reduction)}\")\n", + "print(f\" Relative reduction: {b1_poverty_pct_reduction:.2f}%\")\n", + "print(f\" Children lifted out: {int(b1_baseline_poverty['children_in_poverty'] - b1_eitc_poverty['children_in_poverty']):,}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## B2. New CTC Only (2026) vs Zeroed Out Baseline" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating new CTC reform simulation (zeroed out baseline)...\n", + "Done!\n" + ] + } + ], + "source": [ + "print(\"Creating new CTC reform simulation (zeroed out baseline)...\")\n", + "# Apply the new CTC reform directly (it will overwrite the zeroed CTC)\n", + "new_ctc_reform_zeroed = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=new_ctc_reform)\n", + "print(\"Done!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "BASELINE B - NEW CTC REFORM IMPACTS (2026) - CTC Only\n", + "================================================================================\n", + "\n", + "EITC Budgetary Impact (unchanged at 85%):\n", + " DC EITC cost: $57.78M\n", + "\n", + "CTC Budgetary Impact:\n", + " Baseline DC CTC cost: $0.00M (eliminated)\n", + " Reform DC CTC cost: $85.78M (new CTC: $1000, under 18)\n", + " Net cost: $85.78M\n", + "\n", + "Poverty Impact (Children Under 18):\n", + " Baseline poverty rate: 28.29%\n", + " Reform poverty rate: 27.69%\n", + " Absolute reduction: 0.60%\n", + " Relative reduction: 2.11%\n", + " Children lifted out: 223,716\n" + ] + } + ], + "source": [ + "print(\"=\" * 80)\n", + "print(\"BASELINE B - NEW CTC REFORM IMPACTS (2026) - CTC Only\")\n", + "print(\"=\" * 80)\n", + "\n", + "# Budgetary impact - EITC (baseline 85%, unchanged)\n", + "b2_eitc_budget = calculate_budgetary_impact(baseline_zeroed_out, new_ctc_reform_zeroed, \"dc_eitc\", period=2026)\n", + "print(f\"\\nEITC Budgetary Impact (unchanged at 85%):\")\n", + "print(f\" DC EITC cost: {format_currency(b2_eitc_budget['baseline'])}\")\n", + "\n", + "# Budgetary impact - CTC\n", + "b2_ctc_budget = calculate_budgetary_impact(baseline_zeroed_out, new_ctc_reform_zeroed, \"dc_ctc\", period=2026)\n", + "print(f\"\\nCTC Budgetary Impact:\")\n", + "print(f\" Baseline DC CTC cost: {format_currency(b2_ctc_budget['baseline'])} (eliminated)\")\n", + "print(f\" Reform DC CTC cost: {format_currency(b2_ctc_budget['reform'])} (new CTC: $1000, under 18)\")\n", + "print(f\" Net cost: {format_currency(b2_ctc_budget['net_cost'])}\")\n", + "\n", + "# Poverty impact\n", + "b2_baseline_poverty = calculate_child_poverty(baseline_zeroed_out, period=2026)\n", + "b2_ctc_poverty = calculate_child_poverty(new_ctc_reform_zeroed, period=2026)\n", + "\n", + "b2_poverty_reduction = b2_baseline_poverty['poverty_rate'] - b2_ctc_poverty['poverty_rate']\n", + "b2_poverty_pct_reduction = (b2_poverty_reduction / b2_baseline_poverty['poverty_rate']) * 100\n", + "\n", + "print(f\"\\nPoverty Impact (Children Under 18):\")\n", + "print(f\" Baseline poverty rate: {format_percent(b2_baseline_poverty['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(b2_ctc_poverty['poverty_rate'])}\")\n", + "print(f\" Absolute reduction: {format_percent(b2_poverty_reduction)}\")\n", + "print(f\" Relative reduction: {b2_poverty_pct_reduction:.2f}%\")\n", + "print(f\" Children lifted out: {int(b2_baseline_poverty['children_in_poverty'] - b2_ctc_poverty['children_in_poverty']):,}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## B3. Combined EITC + New CTC (2026) vs Zeroed Out Baseline" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating combined EITC + CTC reform simulation (zeroed out baseline)...\n", + "Done!\n" + ] + } + ], + "source": [ + "print(\"Creating combined EITC + CTC reform simulation (zeroed out baseline)...\")\n", + "# Apply the combined reform directly (it will set all parameters)\n", + "combined_reform_zeroed = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=combined_reform)\n", + "print(\"Done!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================================================================================\n", + "BASELINE B - COMBINED REFORM IMPACTS (2026) - EITC + CTC\n", + "================================================================================\n", + "\n", + "EITC Budgetary Impact:\n", + " Baseline DC EITC cost: $57.78M (85% match)\n", + " Reform DC EITC cost: $64.33M (100% match)\n", + " Net cost: $6.55M\n", + "\n", + "CTC Budgetary Impact:\n", + " Baseline DC CTC cost: $0.00M (eliminated)\n", + " Reform DC CTC cost: $85.78M (new CTC: $1000, under 18)\n", + " Net cost: $85.78M\n", + "\n", + "Total Combined Net Cost: $92.33M\n", + "\n", + "Poverty Impact (Children Under 18):\n", + " Baseline poverty rate: 28.29%\n", + " Reform poverty rate: 27.69%\n", + " Absolute reduction: 0.60%\n", + " Relative reduction: 2.11%\n", + " Children lifted out: 223,716\n" + ] + } + ], + "source": [ + "print(\"=\" * 80)\n", + "print(\"BASELINE B - COMBINED REFORM IMPACTS (2026) - EITC + CTC\")\n", + "print(\"=\" * 80)\n", + "\n", + "# Budgetary impact - EITC\n", + "b3_eitc_budget = calculate_budgetary_impact(baseline_zeroed_out, combined_reform_zeroed, \"dc_eitc\", period=2026)\n", + "print(f\"\\nEITC Budgetary Impact:\")\n", + "print(f\" Baseline DC EITC cost: {format_currency(b3_eitc_budget['baseline'])} (85% match)\")\n", + "print(f\" Reform DC EITC cost: {format_currency(b3_eitc_budget['reform'])} (100% match)\")\n", + "print(f\" Net cost: {format_currency(b3_eitc_budget['net_cost'])}\")\n", + "\n", + "# Budgetary impact - CTC\n", + "b3_ctc_budget = calculate_budgetary_impact(baseline_zeroed_out, combined_reform_zeroed, \"dc_ctc\", period=2026)\n", + "print(f\"\\nCTC Budgetary Impact:\")\n", + "print(f\" Baseline DC CTC cost: {format_currency(b3_ctc_budget['baseline'])} (eliminated)\")\n", + "print(f\" Reform DC CTC cost: {format_currency(b3_ctc_budget['reform'])} (new CTC: $1000, under 18)\")\n", + "print(f\" Net cost: {format_currency(b3_ctc_budget['net_cost'])}\")\n", + "\n", + "# Total budgetary impact\n", + "b3_total_cost = b3_eitc_budget['net_cost'] + b3_ctc_budget['net_cost']\n", + "print(f\"\\nTotal Combined Net Cost: {format_currency(b3_total_cost)}\")\n", + "\n", + "# Poverty impact\n", + "b3_baseline_poverty = calculate_child_poverty(baseline_zeroed_out, period=2026)\n", + "b3_combined_poverty = calculate_child_poverty(combined_reform_zeroed, period=2026)\n", + "\n", + "b3_poverty_reduction = b3_baseline_poverty['poverty_rate'] - b3_combined_poverty['poverty_rate']\n", + "b3_poverty_pct_reduction = (b3_poverty_reduction / b3_baseline_poverty['poverty_rate']) * 100\n", + "\n", + "print(f\"\\nPoverty Impact (Children Under 18):\")\n", + "print(f\" Baseline poverty rate: {format_percent(b3_baseline_poverty['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(b3_combined_poverty['poverty_rate'])}\")\n", + "print(f\" Absolute reduction: {format_percent(b3_poverty_reduction)}\")\n", + "print(f\" Relative reduction: {b3_poverty_pct_reduction:.2f}%\")\n", + "print(f\" Children lifted out: {int(b3_baseline_poverty['children_in_poverty'] - b3_combined_poverty['children_in_poverty']):,}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# COMPREHENSIVE SUMMARY TABLES" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Summary: Baseline A (Current Law)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "========================================================================================================================\n", + "BASELINE A SUMMARY: Current Law (existing CTC $420/child under 6 remains)\n", + "========================================================================================================================\n", + " Scenario Year EITC Cost CTC Cost Total Cost Child Poverty Rate Children in Poverty\n", + " Baseline 2025 $57.63M $16.70M $74.33M 28.71% 10,626,794\n", + " EITC Reform 2025 $64.15M $16.70M $80.85M 28.71% 10,626,794\n", + " Baseline 2026 $57.78M $16.82M $74.60M 28.29% 10,620,556\n", + "New CTC Only 2026 $57.78M $85.78M $143.56M 27.69% 10,396,840\n", + " EITC + CTC 2026 $64.33M $85.78M $150.10M 27.69% 10,396,840\n", + "\n", + "Exported to: dc_reforms_baseline_a_current_law.csv\n" + ] + } + ], + "source": [ + "summary_a_data = [\n", + " {\n", + " \"Scenario\": \"Baseline\",\n", + " \"Year\": \"2025\",\n", + " \"EITC Cost\": format_currency(a1_eitc_budget['baseline']),\n", + " \"CTC Cost\": format_currency(a1_ctc_budget['baseline']),\n", + " \"Total Cost\": format_currency(a1_eitc_budget['baseline'] + a1_ctc_budget['baseline']),\n", + " \"Child Poverty Rate\": format_percent(a1_baseline_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(a1_baseline_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"EITC Reform\",\n", + " \"Year\": \"2025\",\n", + " \"EITC Cost\": format_currency(a1_eitc_budget['reform']),\n", + " \"CTC Cost\": format_currency(a1_ctc_budget['baseline']),\n", + " \"Total Cost\": format_currency(a1_eitc_budget['reform'] + a1_ctc_budget['baseline']),\n", + " \"Child Poverty Rate\": format_percent(a1_eitc_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(a1_eitc_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"Baseline\",\n", + " \"Year\": \"2026\",\n", + " \"EITC Cost\": format_currency(a2_eitc_budget['baseline']),\n", + " \"CTC Cost\": format_currency(a2_ctc_budget['baseline']),\n", + " \"Total Cost\": format_currency(a2_eitc_budget['baseline'] + a2_ctc_budget['baseline']),\n", + " \"Child Poverty Rate\": format_percent(a2_baseline_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(a2_baseline_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"New CTC Only\",\n", + " \"Year\": \"2026\",\n", + " \"EITC Cost\": format_currency(a2_eitc_budget['baseline']),\n", + " \"CTC Cost\": format_currency(a2_ctc_budget['reform']),\n", + " \"Total Cost\": format_currency(a2_eitc_budget['baseline'] + a2_ctc_budget['reform']),\n", + " \"Child Poverty Rate\": format_percent(a2_ctc_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(a2_ctc_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"EITC + CTC\",\n", + " \"Year\": \"2026\",\n", + " \"EITC Cost\": format_currency(a3_eitc_budget['reform']),\n", + " \"CTC Cost\": format_currency(a3_ctc_budget['reform']),\n", + " \"Total Cost\": format_currency(a3_eitc_budget['reform'] + a3_ctc_budget['reform']),\n", + " \"Child Poverty Rate\": format_percent(a3_combined_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(a3_combined_poverty['children_in_poverty']):,}\"\n", + " }\n", + "]\n", + "\n", + "summary_a_df = pd.DataFrame(summary_a_data)\n", + "\n", + "print(\"\\n\" + \"=\" * 120)\n", + "print(\"BASELINE A SUMMARY: Current Law (existing CTC $420/child under 6 remains)\")\n", + "print(\"=\" * 120)\n", + "print(summary_a_df.to_string(index=False))\n", + "\n", + "summary_a_df.to_csv(\"dc_reforms_baseline_a_current_law.csv\", index=False)\n", + "print(\"\\nExported to: dc_reforms_baseline_a_current_law.csv\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Summary: Baseline B (Zeroed Out)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "========================================================================================================================\n", + "BASELINE B SUMMARY: Zeroed Out (existing CTC eliminated in budget)\n", + "========================================================================================================================\n", + " Scenario Year EITC Cost CTC Cost Total Cost Child Poverty Rate Children in Poverty\n", + " Baseline 2025 $57.63M $0.00M $57.63M 28.71% 10,626,794\n", + " EITC Reform 2025 $64.15M $0.00M $64.15M 28.71% 10,626,794\n", + " Baseline 2026 $57.78M $0.00M $57.78M 28.29% 10,620,556\n", + "New CTC Only 2026 $57.78M $85.78M $143.56M 27.69% 10,396,840\n", + " EITC + CTC 2026 $64.33M $85.78M $150.10M 27.69% 10,396,840\n", + "\n", + "Exported to: dc_reforms_baseline_b_zeroed_out.csv\n" + ] + } + ], + "source": [ + "summary_b_data = [\n", + " {\n", + " \"Scenario\": \"Baseline\",\n", + " \"Year\": \"2025\",\n", + " \"EITC Cost\": format_currency(b1_eitc_budget['baseline']),\n", + " \"CTC Cost\": format_currency(b1_ctc_budget['baseline']),\n", + " \"Total Cost\": format_currency(b1_eitc_budget['baseline'] + b1_ctc_budget['baseline']),\n", + " \"Child Poverty Rate\": format_percent(b1_baseline_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(b1_baseline_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"EITC Reform\",\n", + " \"Year\": \"2025\",\n", + " \"EITC Cost\": format_currency(b1_eitc_budget['reform']),\n", + " \"CTC Cost\": format_currency(b1_ctc_budget['baseline']),\n", + " \"Total Cost\": format_currency(b1_eitc_budget['reform'] + b1_ctc_budget['baseline']),\n", + " \"Child Poverty Rate\": format_percent(b1_eitc_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(b1_eitc_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"Baseline\",\n", + " \"Year\": \"2026\",\n", + " \"EITC Cost\": format_currency(b2_eitc_budget['baseline']),\n", + " \"CTC Cost\": format_currency(b2_ctc_budget['baseline']),\n", + " \"Total Cost\": format_currency(b2_eitc_budget['baseline'] + b2_ctc_budget['baseline']),\n", + " \"Child Poverty Rate\": format_percent(b2_baseline_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(b2_baseline_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"New CTC Only\",\n", + " \"Year\": \"2026\",\n", + " \"EITC Cost\": format_currency(b2_eitc_budget['baseline']),\n", + " \"CTC Cost\": format_currency(b2_ctc_budget['reform']),\n", + " \"Total Cost\": format_currency(b2_eitc_budget['baseline'] + b2_ctc_budget['reform']),\n", + " \"Child Poverty Rate\": format_percent(b2_ctc_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(b2_ctc_poverty['children_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"EITC + CTC\",\n", + " \"Year\": \"2026\",\n", + " \"EITC Cost\": format_currency(b3_eitc_budget['reform']),\n", + " \"CTC Cost\": format_currency(b3_ctc_budget['reform']),\n", + " \"Total Cost\": format_currency(b3_eitc_budget['reform'] + b3_ctc_budget['reform']),\n", + " \"Child Poverty Rate\": format_percent(b3_combined_poverty['poverty_rate']),\n", + " \"Children in Poverty\": f\"{int(b3_combined_poverty['children_in_poverty']):,}\"\n", + " }\n", + "]\n", + "\n", + "summary_b_df = pd.DataFrame(summary_b_data)\n", + "\n", + "print(\"\\n\" + \"=\" * 120)\n", + "print(\"BASELINE B SUMMARY: Zeroed Out (existing CTC eliminated in budget)\")\n", + "print(\"=\" * 120)\n", + "print(summary_b_df.to_string(index=False))\n", + "\n", + "summary_b_df.to_csv(\"dc_reforms_baseline_b_zeroed_out.csv\", index=False)\n", + "print(\"\\nExported to: dc_reforms_baseline_b_zeroed_out.csv\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Net Cost Comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "========================================================================================================================\n", + "NET COST ANALYSIS\n", + "========================================================================================================================\n", + "\n", + "============================================================\n", + "BASELINE A: Relative to Current Law\n", + "============================================================\n", + "\n", + "2025 - EITC Enhancement:\n", + " EITC net cost: $6.52M\n", + " CTC net cost: $0.00M (unchanged)\n", + " Total: $6.52M\n", + "\n", + "2026 - New CTC Only:\n", + " EITC net cost: $0.00M (unchanged at 85%)\n", + " CTC net cost: $68.96M\n", + " Total: $68.96M\n", + "\n", + "2026 - Combined EITC + CTC:\n", + " EITC net cost: $6.55M\n", + " CTC net cost: $68.96M\n", + " Total: $75.51M\n", + "\n", + "============================================================\n", + "BASELINE B: Relative to Zeroed Out CTC\n", + "============================================================\n", + "\n", + "2025 - EITC Enhancement:\n", + " EITC net cost: $6.52M\n", + " CTC net cost: $0.00M (remains eliminated)\n", + " Total: $6.52M\n", + "\n", + "2026 - New CTC Only:\n", + " EITC net cost: $0.00M (unchanged at 85%)\n", + " CTC net cost: $85.78M\n", + " Total: $85.78M\n", + "\n", + "2026 - Combined EITC + CTC:\n", + " EITC net cost: $6.55M\n", + " CTC net cost: $85.78M\n", + " Total: $92.33M\n", + "\n", + "============================================================\n", + "Comparison to DC Council Estimates\n", + "============================================================\n", + "\n", + "FY26 (2025) EITC:\n", + " Council estimate: $17.42M\n", + " Our estimate: $6.52M\n", + "\n", + "FY27 (2026) CTC (vs zeroed baseline):\n", + " Council estimate: $55.26M\n", + " Our estimate: $85.78M\n" + ] + } + ], + "source": [ + "print(\"\\n\" + \"=\" * 120)\n", + "print(\"NET COST ANALYSIS\")\n", + "print(\"=\" * 120)\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"BASELINE A: Relative to Current Law\")\n", + "print(\"=\"*60)\n", + "print(f\"\\n2025 - EITC Enhancement:\")\n", + "print(f\" EITC net cost: {format_currency(a1_eitc_budget['net_cost'])}\")\n", + "print(f\" CTC net cost: $0.00M (unchanged)\")\n", + "print(f\" Total: {format_currency(a1_eitc_budget['net_cost'])}\")\n", + "\n", + "print(f\"\\n2026 - New CTC Only:\")\n", + "print(f\" EITC net cost: $0.00M (unchanged at 85%)\")\n", + "print(f\" CTC net cost: {format_currency(a2_ctc_budget['net_cost'])}\")\n", + "print(f\" Total: {format_currency(a2_ctc_budget['net_cost'])}\")\n", + "\n", + "print(f\"\\n2026 - Combined EITC + CTC:\")\n", + "print(f\" EITC net cost: {format_currency(a3_eitc_budget['net_cost'])}\")\n", + "print(f\" CTC net cost: {format_currency(a3_ctc_budget['net_cost'])}\")\n", + "print(f\" Total: {format_currency(a3_total_cost)}\")\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"BASELINE B: Relative to Zeroed Out CTC\")\n", + "print(\"=\"*60)\n", + "print(f\"\\n2025 - EITC Enhancement:\")\n", + "print(f\" EITC net cost: {format_currency(b1_eitc_budget['net_cost'])}\")\n", + "print(f\" CTC net cost: $0.00M (remains eliminated)\")\n", + "print(f\" Total: {format_currency(b1_eitc_budget['net_cost'])}\")\n", + "\n", + "print(f\"\\n2026 - New CTC Only:\")\n", + "print(f\" EITC net cost: $0.00M (unchanged at 85%)\")\n", + "print(f\" CTC net cost: {format_currency(b2_ctc_budget['net_cost'])}\")\n", + "print(f\" Total: {format_currency(b2_ctc_budget['net_cost'])}\")\n", + "\n", + "print(f\"\\n2026 - Combined EITC + CTC:\")\n", + "print(f\" EITC net cost: {format_currency(b3_eitc_budget['net_cost'])}\")\n", + "print(f\" CTC net cost: {format_currency(b3_ctc_budget['net_cost'])}\")\n", + "print(f\" Total: {format_currency(b3_total_cost)}\")\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"Comparison to DC Council Estimates\")\n", + "print(\"=\"*60)\n", + "print(f\"\\nFY26 (2025) EITC:\")\n", + "print(f\" Council estimate: $17.42M\")\n", + "print(f\" Our estimate: {format_currency(a1_eitc_budget['net_cost'])}\")\n", + "\n", + "print(f\"\\nFY27 (2026) CTC (vs zeroed baseline):\")\n", + "print(f\" Council estimate: $55.26M\")\n", + "print(f\" Our estimate: {format_currency(b3_ctc_budget['net_cost'])}\")" + ] + } + ], + "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": 4 +} \ No newline at end of file diff --git a/dc_eitc_ctc_2026_impacts.csv b/dc_eitc_ctc_2026_impacts.csv new file mode 100644 index 0000000..17cbcb8 --- /dev/null +++ b/dc_eitc_ctc_2026_impacts.csv @@ -0,0 +1,5 @@ +Scenario,Net Cost,Overall Poverty Rate,Overall Poverty Change,Child Poverty Rate,Child Poverty Change,People Lifted from Poverty,Children Lifted from Poverty +Baseline,$0.00M,23.93%,0.0%,28.71%,0.0%,0,0 +EITC Only,$6.56M,23.93%,0.0%,28.71%,0.0%,0,0 +CTC Only,$85.78M,23.57%,1.5%,27.70%,3.5%,"2,175","1,218" +Combined (EITC + CTC),$92.34M,23.56%,1.5%,27.69%,3.5%,"2,419","1,279" diff --git a/dc_eitc_ctc_2026_simple.ipynb b/dc_eitc_ctc_2026_simple.ipynb new file mode 100644 index 0000000..a2eb746 --- /dev/null +++ b/dc_eitc_ctc_2026_simple.ipynb @@ -0,0 +1,616 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DC EITC and CTC Reforms Analysis (2026)\n", + "\n", + "This notebook analyzes the impact of two tax reforms in 2026:\n", + "\n", + "## Baseline\n", + "- DC CTC is repealed (set to $0)\n", + "- DC EITC remains at 85% federal match\n", + "\n", + "## Reforms\n", + "1. **EITC Enhancement**: Increase DC EITC from 85% to 100% federal match\n", + "2. **New CTC**: $1,000 per child under 18, with income thresholds and phase-outs\n", + "3. **Combined**: Both EITC and CTC reforms together\n", + "\n", + "## Metrics\n", + "For each reform, we calculate:\n", + "- Budgetary impact (net cost)\n", + "- Overall poverty impact\n", + "- Child poverty impact" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper Functions" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_poverty(sim, period=2026, child_only=False):\n", + " \"\"\"\n", + " Calculate poverty rate and count.\n", + " \n", + " Args:\n", + " sim: Microsimulation object\n", + " period: Year to analyze\n", + " child_only: If True, only count children under 18\n", + " \n", + " Returns:\n", + " poverty_rate: Weighted poverty rate (for accurate population estimates)\n", + " people_in_poverty: Unweighted count (number of people in the sample)\n", + " \"\"\"\n", + " age = sim.calculate(\"age\", period=period)\n", + " is_in_poverty = sim.calculate(\"person_in_poverty\", period=period)\n", + " person_weight = sim.calculate(\"person_weight\", period=period)\n", + " \n", + " if child_only:\n", + " mask = age < 18\n", + " else:\n", + " mask = np.ones_like(age, dtype=bool)\n", + " \n", + " # Weighted poverty rate (correct for population-level analysis)\n", + " weighted_in_poverty = (is_in_poverty[mask] * person_weight[mask]).sum()\n", + " weighted_total = person_weight[mask].sum()\n", + " poverty_rate = weighted_in_poverty / weighted_total if weighted_total > 0 else 0\n", + " \n", + " # Unweighted count (actual sample count for \"people lifted\")\n", + " unweighted_in_poverty = is_in_poverty[mask].sum()\n", + " unweighted_total = mask.sum()\n", + " \n", + " return {\n", + " \"poverty_rate\": poverty_rate,\n", + " \"people_in_poverty\": unweighted_in_poverty,\n", + " \"total_people\": unweighted_total\n", + " }\n", + "\n", + "def calculate_budgetary_impact(baseline_sim, reform_sim, variable, period=2026):\n", + " \"\"\"\n", + " Calculate the budgetary impact (net cost) of a reform.\n", + " \"\"\"\n", + " baseline_value = baseline_sim.calculate(variable, period=period, map_to=\"household\").sum()\n", + " reform_value = reform_sim.calculate(variable, period=period, map_to=\"household\").sum()\n", + " \n", + " return reform_value - baseline_value\n", + "\n", + "def format_currency(value):\n", + " \"\"\"Format value as currency in millions.\"\"\"\n", + " return f\"${value/1e6:.2f}M\"\n", + "\n", + "def format_percent(value):\n", + " \"\"\"Format value as percentage.\"\"\"\n", + " return f\"{value*100:.2f}%\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define Baseline and Reforms" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform functions defined!\n" + ] + } + ], + "source": [ + "def create_baseline():\n", + " \"\"\"Baseline: CTC repealed, EITC at 85%\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2026-01-01.2100-12-31\": 0\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "def create_eitc_reform():\n", + " \"\"\"EITC only: Increase to 100% match, keep CTC at $0\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.eitc.with_children.match\": {\n", + " \"2026-01-01.2100-12-31\": 1.0\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2026-01-01.2100-12-31\": 0\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "def create_ctc_reform():\n", + " \"\"\"CTC only: New $1,000 CTC, keep EITC at 85%\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2026-01-01.2100-12-31\": 1000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2026-01-01.2100-12-31\": 18\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.child_cap\": {\n", + " \"2026-01-01.2100-12-31\": 999\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.phase_out.amount\": {\n", + " \"2026-01-01.2100-12-31\": 50\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2026-01-01.2100-12-31\": 70_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2026-01-01.2100-12-31\": 35_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "def create_combined_reform():\n", + " \"\"\"Combined: Both EITC (100%) and new CTC ($1,000)\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " # EITC: 100% match\n", + " \"gov.states.dc.tax.income.credits.eitc.with_children.match\": {\n", + " \"2026-01-01.2100-12-31\": 1.0\n", + " },\n", + " # CTC: $1,000 per child\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2026-01-01.2100-12-31\": 1000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2026-01-01.2100-12-31\": 18\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.child_cap\": {\n", + " \"2026-01-01.2100-12-31\": 999\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.phase_out.amount\": {\n", + " \"2026-01-01.2100-12-31\": 50\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2026-01-01.2100-12-31\": 70_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2026-01-01.2100-12-31\": 35_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2026-01-01.2100-12-31\": 55_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "print(\"Reform functions defined!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load Simulations" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading baseline (CTC repealed)...\n", + "✓ Baseline loaded\n", + "\n", + "Loading EITC reform...\n", + "✓ EITC reform loaded\n", + "\n", + "Loading CTC reform...\n", + "✓ CTC reform loaded\n", + "\n", + "Loading combined reform...\n", + "✓ Combined reform loaded\n", + "\n", + "============================================================\n", + "All simulations ready!\n", + "============================================================\n" + ] + } + ], + "source": [ + "print(\"Loading baseline (CTC repealed)...\")\n", + "baseline_reform = create_baseline()\n", + "baseline = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=baseline_reform)\n", + "print(\"✓ Baseline loaded\")\n", + "\n", + "print(\"\\nLoading EITC reform...\")\n", + "eitc_reform = create_eitc_reform()\n", + "eitc_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=eitc_reform)\n", + "print(\"✓ EITC reform loaded\")\n", + "\n", + "print(\"\\nLoading CTC reform...\")\n", + "ctc_reform = create_ctc_reform()\n", + "ctc_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=ctc_reform)\n", + "print(\"✓ CTC reform loaded\")\n", + "\n", + "print(\"\\nLoading combined reform...\")\n", + "combined_reform = create_combined_reform()\n", + "combined_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=combined_reform)\n", + "print(\"✓ Combined reform loaded\")\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"All simulations ready!\")\n", + "print(\"=\"*60)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Impacts" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ All impacts calculated\n" + ] + } + ], + "source": [ + "# Baseline metrics\n", + "baseline_overall_pov = calculate_poverty(baseline, child_only=False)\n", + "baseline_child_pov = calculate_poverty(baseline, child_only=True)\n", + "\n", + "# EITC reform impacts\n", + "eitc_cost = calculate_budgetary_impact(baseline, eitc_sim, \"dc_eitc\")\n", + "eitc_ctc_cost = calculate_budgetary_impact(baseline, eitc_sim, \"dc_ctc\")\n", + "eitc_total_cost = eitc_cost + eitc_ctc_cost\n", + "eitc_overall_pov = calculate_poverty(eitc_sim, child_only=False)\n", + "eitc_child_pov = calculate_poverty(eitc_sim, child_only=True)\n", + "\n", + "# CTC reform impacts\n", + "ctc_eitc_cost = calculate_budgetary_impact(baseline, ctc_sim, \"dc_eitc\")\n", + "ctc_cost = calculate_budgetary_impact(baseline, ctc_sim, \"dc_ctc\")\n", + "ctc_total_cost = ctc_eitc_cost + ctc_cost\n", + "ctc_overall_pov = calculate_poverty(ctc_sim, child_only=False)\n", + "ctc_child_pov = calculate_poverty(ctc_sim, child_only=True)\n", + "\n", + "# Combined reform impacts\n", + "combined_eitc_cost = calculate_budgetary_impact(baseline, combined_sim, \"dc_eitc\")\n", + "combined_ctc_cost = calculate_budgetary_impact(baseline, combined_sim, \"dc_ctc\")\n", + "combined_total_cost = combined_eitc_cost + combined_ctc_cost\n", + "combined_overall_pov = calculate_poverty(combined_sim, child_only=False)\n", + "combined_child_pov = calculate_poverty(combined_sim, child_only=True)\n", + "\n", + "print(\"✓ All impacts calculated\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Results Summary" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "================================================================================================================================================================\n", + "DC EITC AND CTC REFORMS - 2026 IMPACTS\n", + "Baseline: CTC Repealed, EITC at 85% Federal Match\n", + "================================================================================================================================================================\n", + " Scenario Net Cost Overall Poverty Rate Overall Poverty Change Child Poverty Rate Child Poverty Change People Lifted from Poverty Children Lifted from Poverty\n", + " Baseline $0.00M 23.93% 0.0% 28.71% 0.0% 0 0\n", + " EITC Only $6.56M 23.93% 0.0% 28.71% 0.0% 0 0\n", + " CTC Only $85.78M 23.57% 1.5% 27.70% 3.5% 2,175 1,218\n", + "Combined (EITC + CTC) $92.34M 23.56% 1.5% 27.69% 3.5% 2,419 1,279\n", + "\n", + "✓ Exported to: dc_eitc_ctc_2026_impacts.csv\n" + ] + } + ], + "source": [ + "# Calculate relative changes\n", + "def calc_relative_change(baseline_rate, reform_rate):\n", + " if baseline_rate == 0:\n", + " return 0\n", + " return ((baseline_rate - reform_rate) / baseline_rate) * 100\n", + "\n", + "eitc_overall_rel = calc_relative_change(baseline_overall_pov['poverty_rate'], eitc_overall_pov['poverty_rate'])\n", + "eitc_child_rel = calc_relative_change(baseline_child_pov['poverty_rate'], eitc_child_pov['poverty_rate'])\n", + "ctc_overall_rel = calc_relative_change(baseline_overall_pov['poverty_rate'], ctc_overall_pov['poverty_rate'])\n", + "ctc_child_rel = calc_relative_change(baseline_child_pov['poverty_rate'], ctc_child_pov['poverty_rate'])\n", + "combined_overall_rel = calc_relative_change(baseline_overall_pov['poverty_rate'], combined_overall_pov['poverty_rate'])\n", + "combined_child_rel = calc_relative_change(baseline_child_pov['poverty_rate'], combined_child_pov['poverty_rate'])\n", + "\n", + "# Create comprehensive results table\n", + "results = [\n", + " {\n", + " \"Scenario\": \"Baseline\",\n", + " \"Net Cost\": \"$0.00M\",\n", + " \"Overall Poverty Rate\": format_percent(baseline_overall_pov['poverty_rate']),\n", + " \"Overall Poverty Change\": \"0.0%\",\n", + " \"Child Poverty Rate\": format_percent(baseline_child_pov['poverty_rate']),\n", + " \"Child Poverty Change\": \"0.0%\",\n", + " \"People Lifted from Poverty\": \"0\",\n", + " \"Children Lifted from Poverty\": \"0\"\n", + " },\n", + " {\n", + " \"Scenario\": \"EITC Only\",\n", + " \"Net Cost\": format_currency(eitc_total_cost),\n", + " \"Overall Poverty Rate\": format_percent(eitc_overall_pov['poverty_rate']),\n", + " \"Overall Poverty Change\": f\"{eitc_overall_rel:.1f}%\",\n", + " \"Child Poverty Rate\": format_percent(eitc_child_pov['poverty_rate']),\n", + " \"Child Poverty Change\": f\"{eitc_child_rel:.1f}%\",\n", + " \"People Lifted from Poverty\": f\"{int(baseline_overall_pov['people_in_poverty'] - eitc_overall_pov['people_in_poverty']):,}\",\n", + " \"Children Lifted from Poverty\": f\"{int(baseline_child_pov['people_in_poverty'] - eitc_child_pov['people_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"CTC Only\",\n", + " \"Net Cost\": format_currency(ctc_total_cost),\n", + " \"Overall Poverty Rate\": format_percent(ctc_overall_pov['poverty_rate']),\n", + " \"Overall Poverty Change\": f\"{ctc_overall_rel:.1f}%\",\n", + " \"Child Poverty Rate\": format_percent(ctc_child_pov['poverty_rate']),\n", + " \"Child Poverty Change\": f\"{ctc_child_rel:.1f}%\",\n", + " \"People Lifted from Poverty\": f\"{int(baseline_overall_pov['people_in_poverty'] - ctc_overall_pov['people_in_poverty']):,}\",\n", + " \"Children Lifted from Poverty\": f\"{int(baseline_child_pov['people_in_poverty'] - ctc_child_pov['people_in_poverty']):,}\"\n", + " },\n", + " {\n", + " \"Scenario\": \"Combined (EITC + CTC)\",\n", + " \"Net Cost\": format_currency(combined_total_cost),\n", + " \"Overall Poverty Rate\": format_percent(combined_overall_pov['poverty_rate']),\n", + " \"Overall Poverty Change\": f\"{combined_overall_rel:.1f}%\",\n", + " \"Child Poverty Rate\": format_percent(combined_child_pov['poverty_rate']),\n", + " \"Child Poverty Change\": f\"{combined_child_rel:.1f}%\",\n", + " \"People Lifted from Poverty\": f\"{int(baseline_overall_pov['people_in_poverty'] - combined_overall_pov['people_in_poverty']):,}\",\n", + " \"Children Lifted from Poverty\": f\"{int(baseline_child_pov['people_in_poverty'] - combined_child_pov['people_in_poverty']):,}\"\n", + " }\n", + "]\n", + "\n", + "df_results = pd.DataFrame(results)\n", + "\n", + "print(\"\\n\" + \"=\"*160)\n", + "print(\"DC EITC AND CTC REFORMS - 2026 IMPACTS\")\n", + "print(\"Baseline: CTC Repealed, EITC at 85% Federal Match\")\n", + "print(\"=\"*160)\n", + "print(df_results.to_string(index=False))\n", + "\n", + "# Export to CSV\n", + "df_results.to_csv(\"dc_eitc_ctc_2026_impacts.csv\", index=False)\n", + "print(\"\\n✓ Exported to: dc_eitc_ctc_2026_impacts.csv\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Detailed Breakdown" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "================================================================================\n", + "DETAILED BREAKDOWN BY PROVISION\n", + "================================================================================\n", + "\n", + "--------------------------------------------------------------------------------\n", + "1. EITC ENHANCEMENT (100% federal match)\n", + "--------------------------------------------------------------------------------\n", + "Budgetary Impact:\n", + " EITC net cost: $6.56M\n", + " CTC net cost: $0.00M\n", + " Total net cost: $6.56M\n", + "\n", + "Overall Poverty Impact:\n", + " Baseline poverty rate: 23.93%\n", + " Reform poverty rate: 23.93%\n", + " Relative change: 0.0%\n", + " People lifted from poverty: 0\n", + "\n", + "Child Poverty Impact:\n", + " Baseline poverty rate: 28.71%\n", + " Reform poverty rate: 28.71%\n", + " Relative change: 0.0%\n", + " Children lifted from poverty: 0\n", + "\n", + "--------------------------------------------------------------------------------\n", + "2. NEW CHILD TAX CREDIT ($1,000 per child under 18)\n", + "--------------------------------------------------------------------------------\n", + "Budgetary Impact:\n", + " EITC net cost: $0.00M\n", + " CTC net cost: $85.78M\n", + " Total net cost: $85.78M\n", + "\n", + "Overall Poverty Impact:\n", + " Baseline poverty rate: 23.93%\n", + " Reform poverty rate: 23.57%\n", + " Relative change: 1.5%\n", + " People lifted from poverty: 2,175\n", + "\n", + "Child Poverty Impact:\n", + " Baseline poverty rate: 28.71%\n", + " Reform poverty rate: 27.70%\n", + " Relative change: 3.5%\n", + " Children lifted from poverty: 1,218\n", + "\n", + "--------------------------------------------------------------------------------\n", + "3. COMBINED REFORMS (EITC + CTC)\n", + "--------------------------------------------------------------------------------\n", + "Budgetary Impact:\n", + " EITC net cost: $6.56M\n", + " CTC net cost: $85.78M\n", + " Total net cost: $92.34M\n", + "\n", + "Overall Poverty Impact:\n", + " Baseline poverty rate: 23.93%\n", + " Reform poverty rate: 23.56%\n", + " Relative change: 1.5%\n", + " People lifted from poverty: 2,419\n", + "\n", + "Child Poverty Impact:\n", + " Baseline poverty rate: 28.71%\n", + " Reform poverty rate: 27.69%\n", + " Relative change: 3.5%\n", + " Children lifted from poverty: 1,279\n" + ] + } + ], + "source": [ + "print(\"\\n\" + \"=\"*80)\n", + "print(\"DETAILED BREAKDOWN BY PROVISION\")\n", + "print(\"=\"*80)\n", + "\n", + "print(\"\\n\" + \"-\"*80)\n", + "print(\"1. EITC ENHANCEMENT (100% federal match)\")\n", + "print(\"-\"*80)\n", + "print(f\"Budgetary Impact:\")\n", + "print(f\" EITC net cost: {format_currency(eitc_cost)}\")\n", + "print(f\" CTC net cost: {format_currency(eitc_ctc_cost)}\")\n", + "print(f\" Total net cost: {format_currency(eitc_total_cost)}\")\n", + "print(f\"\\nOverall Poverty Impact:\")\n", + "print(f\" Baseline poverty rate: {format_percent(baseline_overall_pov['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(eitc_overall_pov['poverty_rate'])}\")\n", + "print(f\" Relative change: {eitc_overall_rel:.1f}%\")\n", + "print(f\" People lifted from poverty: {int(baseline_overall_pov['people_in_poverty'] - eitc_overall_pov['people_in_poverty']):,}\")\n", + "print(f\"\\nChild Poverty Impact:\")\n", + "print(f\" Baseline poverty rate: {format_percent(baseline_child_pov['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(eitc_child_pov['poverty_rate'])}\")\n", + "print(f\" Relative change: {eitc_child_rel:.1f}%\")\n", + "print(f\" Children lifted from poverty: {int(baseline_child_pov['people_in_poverty'] - eitc_child_pov['people_in_poverty']):,}\")\n", + "\n", + "print(\"\\n\" + \"-\"*80)\n", + "print(\"2. NEW CHILD TAX CREDIT ($1,000 per child under 18)\")\n", + "print(\"-\"*80)\n", + "print(f\"Budgetary Impact:\")\n", + "print(f\" EITC net cost: {format_currency(ctc_eitc_cost)}\")\n", + "print(f\" CTC net cost: {format_currency(ctc_cost)}\")\n", + "print(f\" Total net cost: {format_currency(ctc_total_cost)}\")\n", + "print(f\"\\nOverall Poverty Impact:\")\n", + "print(f\" Baseline poverty rate: {format_percent(baseline_overall_pov['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(ctc_overall_pov['poverty_rate'])}\")\n", + "print(f\" Relative change: {ctc_overall_rel:.1f}%\")\n", + "print(f\" People lifted from poverty: {int(baseline_overall_pov['people_in_poverty'] - ctc_overall_pov['people_in_poverty']):,}\")\n", + "print(f\"\\nChild Poverty Impact:\")\n", + "print(f\" Baseline poverty rate: {format_percent(baseline_child_pov['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(ctc_child_pov['poverty_rate'])}\")\n", + "print(f\" Relative change: {ctc_child_rel:.1f}%\")\n", + "print(f\" Children lifted from poverty: {int(baseline_child_pov['people_in_poverty'] - ctc_child_pov['people_in_poverty']):,}\")\n", + "\n", + "print(\"\\n\" + \"-\"*80)\n", + "print(\"3. COMBINED REFORMS (EITC + CTC)\")\n", + "print(\"-\"*80)\n", + "print(f\"Budgetary Impact:\")\n", + "print(f\" EITC net cost: {format_currency(combined_eitc_cost)}\")\n", + "print(f\" CTC net cost: {format_currency(combined_ctc_cost)}\")\n", + "print(f\" Total net cost: {format_currency(combined_total_cost)}\")\n", + "print(f\"\\nOverall Poverty Impact:\")\n", + "print(f\" Baseline poverty rate: {format_percent(baseline_overall_pov['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(combined_overall_pov['poverty_rate'])}\")\n", + "print(f\" Relative change: {combined_overall_rel:.1f}%\")\n", + "print(f\" People lifted from poverty: {int(baseline_overall_pov['people_in_poverty'] - combined_overall_pov['people_in_poverty']):,}\")\n", + "print(f\"\\nChild Poverty Impact:\")\n", + "print(f\" Baseline poverty rate: {format_percent(baseline_child_pov['poverty_rate'])}\")\n", + "print(f\" Reform poverty rate: {format_percent(combined_child_pov['poverty_rate'])}\")\n", + "print(f\" Relative change: {combined_child_rel:.1f}%\")\n", + "print(f\" Children lifted from poverty: {int(baseline_child_pov['people_in_poverty'] - combined_child_pov['people_in_poverty']):,}\")" + ] + } + ], + "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": 4 +} diff --git a/obbba_district_impacts/Congressional-Hackathon-2025 b/obbba_district_impacts/Congressional-Hackathon-2025 new file mode 160000 index 0000000..3f6d05e --- /dev/null +++ b/obbba_district_impacts/Congressional-Hackathon-2025 @@ -0,0 +1 @@ +Subproject commit 3f6d05e76400c6e396a3a4eddd34a7b3f6919fc3 diff --git a/us/states/dc/cps_comparison.ipynb b/us/states/dc/cps_comparison.ipynb new file mode 100644 index 0000000..054342a --- /dev/null +++ b/us/states/dc/cps_comparison.ipynb @@ -0,0 +1,269 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# CPS 2024 Dataset Exploration\n", + "\n", + "This notebook explores the CPS 2024 dataset to understand household counts and income distribution for comparison with the DC dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "ename": "EntryNotFoundError", + "evalue": "404 Client Error. (Request ID: Root=1-68dd68f4-1f8ede284014812a17566523;48a4a1a7-d197-4e14-b249-0f8ffde66e50)\n\nEntry Not Found for url: https://huggingface.co/policyengine/policyengine-us-data/resolve/main/cps_2024.h5.", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mHTTPError\u001b[0m Traceback (most recent call last)", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\utils\\_http.py:409\u001b[0m, in \u001b[0;36mhf_raise_for_status\u001b[1;34m(response, endpoint_name)\u001b[0m\n\u001b[0;32m 408\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 409\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraise_for_status\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 410\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m HTTPError \u001b[38;5;28;01mas\u001b[39;00m e:\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\requests\\models.py:1024\u001b[0m, in \u001b[0;36mResponse.raise_for_status\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 1023\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m http_error_msg:\n\u001b[1;32m-> 1024\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m HTTPError(http_error_msg, response\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m)\n", + "\u001b[1;31mHTTPError\u001b[0m: 404 Client Error: Not Found for url: https://huggingface.co/policyengine/policyengine-us-data/resolve/main/cps_2024.h5", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[1;31mEntryNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[9], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# Load microsimulation with new data source\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m sim \u001b[38;5;241m=\u001b[39m \u001b[43mMicrosimulation\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdataset\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mhf://policyengine/policyengine-us-data/cps_2024.h5\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\PolicyEngine\\policyengine-us\\policyengine_us\\system.py:220\u001b[0m, in \u001b[0;36mMicrosimulation.__init__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 213\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[0;32m 214\u001b[0m dataset \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 215\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(dataset, \u001b[38;5;28mstr\u001b[39m)\n\u001b[0;32m 216\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcps_2023\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m dataset\n\u001b[0;32m 217\u001b[0m ):\n\u001b[0;32m 218\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdefault_input_period \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m2023\u001b[39m\n\u001b[1;32m--> 220\u001b[0m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__init__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 222\u001b[0m reform \u001b[38;5;241m=\u001b[39m create_structural_reforms_from_parameters(\n\u001b[0;32m 223\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtax_benefit_system\u001b[38;5;241m.\u001b[39mparameters, start_instant\n\u001b[0;32m 224\u001b[0m )\n\u001b[0;32m 225\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m reform \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "File \u001b[1;32m~\\PolicyEngine\\policyengine-core\\policyengine_core\\simulations\\simulation.py:161\u001b[0m, in \u001b[0;36mSimulation.__init__\u001b[1;34m(self, tax_benefit_system, populations, situation, dataset, reform, trace)\u001b[0m\n\u001b[0;32m 159\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 160\u001b[0m version \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m--> 161\u001b[0m dataset \u001b[38;5;241m=\u001b[39m \u001b[43mdownload_huggingface_dataset\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 162\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43mf\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43mowner\u001b[49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[38;5;124;43m/\u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43mrepo\u001b[49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 163\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_filename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 164\u001b[0m \u001b[43m \u001b[49m\u001b[43mversion\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mversion\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 165\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 166\u001b[0m datasets_by_name \u001b[38;5;241m=\u001b[39m {\n\u001b[0;32m 167\u001b[0m dataset\u001b[38;5;241m.\u001b[39mname: dataset \u001b[38;5;28;01mfor\u001b[39;00m dataset \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdatasets\n\u001b[0;32m 168\u001b[0m }\n\u001b[0;32m 169\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m dataset \u001b[38;5;129;01min\u001b[39;00m datasets_by_name:\n", + "File \u001b[1;32m~\\PolicyEngine\\policyengine-core\\policyengine_core\\tools\\hugging_face.py:54\u001b[0m, in \u001b[0;36mdownload_huggingface_dataset\u001b[1;34m(repo, repo_filename, version, local_dir)\u001b[0m\n\u001b[0;32m 51\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_repo_private:\n\u001b[0;32m 52\u001b[0m authentication_token: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m get_or_prompt_hf_token()\n\u001b[1;32m---> 54\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mhf_hub_download\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 55\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrepo\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 56\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mmodel\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 57\u001b[0m \u001b[43m \u001b[49m\u001b[43mfilename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrepo_filename\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 58\u001b[0m \u001b[43m \u001b[49m\u001b[43mrevision\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mversion\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 59\u001b[0m \u001b[43m \u001b[49m\u001b[43mtoken\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mauthentication_token\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 60\u001b[0m \u001b[43m \u001b[49m\u001b[43mlocal_dir\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlocal_dir\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 61\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\utils\\_validators.py:114\u001b[0m, in \u001b[0;36mvalidate_hf_hub_args.._inner_fn\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 111\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_use_auth_token:\n\u001b[0;32m 112\u001b[0m kwargs \u001b[38;5;241m=\u001b[39m smoothly_deprecate_use_auth_token(fn_name\u001b[38;5;241m=\u001b[39mfn\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m, has_token\u001b[38;5;241m=\u001b[39mhas_token, kwargs\u001b[38;5;241m=\u001b[39mkwargs)\n\u001b[1;32m--> 114\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\file_download.py:1008\u001b[0m, in \u001b[0;36mhf_hub_download\u001b[1;34m(repo_id, filename, subfolder, repo_type, revision, library_name, library_version, cache_dir, local_dir, user_agent, force_download, proxies, etag_timeout, token, local_files_only, headers, endpoint, resume_download, force_filename, local_dir_use_symlinks)\u001b[0m\n\u001b[0;32m 988\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _hf_hub_download_to_local_dir(\n\u001b[0;32m 989\u001b[0m \u001b[38;5;66;03m# Destination\u001b[39;00m\n\u001b[0;32m 990\u001b[0m local_dir\u001b[38;5;241m=\u001b[39mlocal_dir,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1005\u001b[0m local_files_only\u001b[38;5;241m=\u001b[39mlocal_files_only,\n\u001b[0;32m 1006\u001b[0m )\n\u001b[0;32m 1007\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1008\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_hf_hub_download_to_cache_dir\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1009\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# Destination\u001b[39;49;00m\n\u001b[0;32m 1010\u001b[0m \u001b[43m \u001b[49m\u001b[43mcache_dir\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcache_dir\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1011\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# File info\u001b[39;49;00m\n\u001b[0;32m 1012\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrepo_id\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1013\u001b[0m \u001b[43m \u001b[49m\u001b[43mfilename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1014\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrepo_type\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1015\u001b[0m \u001b[43m \u001b[49m\u001b[43mrevision\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrevision\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1016\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# HTTP info\u001b[39;49;00m\n\u001b[0;32m 1017\u001b[0m \u001b[43m \u001b[49m\u001b[43mendpoint\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mendpoint\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1018\u001b[0m \u001b[43m \u001b[49m\u001b[43metag_timeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43metag_timeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1019\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhf_headers\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1020\u001b[0m \u001b[43m \u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxies\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1021\u001b[0m \u001b[43m \u001b[49m\u001b[43mtoken\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtoken\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1022\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# Additional options\u001b[39;49;00m\n\u001b[0;32m 1023\u001b[0m \u001b[43m \u001b[49m\u001b[43mlocal_files_only\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlocal_files_only\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1024\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_download\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_download\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1025\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\file_download.py:1071\u001b[0m, in \u001b[0;36m_hf_hub_download_to_cache_dir\u001b[1;34m(cache_dir, repo_id, filename, repo_type, revision, endpoint, etag_timeout, headers, proxies, token, local_files_only, force_download)\u001b[0m\n\u001b[0;32m 1067\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m pointer_path\n\u001b[0;32m 1069\u001b[0m \u001b[38;5;66;03m# Try to get metadata (etag, commit_hash, url, size) from the server.\u001b[39;00m\n\u001b[0;32m 1070\u001b[0m \u001b[38;5;66;03m# If we can't, a HEAD request error is returned.\u001b[39;00m\n\u001b[1;32m-> 1071\u001b[0m (url_to_download, etag, commit_hash, expected_size, xet_file_data, head_call_error) \u001b[38;5;241m=\u001b[39m \u001b[43m_get_metadata_or_catch_error\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1072\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrepo_id\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1073\u001b[0m \u001b[43m \u001b[49m\u001b[43mfilename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1074\u001b[0m \u001b[43m \u001b[49m\u001b[43mrepo_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrepo_type\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1075\u001b[0m \u001b[43m \u001b[49m\u001b[43mrevision\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrevision\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1076\u001b[0m \u001b[43m \u001b[49m\u001b[43mendpoint\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mendpoint\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1077\u001b[0m \u001b[43m \u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxies\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1078\u001b[0m \u001b[43m \u001b[49m\u001b[43metag_timeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43metag_timeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1079\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1080\u001b[0m \u001b[43m \u001b[49m\u001b[43mtoken\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtoken\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1081\u001b[0m \u001b[43m \u001b[49m\u001b[43mlocal_files_only\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlocal_files_only\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1082\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_folder\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_folder\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1083\u001b[0m \u001b[43m \u001b[49m\u001b[43mrelative_filename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrelative_filename\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1084\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1086\u001b[0m \u001b[38;5;66;03m# etag can be None for several reasons:\u001b[39;00m\n\u001b[0;32m 1087\u001b[0m \u001b[38;5;66;03m# 1. we passed local_files_only.\u001b[39;00m\n\u001b[0;32m 1088\u001b[0m \u001b[38;5;66;03m# 2. we don't have a connection\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1094\u001b[0m \u001b[38;5;66;03m# If the specified revision is a commit hash, look inside \"snapshots\".\u001b[39;00m\n\u001b[0;32m 1095\u001b[0m \u001b[38;5;66;03m# If the specified revision is a branch or tag, look inside \"refs\".\u001b[39;00m\n\u001b[0;32m 1096\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m head_call_error \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 1097\u001b[0m \u001b[38;5;66;03m# Couldn't make a HEAD call => let's try to find a local file\u001b[39;00m\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\file_download.py:1531\u001b[0m, in \u001b[0;36m_get_metadata_or_catch_error\u001b[1;34m(repo_id, filename, repo_type, revision, endpoint, proxies, etag_timeout, headers, token, local_files_only, relative_filename, storage_folder)\u001b[0m\n\u001b[0;32m 1529\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 1530\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m-> 1531\u001b[0m metadata \u001b[38;5;241m=\u001b[39m \u001b[43mget_hf_file_metadata\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1532\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxies\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43metag_timeout\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtoken\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtoken\u001b[49m\n\u001b[0;32m 1533\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1534\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m EntryNotFoundError \u001b[38;5;28;01mas\u001b[39;00m http_error:\n\u001b[0;32m 1535\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m storage_folder \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m relative_filename \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 1536\u001b[0m \u001b[38;5;66;03m# Cache the non-existence of the file\u001b[39;00m\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\utils\\_validators.py:114\u001b[0m, in \u001b[0;36mvalidate_hf_hub_args.._inner_fn\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 111\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_use_auth_token:\n\u001b[0;32m 112\u001b[0m kwargs \u001b[38;5;241m=\u001b[39m smoothly_deprecate_use_auth_token(fn_name\u001b[38;5;241m=\u001b[39mfn\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m, has_token\u001b[38;5;241m=\u001b[39mhas_token, kwargs\u001b[38;5;241m=\u001b[39mkwargs)\n\u001b[1;32m--> 114\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\file_download.py:1448\u001b[0m, in \u001b[0;36mget_hf_file_metadata\u001b[1;34m(url, token, proxies, timeout, library_name, library_version, user_agent, headers)\u001b[0m\n\u001b[0;32m 1445\u001b[0m hf_headers[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAccept-Encoding\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124midentity\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;66;03m# prevent any compression => we want to know the real size of the file\u001b[39;00m\n\u001b[0;32m 1447\u001b[0m \u001b[38;5;66;03m# Retrieve metadata\u001b[39;00m\n\u001b[1;32m-> 1448\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43m_request_wrapper\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1449\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mHEAD\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1450\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1451\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhf_headers\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1452\u001b[0m \u001b[43m \u001b[49m\u001b[43mallow_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 1453\u001b[0m \u001b[43m \u001b[49m\u001b[43mfollow_relative_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 1454\u001b[0m \u001b[43m \u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxies\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1455\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1456\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1457\u001b[0m hf_raise_for_status(r)\n\u001b[0;32m 1459\u001b[0m \u001b[38;5;66;03m# Return\u001b[39;00m\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\file_download.py:286\u001b[0m, in \u001b[0;36m_request_wrapper\u001b[1;34m(method, url, follow_relative_redirects, **params)\u001b[0m\n\u001b[0;32m 284\u001b[0m \u001b[38;5;66;03m# Recursively follow relative redirects\u001b[39;00m\n\u001b[0;32m 285\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m follow_relative_redirects:\n\u001b[1;32m--> 286\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[43m_request_wrapper\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 287\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 288\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 289\u001b[0m \u001b[43m \u001b[49m\u001b[43mfollow_relative_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 290\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 291\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 293\u001b[0m \u001b[38;5;66;03m# If redirection, we redirect only relative paths.\u001b[39;00m\n\u001b[0;32m 294\u001b[0m \u001b[38;5;66;03m# This is useful in case of a renamed repository.\u001b[39;00m\n\u001b[0;32m 295\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;241m300\u001b[39m \u001b[38;5;241m<\u001b[39m\u001b[38;5;241m=\u001b[39m response\u001b[38;5;241m.\u001b[39mstatus_code \u001b[38;5;241m<\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m399\u001b[39m:\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\file_download.py:310\u001b[0m, in \u001b[0;36m_request_wrapper\u001b[1;34m(method, url, follow_relative_redirects, **params)\u001b[0m\n\u001b[0;32m 308\u001b[0m \u001b[38;5;66;03m# Perform request and return if status_code is not in the retry list.\u001b[39;00m\n\u001b[0;32m 309\u001b[0m response \u001b[38;5;241m=\u001b[39m http_backoff(method\u001b[38;5;241m=\u001b[39mmethod, url\u001b[38;5;241m=\u001b[39murl, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mparams, retry_on_exceptions\u001b[38;5;241m=\u001b[39m(), retry_on_status_codes\u001b[38;5;241m=\u001b[39m(\u001b[38;5;241m429\u001b[39m,))\n\u001b[1;32m--> 310\u001b[0m \u001b[43mhf_raise_for_status\u001b[49m\u001b[43m(\u001b[49m\u001b[43mresponse\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 311\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m response\n", + "File \u001b[1;32mc:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\huggingface_hub\\utils\\_http.py:420\u001b[0m, in \u001b[0;36mhf_raise_for_status\u001b[1;34m(response, endpoint_name)\u001b[0m\n\u001b[0;32m 418\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m error_code \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEntryNotFound\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m 419\u001b[0m message \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse\u001b[38;5;241m.\u001b[39mstatus_code\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m Client Error.\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEntry Not Found for url: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse\u001b[38;5;241m.\u001b[39murl\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m--> 420\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m _format(EntryNotFoundError, message, response) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01me\u001b[39;00m\n\u001b[0;32m 422\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m error_code \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGatedRepo\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m 423\u001b[0m message \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m 424\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse\u001b[38;5;241m.\u001b[39mstatus_code\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m Client Error.\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCannot access gated repo for url \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse\u001b[38;5;241m.\u001b[39murl\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 425\u001b[0m )\n", + "\u001b[1;31mEntryNotFoundError\u001b[0m: 404 Client Error. (Request ID: Root=1-68dd68f4-1f8ede284014812a17566523;48a4a1a7-d197-4e14-b249-0f8ffde66e50)\n\nEntry Not Found for url: https://huggingface.co/policyengine/policyengine-us-data/resolve/main/cps_2024.h5." + ] + } + ], + "source": [ + "# Load microsimulation with new data source\n", + "sim = Microsimulation(dataset='hf://policyengine/policyengine-us-data/cps_2024.h5')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Check dataset size\n", + "household_weight = sim.calculate(\"household_weight\", period=2025)\n", + "household_count = sim.calculate(\"household_count\", period=2025, map_to=\"household\")\n", + "person_count = sim.calculate(\"person_count\", period=2025, map_to=\"household\")\n", + "\n", + "print(f\"Number of households in dataset: {len(household_weight):,}\")\n", + "print(f\"Household count (mapped): {household_count.sum():,.0f}\")\n", + "print(f\"Person count (mapped): {person_count.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Check household income distribution (aggregate to household level using map_to)\n", + "agi = sim.calculate(\"adjusted_gross_income\", period=2025, map_to=\"household\")\n", + "print(f\"Income distribution:\")\n", + "print(f\" Median AGI: ${agi.median():,.0f}\")\n", + "print(f\" 75th percentile: ${agi.quantile(0.75):,.0f}\")\n", + "print(f\" 90th percentile: ${agi.quantile(0.90):,.0f}\")\n", + "print(f\" 95th percentile: ${agi.quantile(0.95):,.0f}\")\n", + "print(f\" Max AGI: ${agi.max():,.0f}\")\n", + "print(f\"\\nHouseholds by income threshold:\")\n", + "print(f\" Households over $80k: {(agi > 80_000).sum():,}\")\n", + "print(f\" Households over $120k: {(agi > 120_000).sum():,}\")\n", + "print(f\" Households over $160k: {(agi > 160_000).sum():,}\")\n", + "print(f\" Households over $240k: {(agi > 240_000).sum():,}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Check households with children (count at person level, aggregate to household)\n", + "is_child = sim.calculate(\"is_child\", period=2025)\n", + "household_id = sim.calculate(\"household_id\", period=2025)\n", + "\n", + "# Count children per household\n", + "children_per_household = pd.Series(is_child).groupby(household_id).sum()\n", + "\n", + "# Map back to household array\n", + "household_children = children_per_household.reindex(household_id.unique()).fillna(0).values\n", + "\n", + "print(f\"\\nHouseholds with children:\")\n", + "print(f\" Total households with children: {(household_children > 0).sum():,}\")\n", + "print(f\" Households with 1 child: {(household_children == 1).sum():,}\")\n", + "print(f\" Households with 2 children: {(household_children == 2).sum():,}\")\n", + "print(f\" Households with 3+ children: {(household_children >= 3).sum():,}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Check children by age groups (count at person level)\n", + "age = sim.calculate(\"age\", period=2025)\n", + "is_child_age = age < 18\n", + "\n", + "# Calculate totals\n", + "total_children = is_child.sum()\n", + "children_under_4 = (age < 4).sum()\n", + "children_under_6 = (age < 6).sum()\n", + "children_6_17 = ((age >= 6) & (age < 18)).sum()\n", + "\n", + "print(f\"\\nChildren by age:\")\n", + "print(f\" Total children under 18: {total_children:,}\")\n", + "print(f\" Children under 4: {children_under_4:,}\")\n", + "print(f\" Children under 6: {children_under_6:,}\")\n", + "print(f\" Children ages 6-17: {children_6_17:,}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Distribution of children under 4 per tax unit\n", + "df = sim.calculate_dataframe(['household_id', 'tax_unit_id', 'person_id', 'age'])\n", + "\n", + "# Filter for children under 4\n", + "children_under_4_df = df[df['age'] < 4]\n", + "\n", + "# Count children per tax unit\n", + "children_per_tax_unit = children_under_4_df.groupby('tax_unit_id').size()\n", + "\n", + "# Get all unique tax units\n", + "all_tax_units = df['tax_unit_id'].unique()\n", + "\n", + "# Create distribution: start with 0 for all tax units, then update with actual counts\n", + "distribution = pd.Series(0, index=all_tax_units)\n", + "distribution.update(children_per_tax_unit)\n", + "\n", + "# Get value counts of the distribution\n", + "distribution_summary = distribution.value_counts().sort_index()\n", + "\n", + "# Print results\n", + "print(\"Distribution of children under 4 per tax unit:\")\n", + "print(distribution_summary)\n", + "print(f\"\\nTotal tax units: {len(all_tax_units):,}\")\n", + "print(f\"Tax units with at least one child under 4: {(distribution > 0).sum():,}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create summary table with all findings\n", + "summary_data = {\n", + " 'Metric': [\n", + " 'Number of households in dataset',\n", + " 'Household count (mapped to household)',\n", + " 'Person count (mapped to household)',\n", + " 'Median AGI',\n", + " '75th percentile AGI',\n", + " '90th percentile AGI',\n", + " '95th percentile AGI',\n", + " 'Max AGI',\n", + " 'Households over $80k',\n", + " 'Households over $120k',\n", + " 'Households over $160k',\n", + " 'Households over $240k',\n", + " 'Total households with children',\n", + " 'Households with 1 child',\n", + " 'Households with 2 children',\n", + " 'Households with 3+ children',\n", + " 'Total children under 18',\n", + " 'Children under 4',\n", + " 'Children under 6',\n", + " 'Children ages 6-17',\n", + " 'Total tax units',\n", + " 'Tax units with at least one child under 4'\n", + " ],\n", + " 'Value': [\n", + " f\"{len(household_weight):,}\",\n", + " f\"{household_count.sum():,.0f}\",\n", + " f\"{person_count.sum():,.0f}\",\n", + " f\"${agi.median():,.0f}\",\n", + " f\"${agi.quantile(0.75):,.0f}\",\n", + " f\"${agi.quantile(0.90):,.0f}\",\n", + " f\"${agi.quantile(0.95):,.0f}\",\n", + " f\"${agi.max():,.0f}\",\n", + " f\"{(agi > 80_000).sum():,.0f}\",\n", + " f\"{(agi > 120_000).sum():,.0f}\",\n", + " f\"{(agi > 160_000).sum():,.0f}\",\n", + " f\"{(agi > 240_000).sum():,.0f}\",\n", + " f\"{(household_children > 0).sum():,.0f}\",\n", + " f\"{(household_children == 1).sum():,.0f}\",\n", + " f\"{(household_children == 2).sum():,.0f}\",\n", + " f\"{(household_children >= 3).sum():,.0f}\",\n", + " f\"{total_children:,.0f}\",\n", + " f\"{children_under_4:,.0f}\",\n", + " f\"{children_under_6:,.0f}\",\n", + " f\"{children_6_17:,.0f}\",\n", + " f\"{len(all_tax_units):,}\",\n", + " f\"{(distribution > 0).sum():,}\"\n", + " ]\n", + "}\n", + "\n", + "summary_df = pd.DataFrame(summary_data)\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"CPS 2024 DATASET SUMMARY (Household Level)\")\n", + "print(\"=\"*60)\n", + "print(summary_df.to_string(index=False))\n", + "print(\"=\"*60)\n", + "\n", + "# Also save as CSV for easy sharing\n", + "summary_df.to_csv('cps_2024_dataset_summary.csv', index=False)\n", + "print(\"\\nSummary saved to: cps_2024_dataset_summary.csv\")" + ] + } + ], + "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/dc/ctc_child_poverty_by_age.ipynb b/us/states/dc/ctc_child_poverty_by_age.ipynb new file mode 100644 index 0000000..50001ea --- /dev/null +++ b/us/states/dc/ctc_child_poverty_by_age.ipynb @@ -0,0 +1,462 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DC CTC Reform: Child Poverty Reduction by Age Range\n", + "\n", + "Analysis of child poverty impact for DC CTC reform with:\n", + "- $1,000 per child\n", + "- 10% phase-out ($100 reduction per $1,000 over income threshold)\n", + "- No cap on number of children\n", + "- Lower income thresholds: $50k (Single/HoH/Surviving), $75k (Joint), $37.5k (Separate)\n", + "\n", + "**Baseline**: Current DC CTC repealed (zeroed out)\n", + "\n", + "We'll analyze the percentage reduction in overall child poverty for different age eligibility thresholds." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "# Create baseline with current DC CTC zeroed out\n", + "def create_baseline_reform():\n", + " \"\"\"Zero out the existing DC CTC\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "baseline_reform = create_baseline_reform()\n", + "baseline_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=baseline_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def create_reform(age_threshold):\n", + " \"\"\"\n", + " Create DC CTC reform with:\n", + " - $1,000 per child\n", + " - 10% phase-out ($100 per $1,000 over threshold)\n", + " - No cap on children\n", + " - Lower income thresholds\n", + " \"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": 1000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": age_threshold\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.child_cap\": {\n", + " \"2025-01-01.2100-12-31\": 999\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.phase_out.amount\": {\n", + " \"2025-01-01.2100-12-31\": 100\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2025-01-01.2100-12-31\": 50_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2025-01-01.2100-12-31\": 75_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2025-01-01.2100-12-31\": 37_500\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2025-01-01.2100-12-31\": 50_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2025-01-01.2100-12-31\": 50_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_child_poverty(sim):\n", + " \"\"\"\n", + " Calculate overall child poverty rate (children under 18).\n", + " Returns poverty rate, count in poverty, and total children.\n", + " \"\"\"\n", + " # Get person-level data\n", + " age = sim.calculate(\"age\", period=2025)\n", + " is_in_poverty = sim.calculate(\"person_in_poverty\", period=2025)\n", + " \n", + " # Filter for children under 18\n", + " mask = age < 18\n", + " \n", + " # Calculate poverty count and total children\n", + " # The simulation data is already weighted, so we just count/sum\n", + " children_in_poverty = is_in_poverty[mask].sum()\n", + " total_children = mask.sum()\n", + " \n", + " # Calculate poverty rate\n", + " poverty_rate = children_in_poverty / total_children if total_children > 0 else 0\n", + " \n", + " return {\n", + " \"poverty_rate\": poverty_rate,\n", + " \"children_in_poverty\": children_in_poverty,\n", + " \"total_children\": total_children\n", + " }" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Baseline Child Poverty Rate\n", + "\n", + "Baseline: Current DC CTC repealed (zeroed out)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BASELINE CHILD POVERTY RATE (current DC CTC repealed)\n", + "======================================================================\n", + "Children under 18: 21.13%\n", + "Children in poverty: 27,758\n", + "Total children: 131,386\n" + ] + } + ], + "source": [ + "# Calculate baseline child poverty rate (with DC CTC zeroed out)\n", + "baseline_poverty = calculate_child_poverty(baseline_sim)\n", + "\n", + "print(\"BASELINE CHILD POVERTY RATE (current DC CTC repealed)\")\n", + "print(\"=\"*70)\n", + "print(f\"Children under 18: {baseline_poverty['poverty_rate']*100:.2f}%\")\n", + "print(f\"Children in poverty: {baseline_poverty['children_in_poverty']:,.0f}\")\n", + "print(f\"Total children: {baseline_poverty['total_children']:,.0f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reform Impact Analysis\n", + "\n", + "Analyze reforms with different age eligibility thresholds (6, 8, 12, 18).\n", + "\n", + "Each reform uses:\n", + "- $1,000 per child\n", + "- 10% phase-out\n", + "- No child cap\n", + "- Lower income thresholds" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Analyzing reform: Eligible children under age 6\n", + " Poverty rate: 21.13% → 20.86% (1.3% reduction)\n", + " Annual cost: $25,164,361\n", + "\n", + "Analyzing reform: Eligible children under age 8\n", + " Poverty rate: 21.13% → 20.86% (1.3% reduction)\n", + " Annual cost: $33,342,733\n", + "\n", + "Analyzing reform: Eligible children under age 12\n", + " Poverty rate: 21.13% → 20.33% (3.8% reduction)\n", + " Annual cost: $53,009,724\n", + "\n", + "Analyzing reform: Eligible children under age 18\n", + " Poverty rate: 21.13% → 19.76% (6.4% reduction)\n", + " Annual cost: $82,271,789\n", + "\n", + "Analysis complete!\n" + ] + } + ], + "source": [ + "# Define age thresholds to analyze\n", + "age_thresholds = [6, 8, 12, 18]\n", + "\n", + "# Store baseline values for comparison\n", + "baseline_rate = baseline_poverty['poverty_rate']\n", + "\n", + "# Analyze each reform\n", + "results = []\n", + "\n", + "for age_threshold in age_thresholds:\n", + " print(f\"\\nAnalyzing reform: Eligible children under age {age_threshold}\")\n", + " \n", + " # Create reform simulation\n", + " reform = create_reform(age_threshold)\n", + " reform_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=reform)\n", + " \n", + " # Calculate poverty rate under reform\n", + " reform_poverty = calculate_child_poverty(reform_sim)\n", + " reform_rate = reform_poverty['poverty_rate']\n", + " \n", + " # Calculate cost\n", + " reform_ctc = reform_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + " total_cost = reform_ctc.sum()\n", + " \n", + " # Calculate percentage reduction\n", + " if baseline_rate > 0:\n", + " pct_reduction = ((baseline_rate - reform_rate) / baseline_rate) * 100\n", + " else:\n", + " pct_reduction = 0\n", + " \n", + " absolute_reduction = (baseline_rate - reform_rate) * 100 # in percentage points\n", + " \n", + " results.append({\n", + " \"Age Eligibility\": f\"Under {age_threshold}\",\n", + " \"Baseline Poverty Rate\": f\"{baseline_rate*100:.2f}%\",\n", + " \"Reform Poverty Rate\": f\"{reform_rate*100:.2f}%\",\n", + " \"Absolute Reduction (pp)\": f\"{absolute_reduction:.2f}\",\n", + " \"Percentage Reduction\": f\"{pct_reduction:.1f}%\",\n", + " \"Annual Cost\": f\"${total_cost:,.0f}\",\n", + " # Numeric values for sorting\n", + " \"Age (Numeric)\": age_threshold,\n", + " \"Baseline Rate (Numeric)\": baseline_rate,\n", + " \"Reform Rate (Numeric)\": reform_rate,\n", + " \"Pct Reduction (Numeric)\": pct_reduction,\n", + " \"Cost (Numeric)\": total_cost\n", + " })\n", + " \n", + " print(f\" Poverty rate: {baseline_rate*100:.2f}% → {reform_rate*100:.2f}% ({pct_reduction:.1f}% reduction)\")\n", + " print(f\" Annual cost: ${total_cost:,.0f}\")\n", + "\n", + "print(\"\\nAnalysis complete!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Results Summary\n", + "\n", + "Overall child poverty reduction (children under 18) for each age eligibility threshold." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "========================================================================================================================\n", + "DC CTC REFORM: CHILD POVERTY REDUCTION BY AGE ELIGIBILITY\n", + "Reform Parameters: $1,000/child, 10% phase-out, No child cap\n", + "Baseline: Current DC CTC repealed\n", + "========================================================================================================================\n", + "Age Eligibility Baseline Poverty Rate Reform Poverty Rate Absolute Reduction (pp) Percentage Reduction Annual Cost\n", + " Under 6 21.13% 20.86% 0.27 1.3% $25,164,361\n", + " Under 8 21.13% 20.86% 0.27 1.3% $33,342,733\n", + " Under 12 21.13% 20.33% 0.79 3.8% $53,009,724\n", + " Under 18 21.13% 19.76% 1.36 6.4% $82,271,789\n", + "========================================================================================================================\n" + ] + } + ], + "source": [ + "# Create DataFrame\n", + "df = pd.DataFrame(results)\n", + "\n", + "# Display full results table\n", + "print(\"\\n\" + \"=\"*120)\n", + "print(\"DC CTC REFORM: CHILD POVERTY REDUCTION BY AGE ELIGIBILITY\")\n", + "print(\"Reform Parameters: $1,000/child, 10% phase-out, No child cap\")\n", + "print(\"Baseline: Current DC CTC repealed\")\n", + "print(\"=\"*120)\n", + "print(df[['Age Eligibility', 'Baseline Poverty Rate', 'Reform Poverty Rate', \n", + " 'Absolute Reduction (pp)', 'Percentage Reduction', 'Annual Cost']].to_string(index=False))\n", + "print(\"=\"*120)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cost-Effectiveness Analysis\n", + "\n", + "Compare the cost per percentage point reduction in child poverty." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "COST-EFFECTIVENESS COMPARISON\n", + "====================================================================================================\n", + "Age Eligibility Percentage Reduction Annual Cost Cost per pp Reduction\n", + " Under 6 1.3% $25,164,361 $93,190,797\n", + " Under 8 1.3% $33,342,733 $123,477,635\n", + " Under 12 3.8% $53,009,724 $66,697,531\n", + " Under 18 6.4% $82,271,789 $60,376,900\n", + "====================================================================================================\n" + ] + } + ], + "source": [ + "# Calculate cost per percentage point reduction\n", + "print(\"\\nCOST-EFFECTIVENESS COMPARISON\")\n", + "print(\"=\"*100)\n", + "\n", + "cost_effectiveness = []\n", + "for _, row in df.iterrows():\n", + " if row['Pct Reduction (Numeric)'] > 0:\n", + " cost_per_pp = row['Cost (Numeric)'] / abs((row['Baseline Rate (Numeric)'] - row['Reform Rate (Numeric)']) * 100)\n", + " cost_effectiveness.append({\n", + " \"Age Eligibility\": row['Age Eligibility'],\n", + " \"Percentage Reduction\": row['Percentage Reduction'],\n", + " \"Annual Cost\": row['Annual Cost'],\n", + " \"Cost per pp Reduction\": f\"${cost_per_pp:,.0f}\"\n", + " })\n", + "\n", + "cost_df = pd.DataFrame(cost_effectiveness)\n", + "print(cost_df.to_string(index=False))\n", + "print(\"=\"*100)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Key Findings" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "KEY FINDINGS\n", + "================================================================================\n", + "\n", + "Baseline child poverty rate (DC CTC repealed): 21.13%\n", + "\n", + "Child poverty reduction by reform:\n", + " Under 6 : 1.3% reduction (costs $25,164,361)\n", + " Under 8 : 1.3% reduction (costs $33,342,733)\n", + " Under 12 : 3.8% reduction (costs $53,009,724)\n", + " Under 18 : 6.4% reduction (costs $82,271,789)\n", + "\n", + "Most cost-effective: Under 18 ($60,376,900 per percentage point reduction)\n", + "================================================================================\n" + ] + } + ], + "source": [ + "print(\"\\nKEY FINDINGS\")\n", + "print(\"=\"*80)\n", + "print(f\"\\nBaseline child poverty rate (DC CTC repealed): {baseline_rate*100:.2f}%\")\n", + "print(f\"\\nChild poverty reduction by reform:\")\n", + "for _, row in df.iterrows():\n", + " print(f\" {row['Age Eligibility']:10s}: {row['Percentage Reduction']:>6s} reduction (costs {row['Annual Cost']})\")\n", + "\n", + "# Find most cost-effective\n", + "if len(cost_effectiveness) > 0:\n", + " best_reform = min(cost_effectiveness, key=lambda x: float(x['Cost per pp Reduction'].replace('$','').replace(',','')))\n", + " print(f\"\\nMost cost-effective: {best_reform['Age Eligibility']} ({best_reform['Cost per pp Reduction']} per percentage point reduction)\")\n", + "print(\"=\"*80)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Results exported to dc_ctc_child_poverty_by_age.csv\n" + ] + } + ], + "source": [ + "# Export results to CSV\n", + "csv_filename = \"dc_ctc_child_poverty_by_age.csv\"\n", + "df[['Age Eligibility', 'Baseline Poverty Rate', 'Reform Poverty Rate', \n", + " 'Absolute Reduction (pp)', 'Percentage Reduction', 'Annual Cost']].to_csv(csv_filename, index=False)\n", + "print(f\"\\nResults exported to {csv_filename}\")" + ] + } + ], + "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": 4 +} diff --git a/us/states/dc/ctc_reforms.ipynb b/us/states/dc/ctc_reforms.ipynb new file mode 100644 index 0000000..888c1b9 --- /dev/null +++ b/us/states/dc/ctc_reforms.ipynb @@ -0,0 +1,763 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DC Child Tax Credit Reform Analysis\n", + "\n", + "This notebook analyzes baseline and reform scenarios for the DC Child Tax Credit at various cost levels ($5M, $10M, and $15M) targeting different age groups:\n", + "- Preschool age (under 4)\n", + "- Early childhood (under 6)\n", + "- All children (under 18)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Load DC dataset (same as dataset_exploration notebook)\n", + "sim = Microsimulation(dataset='hf://policyengine/test/DC.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Baseline: Zero Out Current DC CTC\n", + "\n", + "Current DC CTC provides $420 per child under age 6, with income phase-outs starting at $160k (single)/$240k (joint)." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def create_baseline_reform():\n", + " \"\"\"Zero out the existing DC CTC\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "baseline_reform = create_baseline_reform()\n", + "baseline_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=baseline_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Current DC CTC annual cost: $17,971,915\n", + "Baseline DC CTC cost (zeroed out): $0\n" + ] + } + ], + "source": [ + "# Calculate baseline cost\n", + "current_ctc = sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "baseline_ctc = baseline_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "current_cost = current_ctc.sum()\n", + "print(f\"Current DC CTC annual cost: ${current_cost:,.0f}\")\n", + "print(f\"Baseline DC CTC cost (zeroed out): ${baseline_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def create_preschool_reform(amount_per_child):\n", + " \"\"\"Create reform targeting preschool age children (under 4)\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": amount_per_child\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": 4\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "# Adjusted estimates based on actual costs\n", + "preschool_5m_amount = 175 # Estimate for $5M\n", + "preschool_10m_amount = 350 # Estimate for $10M\n", + "preschool_15m_amount = 525 # Estimate for $15M\n", + "\n", + "preschool_5m_reform = create_preschool_reform(preschool_5m_amount)\n", + "preschool_10m_reform = create_preschool_reform(preschool_10m_amount)\n", + "preschool_15m_reform = create_preschool_reform(preschool_15m_amount)\n", + "\n", + "preschool_5m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=preschool_5m_reform)\n", + "preschool_10m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=preschool_10m_reform)\n", + "preschool_15m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=preschool_15m_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform 1: Preschool Age (Under 4)\n", + " $5M target - Amount per child: $175, Actual cost: $5,017,059\n", + " $10M target - Amount per child: $350, Actual cost: $10,068,140\n", + " $15M target - Amount per child: $525, Actual cost: $15,148,594\n" + ] + } + ], + "source": [ + "# Calculate costs for preschool reforms\n", + "preschool_5m_ctc = preschool_5m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "preschool_10m_ctc = preschool_10m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "preschool_15m_ctc = preschool_15m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "print(\"Reform 1: Preschool Age (Under 4)\")\n", + "print(f\" $5M target - Amount per child: ${preschool_5m_amount}, Actual cost: ${preschool_5m_ctc.sum():,.0f}\")\n", + "print(f\" $10M target - Amount per child: ${preschool_10m_amount}, Actual cost: ${preschool_10m_ctc.sum():,.0f}\")\n", + "print(f\" $15M target - Amount per child: ${preschool_15m_amount}, Actual cost: ${preschool_15m_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def create_under_6_reform(amount_per_child):\n", + " \"\"\"Create reform for children under 6 (current age threshold)\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": amount_per_child\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": 6\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "# Adjusted estimates based on actual costs\n", + "under6_5m_amount = 120 # Estimate for $5M\n", + "under6_10m_amount = 235 # Estimate for $10M\n", + "under6_15m_amount = 350 # Estimate for $15M\n", + "\n", + "under6_5m_reform = create_under_6_reform(under6_5m_amount)\n", + "under6_10m_reform = create_under_6_reform(under6_10m_amount)\n", + "under6_15m_reform = create_under_6_reform(under6_15m_amount)\n", + "\n", + "under6_5m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under6_5m_reform)\n", + "under6_10m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under6_10m_reform)\n", + "under6_15m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under6_15m_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform 2: Early Childhood (Under 6)\n", + " $5M target - Amount per child: $120, Actual cost: $5,104,786\n", + " $10M target - Amount per child: $235, Actual cost: $10,019,970\n", + " $15M target - Amount per child: $350, Actual cost: $14,957,336\n" + ] + } + ], + "source": [ + "# Calculate costs for under 6 reforms\n", + "under6_5m_ctc = under6_5m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under6_10m_ctc = under6_10m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under6_15m_ctc = under6_15m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "print(\"Reform 2: Early Childhood (Under 6)\")\n", + "print(f\" $5M target - Amount per child: ${under6_5m_amount}, Actual cost: ${under6_5m_ctc.sum():,.0f}\")\n", + "print(f\" $10M target - Amount per child: ${under6_10m_amount}, Actual cost: ${under6_10m_ctc.sum():,.0f}\")\n", + "print(f\" $15M target - Amount per child: ${under6_15m_amount}, Actual cost: ${under6_15m_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def create_under_18_reform(amount_per_child):\n", + " \"\"\"Create reform for all children under 18\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": amount_per_child\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": 18\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "# Adjusted estimates based on actual costs\n", + "under18_5m_amount = 45 # Estimate for $5M\n", + "under18_10m_amount = 85 # Estimate for $10M\n", + "under18_15m_amount = 125 # Estimate for $15M\n", + "\n", + "under18_5m_reform = create_under_18_reform(under18_5m_amount)\n", + "under18_10m_reform = create_under_18_reform(under18_10m_amount)\n", + "under18_15m_reform = create_under_18_reform(under18_15m_amount)\n", + "\n", + "under18_5m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under18_5m_reform)\n", + "under18_10m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under18_10m_reform)\n", + "under18_15m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under18_15m_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform 3: All Children (Under 18)\n", + " $5M target - Amount per child: $45, Actual cost: $5,302,008\n", + " $10M target - Amount per child: $85, Actual cost: $10,026,294\n", + " $15M target - Amount per child: $125, Actual cost: $14,760,191\n" + ] + } + ], + "source": [ + "# Calculate costs for under 18 reforms\n", + "under18_5m_ctc = under18_5m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under18_10m_ctc = under18_10m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under18_15m_ctc = under18_15m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "print(\"Reform 3: All Children (Under 18)\")\n", + "print(f\" $5M target - Amount per child: ${under18_5m_amount}, Actual cost: ${under18_5m_ctc.sum():,.0f}\")\n", + "print(f\" $10M target - Amount per child: ${under18_10m_amount}, Actual cost: ${under18_10m_ctc.sum():,.0f}\")\n", + "print(f\" $15M target - Amount per child: ${under18_15m_amount}, Actual cost: ${under18_15m_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def create_preschool_reform_lower_threshold(amount_per_child):\n", + " \"\"\"Create reform for children under 4 with lower income thresholds\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": amount_per_child\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": 4\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2025-01-01.2100-12-31\": 120_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2025-01-01.2100-12-31\": 60_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "# Adjusted amounts based on target costs\n", + "preschool_lower_5m_amount = 195 # Estimate for $5M\n", + "preschool_lower_10m_amount = 390 # Estimate for $10M\n", + "preschool_lower_15m_amount = 570 # Estimate for $15M\n", + "\n", + "preschool_lower_5m_reform = create_preschool_reform_lower_threshold(preschool_lower_5m_amount)\n", + "preschool_lower_10m_reform = create_preschool_reform_lower_threshold(preschool_lower_10m_amount)\n", + "preschool_lower_15m_reform = create_preschool_reform_lower_threshold(preschool_lower_15m_amount)\n", + "\n", + "preschool_lower_5m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=preschool_lower_5m_reform)\n", + "preschool_lower_10m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=preschool_lower_10m_reform)\n", + "preschool_lower_15m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=preschool_lower_15m_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform 1B: Preschool Age (Under 4) - Lower Income Thresholds\n", + " $5M target - Amount per child: $195, Actual cost: $4,950,844\n", + " $10M target - Amount per child: $390, Actual cost: $9,977,008\n", + " $15M target - Amount per child: $570, Actual cost: $14,794,358\n" + ] + } + ], + "source": [ + "# Calculate costs for preschool reforms with lower thresholds\n", + "preschool_lower_5m_ctc = preschool_lower_5m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "preschool_lower_10m_ctc = preschool_lower_10m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "preschool_lower_15m_ctc = preschool_lower_15m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "print(\"Reform 1B: Preschool Age (Under 4) - Lower Income Thresholds\")\n", + "print(f\" $5M target - Amount per child: ${preschool_lower_5m_amount}, Actual cost: ${preschool_lower_5m_ctc.sum():,.0f}\")\n", + "print(f\" $10M target - Amount per child: ${preschool_lower_10m_amount}, Actual cost: ${preschool_lower_10m_ctc.sum():,.0f}\")\n", + "print(f\" $15M target - Amount per child: ${preschool_lower_15m_amount}, Actual cost: ${preschool_lower_15m_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def create_under_6_reform_lower_threshold(amount_per_child):\n", + " \"\"\"Create reform for children under 6 with lower income thresholds\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": amount_per_child\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": 6\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2025-01-01.2100-12-31\": 120_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2025-01-01.2100-12-31\": 60_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "# Adjusted amounts based on target costs\n", + "under6_lower_5m_amount = 130 # Estimate for $5M\n", + "under6_lower_10m_amount = 265 # Estimate for $10M\n", + "under6_lower_15m_amount = 385 # Estimate for $15M\n", + "\n", + "under6_lower_5m_reform = create_under_6_reform_lower_threshold(under6_lower_5m_amount)\n", + "under6_lower_10m_reform = create_under_6_reform_lower_threshold(under6_lower_10m_amount)\n", + "under6_lower_15m_reform = create_under_6_reform_lower_threshold(under6_lower_15m_amount)\n", + "\n", + "under6_lower_5m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under6_lower_5m_reform)\n", + "under6_lower_10m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under6_lower_10m_reform)\n", + "under6_lower_15m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under6_lower_15m_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform 2B: Early Childhood (Under 6) - Lower Income Thresholds\n", + " $5M target - Amount per child: $130, Actual cost: $4,910,300\n", + " $10M target - Amount per child: $265, Actual cost: $10,060,217\n", + " $15M target - Amount per child: $385, Actual cost: $14,728,679\n" + ] + } + ], + "source": [ + "# Calculate costs for under 6 reforms with lower thresholds\n", + "under6_lower_5m_ctc = under6_lower_5m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under6_lower_10m_ctc = under6_lower_10m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under6_lower_15m_ctc = under6_lower_15m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "print(\"Reform 2B: Early Childhood (Under 6) - Lower Income Thresholds\")\n", + "print(f\" $5M target - Amount per child: ${under6_lower_5m_amount}, Actual cost: ${under6_lower_5m_ctc.sum():,.0f}\")\n", + "print(f\" $10M target - Amount per child: ${under6_lower_10m_amount}, Actual cost: ${under6_lower_10m_ctc.sum():,.0f}\")\n", + "print(f\" $15M target - Amount per child: ${under6_lower_15m_amount}, Actual cost: ${under6_lower_15m_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "def create_under_18_reform_lower_threshold(amount_per_child):\n", + " \"\"\"Create reform for all children under 18 with lower income thresholds\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": amount_per_child\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": 18\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2025-01-01.2100-12-31\": 120_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2025-01-01.2100-12-31\": 60_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2025-01-01.2100-12-31\": 80_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "# Adjusted amounts based on target costs\n", + "under18_lower_5m_amount = 50 # Estimate for $5M\n", + "under18_lower_10m_amount = 95 # Estimate for $10M\n", + "under18_lower_15m_amount = 145 # Estimate for $15M\n", + "\n", + "under18_lower_5m_reform = create_under_18_reform_lower_threshold(under18_lower_5m_amount)\n", + "under18_lower_10m_reform = create_under_18_reform_lower_threshold(under18_lower_10m_amount)\n", + "under18_lower_15m_reform = create_under_18_reform_lower_threshold(under18_lower_15m_amount)\n", + "\n", + "under18_lower_5m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under18_lower_5m_reform)\n", + "under18_lower_10m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under18_lower_10m_reform)\n", + "under18_lower_15m_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=under18_lower_15m_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform 3B: All Children (Under 18) - Lower Income Thresholds\n", + " $5M target - Amount per child: $50, Actual cost: $5,147,592\n", + " $10M target - Amount per child: $95, Actual cost: $9,823,450\n", + " $15M target - Amount per child: $145, Actual cost: $15,059,910\n" + ] + } + ], + "source": [ + "# Calculate costs for under 18 reforms with lower thresholds\n", + "under18_lower_5m_ctc = under18_lower_5m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under18_lower_10m_ctc = under18_lower_10m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "under18_lower_15m_ctc = under18_lower_15m_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "print(\"Reform 3B: All Children (Under 18) - Lower Income Thresholds\")\n", + "print(f\" $5M target - Amount per child: ${under18_lower_5m_amount}, Actual cost: ${under18_lower_5m_ctc.sum():,.0f}\")\n", + "print(f\" $10M target - Amount per child: ${under18_lower_10m_amount}, Actual cost: ${under18_lower_10m_ctc.sum():,.0f}\")\n", + "print(f\" $15M target - Amount per child: ${under18_lower_15m_amount}, Actual cost: ${under18_lower_15m_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "DC Child Tax Credit Reform Summary\n", + "====================================================================================================\n", + " Reform Age Group Income Threshold Target Cost Amount per Child Actual Cost\n", + " Baseline (Current) Under 6 Current Current $420 $17,971,915\n", + " Reform 1: Preschool Under 4 Standard $5M $175 $5,017,059\n", + " Reform 1: Preschool Under 4 Standard $10M $350 $10,068,140\n", + " Reform 1: Preschool Under 4 Standard $15M $525 $15,148,594\n", + " Reform 1B: Preschool Under 4 Half $5M $195 $4,950,844\n", + " Reform 1B: Preschool Under 4 Half $10M $390 $9,977,008\n", + " Reform 1B: Preschool Under 4 Half $15M $570 $14,794,358\n", + " Reform 2: Early Childhood Under 6 Standard $5M $120 $5,104,786\n", + " Reform 2: Early Childhood Under 6 Standard $10M $235 $10,019,970\n", + " Reform 2: Early Childhood Under 6 Standard $15M $350 $14,957,336\n", + "Reform 2B: Early Childhood Under 6 Half $5M $130 $4,910,300\n", + "Reform 2B: Early Childhood Under 6 Half $10M $265 $10,060,217\n", + "Reform 2B: Early Childhood Under 6 Half $15M $385 $14,728,679\n", + " Reform 3: All Children Under 18 Standard $5M $45 $5,302,008\n", + " Reform 3: All Children Under 18 Standard $10M $85 $10,026,294\n", + " Reform 3: All Children Under 18 Standard $15M $125 $14,760,191\n", + " Reform 3B: All Children Under 18 Half $5M $50 $5,147,592\n", + " Reform 3B: All Children Under 18 Half $10M $95 $9,823,450\n", + " Reform 3B: All Children Under 18 Half $15M $145 $15,059,910\n" + ] + } + ], + "source": [ + "# Create summary DataFrame including all reforms\n", + "summary_data = [\n", + " {\n", + " \"Reform\": \"Baseline (Current)\",\n", + " \"Age Group\": \"Under 6\",\n", + " \"Income Threshold\": \"Current\",\n", + " \"Target Cost\": \"Current\",\n", + " \"Amount per Child\": \"$420\",\n", + " \"Actual Cost\": f\"${current_cost:,.0f}\"\n", + " },\n", + " # Reform 1: Preschool\n", + " {\n", + " \"Reform\": \"Reform 1: Preschool\",\n", + " \"Age Group\": \"Under 4\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$5M\",\n", + " \"Amount per Child\": f\"${preschool_5m_amount}\",\n", + " \"Actual Cost\": f\"${preschool_5m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 1: Preschool\",\n", + " \"Age Group\": \"Under 4\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$10M\",\n", + " \"Amount per Child\": f\"${preschool_10m_amount}\",\n", + " \"Actual Cost\": f\"${preschool_10m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 1: Preschool\",\n", + " \"Age Group\": \"Under 4\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$15M\",\n", + " \"Amount per Child\": f\"${preschool_15m_amount}\",\n", + " \"Actual Cost\": f\"${preschool_15m_ctc.sum():,.0f}\"\n", + " },\n", + " # Reform 1B: Preschool Lower Threshold\n", + " {\n", + " \"Reform\": \"Reform 1B: Preschool\",\n", + " \"Age Group\": \"Under 4\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$5M\",\n", + " \"Amount per Child\": f\"${preschool_lower_5m_amount}\",\n", + " \"Actual Cost\": f\"${preschool_lower_5m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 1B: Preschool\",\n", + " \"Age Group\": \"Under 4\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$10M\",\n", + " \"Amount per Child\": f\"${preschool_lower_10m_amount}\",\n", + " \"Actual Cost\": f\"${preschool_lower_10m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 1B: Preschool\",\n", + " \"Age Group\": \"Under 4\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$15M\",\n", + " \"Amount per Child\": f\"${preschool_lower_15m_amount}\",\n", + " \"Actual Cost\": f\"${preschool_lower_15m_ctc.sum():,.0f}\"\n", + " },\n", + " # Reform 2: Early Childhood\n", + " {\n", + " \"Reform\": \"Reform 2: Early Childhood\",\n", + " \"Age Group\": \"Under 6\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$5M\",\n", + " \"Amount per Child\": f\"${under6_5m_amount}\",\n", + " \"Actual Cost\": f\"${under6_5m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 2: Early Childhood\",\n", + " \"Age Group\": \"Under 6\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$10M\",\n", + " \"Amount per Child\": f\"${under6_10m_amount}\",\n", + " \"Actual Cost\": f\"${under6_10m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 2: Early Childhood\",\n", + " \"Age Group\": \"Under 6\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$15M\",\n", + " \"Amount per Child\": f\"${under6_15m_amount}\",\n", + " \"Actual Cost\": f\"${under6_15m_ctc.sum():,.0f}\"\n", + " },\n", + " # Reform 2B: Early Childhood Lower Threshold\n", + " {\n", + " \"Reform\": \"Reform 2B: Early Childhood\",\n", + " \"Age Group\": \"Under 6\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$5M\",\n", + " \"Amount per Child\": f\"${under6_lower_5m_amount}\",\n", + " \"Actual Cost\": f\"${under6_lower_5m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 2B: Early Childhood\",\n", + " \"Age Group\": \"Under 6\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$10M\",\n", + " \"Amount per Child\": f\"${under6_lower_10m_amount}\",\n", + " \"Actual Cost\": f\"${under6_lower_10m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 2B: Early Childhood\",\n", + " \"Age Group\": \"Under 6\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$15M\",\n", + " \"Amount per Child\": f\"${under6_lower_15m_amount}\",\n", + " \"Actual Cost\": f\"${under6_lower_15m_ctc.sum():,.0f}\"\n", + " },\n", + " # Reform 3: All Children\n", + " {\n", + " \"Reform\": \"Reform 3: All Children\",\n", + " \"Age Group\": \"Under 18\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$5M\",\n", + " \"Amount per Child\": f\"${under18_5m_amount}\",\n", + " \"Actual Cost\": f\"${under18_5m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 3: All Children\",\n", + " \"Age Group\": \"Under 18\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$10M\",\n", + " \"Amount per Child\": f\"${under18_10m_amount}\",\n", + " \"Actual Cost\": f\"${under18_10m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 3: All Children\",\n", + " \"Age Group\": \"Under 18\",\n", + " \"Income Threshold\": \"Standard\",\n", + " \"Target Cost\": \"$15M\",\n", + " \"Amount per Child\": f\"${under18_15m_amount}\",\n", + " \"Actual Cost\": f\"${under18_15m_ctc.sum():,.0f}\"\n", + " },\n", + " # Reform 3B: All Children Lower Threshold\n", + " {\n", + " \"Reform\": \"Reform 3B: All Children\",\n", + " \"Age Group\": \"Under 18\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$5M\",\n", + " \"Amount per Child\": f\"${under18_lower_5m_amount}\",\n", + " \"Actual Cost\": f\"${under18_lower_5m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 3B: All Children\",\n", + " \"Age Group\": \"Under 18\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$10M\",\n", + " \"Amount per Child\": f\"${under18_lower_10m_amount}\",\n", + " \"Actual Cost\": f\"${under18_lower_10m_ctc.sum():,.0f}\"\n", + " },\n", + " {\n", + " \"Reform\": \"Reform 3B: All Children\",\n", + " \"Age Group\": \"Under 18\",\n", + " \"Income Threshold\": \"Half\",\n", + " \"Target Cost\": \"$15M\",\n", + " \"Amount per Child\": f\"${under18_lower_15m_amount}\",\n", + " \"Actual Cost\": f\"${under18_lower_15m_ctc.sum():,.0f}\"\n", + " }\n", + "]\n", + "\n", + "summary_df = pd.DataFrame(summary_data)\n", + "print(\"\\nDC Child Tax Credit Reform Summary\")\n", + "print(\"=\"*100)\n", + "print(summary_df.to_string(index=False))" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Exported to dc_ctc_reform_summary.csv\n" + ] + } + ], + "source": [ + "# Export to CSV\n", + "summary_df.to_csv(\"dc_ctc_reform_summary.csv\", index=False)\n", + "print(\"\\nExported to dc_ctc_reform_summary.csv\")" + ] + } + ], + "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": 4 +} diff --git a/us/states/dc/ctc_reforms_comprehensive.ipynb b/us/states/dc/ctc_reforms_comprehensive.ipynb new file mode 100644 index 0000000..6b2600b --- /dev/null +++ b/us/states/dc/ctc_reforms_comprehensive.ipynb @@ -0,0 +1,783 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DC Child Tax Credit Comprehensive Reform Analysis\n", + "\n", + "This notebook analyzes DC CTC reforms with various parameter combinations:\n", + "- Age thresholds: Under 6, 8, 12, or 18\n", + "- Amount per child: $420, $1,000, $1,500\n", + "- Child limit: 3 or unlimited\n", + "- Phase-out amount: $20, $50, $100 (reduction per $1,000 over threshold)\n", + "- Lower phase-out thresholds: $50k (HoH/Single/Surviving), $75k (Joint), $37.5k (Separate)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\dtsax\\envs\\pe\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np\n", + "import itertools" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Load DC dataset\n", + "sim = Microsimulation(dataset='hf://policyengine/test/DC.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Baseline: Zero Out Current DC CTC\n", + "\n", + "Current DC CTC provides $420 per child under age 6, with income phase-outs starting at $160k (single)/$240k (joint)." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def create_baseline_reform():\n", + " \"\"\"Zero out the existing DC CTC\"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": 0\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + "\n", + "baseline_reform = create_baseline_reform()\n", + "baseline_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=baseline_reform)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Current DC CTC annual cost: $17,971,915\n", + "Baseline DC CTC cost (zeroed out): $0\n" + ] + } + ], + "source": [ + "# Calculate baseline cost\n", + "current_ctc = sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "baseline_ctc = baseline_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + "\n", + "current_cost = current_ctc.sum()\n", + "print(f\"Current DC CTC annual cost: ${current_cost:,.0f}\")\n", + "print(f\"Baseline DC CTC cost (zeroed out): ${baseline_ctc.sum():,.0f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reform Scenarios\n", + "\n", + "Testing all combinations of reform parameters." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def create_reform(age_threshold, amount_per_child, child_cap, phase_out_amount):\n", + " \"\"\"\n", + " Create a DC CTC reform with specified parameters.\n", + " \n", + " Parameters:\n", + " - age_threshold: Maximum age for eligible children (6, 8, 12, or 18)\n", + " - amount_per_child: Dollar amount per child (420, 1000, or 1500)\n", + " - child_cap: Maximum number of children (3 or 999 for unlimited)\n", + " - phase_out_amount: Reduction per $1,000 over income threshold (20, 50, or 100)\n", + " \n", + " All reforms use lower income thresholds:\n", + " - Single/HoH/Surviving Spouse: $50,000\n", + " - Joint: $75,000\n", + " - Separate: $37,500\n", + " \"\"\"\n", + " return Reform.from_dict(\n", + " {\n", + " \"gov.states.dc.tax.income.credits.ctc.amount\": {\n", + " \"2025-01-01.2100-12-31\": amount_per_child\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.age_threshold\": {\n", + " \"2025-01-01.2100-12-31\": age_threshold\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.child.child_cap\": {\n", + " \"2025-01-01.2100-12-31\": child_cap\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.phase_out.amount\": {\n", + " \"2025-01-01.2100-12-31\": phase_out_amount\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SINGLE\": {\n", + " \"2025-01-01.2100-12-31\": 50_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.JOINT\": {\n", + " \"2025-01-01.2100-12-31\": 75_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SEPARATE\": {\n", + " \"2025-01-01.2100-12-31\": 37_500\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.HEAD_OF_HOUSEHOLD\": {\n", + " \"2025-01-01.2100-12-31\": 50_000\n", + " },\n", + " \"gov.states.dc.tax.income.credits.ctc.income_threshold.SURVIVING_SPOUSE\": {\n", + " \"2025-01-01.2100-12-31\": 50_000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total number of reform scenarios: 72\n" + ] + } + ], + "source": [ + "# Define parameter combinations\n", + "age_thresholds = [6, 8, 12, 18]\n", + "amounts = [420, 1000, 1500]\n", + "child_caps = [3, 999] # 999 represents unlimited\n", + "phase_out_amounts = [20, 50, 100]\n", + "\n", + "# Generate all combinations\n", + "combinations = list(itertools.product(age_thresholds, amounts, child_caps, phase_out_amounts))\n", + "print(f\"Total number of reform scenarios: {len(combinations)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running reform 1/72: Age<6, Amount=$420, Cap=3, PhaseOut=$20\n", + "Running reform 2/72: Age<6, Amount=$420, Cap=3, PhaseOut=$50\n", + "Running reform 3/72: Age<6, Amount=$420, Cap=3, PhaseOut=$100\n", + "Running reform 4/72: Age<6, Amount=$420, Cap=None, PhaseOut=$20\n", + "Running reform 5/72: Age<6, Amount=$420, Cap=None, PhaseOut=$50\n", + "Running reform 6/72: Age<6, Amount=$420, Cap=None, PhaseOut=$100\n", + "Running reform 7/72: Age<6, Amount=$1000, Cap=3, PhaseOut=$20\n", + "Running reform 8/72: Age<6, Amount=$1000, Cap=3, PhaseOut=$50\n", + "Running reform 9/72: Age<6, Amount=$1000, Cap=3, PhaseOut=$100\n", + "Running reform 10/72: Age<6, Amount=$1000, Cap=None, PhaseOut=$20\n", + "Running reform 11/72: Age<6, Amount=$1000, Cap=None, PhaseOut=$50\n", + "Running reform 12/72: Age<6, Amount=$1000, Cap=None, PhaseOut=$100\n", + "Running reform 13/72: Age<6, Amount=$1500, Cap=3, PhaseOut=$20\n", + "Running reform 14/72: Age<6, Amount=$1500, Cap=3, PhaseOut=$50\n", + "Running reform 15/72: Age<6, Amount=$1500, Cap=3, PhaseOut=$100\n", + "Running reform 16/72: Age<6, Amount=$1500, Cap=None, PhaseOut=$20\n", + "Running reform 17/72: Age<6, Amount=$1500, Cap=None, PhaseOut=$50\n", + "Running reform 18/72: Age<6, Amount=$1500, Cap=None, PhaseOut=$100\n", + "Running reform 19/72: Age<8, Amount=$420, Cap=3, PhaseOut=$20\n", + "Running reform 20/72: Age<8, Amount=$420, Cap=3, PhaseOut=$50\n", + "Running reform 21/72: Age<8, Amount=$420, Cap=3, PhaseOut=$100\n", + "Running reform 22/72: Age<8, Amount=$420, Cap=None, PhaseOut=$20\n", + "Running reform 23/72: Age<8, Amount=$420, Cap=None, PhaseOut=$50\n", + "Running reform 24/72: Age<8, Amount=$420, Cap=None, PhaseOut=$100\n", + "Running reform 25/72: Age<8, Amount=$1000, Cap=3, PhaseOut=$20\n", + "Running reform 26/72: Age<8, Amount=$1000, Cap=3, PhaseOut=$50\n", + "Running reform 27/72: Age<8, Amount=$1000, Cap=3, PhaseOut=$100\n", + "Running reform 28/72: Age<8, Amount=$1000, Cap=None, PhaseOut=$20\n", + "Running reform 29/72: Age<8, Amount=$1000, Cap=None, PhaseOut=$50\n", + "Running reform 30/72: Age<8, Amount=$1000, Cap=None, PhaseOut=$100\n", + "Running reform 31/72: Age<8, Amount=$1500, Cap=3, PhaseOut=$20\n", + "Running reform 32/72: Age<8, Amount=$1500, Cap=3, PhaseOut=$50\n", + "Running reform 33/72: Age<8, Amount=$1500, Cap=3, PhaseOut=$100\n", + "Running reform 34/72: Age<8, Amount=$1500, Cap=None, PhaseOut=$20\n", + "Running reform 35/72: Age<8, Amount=$1500, Cap=None, PhaseOut=$50\n", + "Running reform 36/72: Age<8, Amount=$1500, Cap=None, PhaseOut=$100\n", + "Running reform 37/72: Age<12, Amount=$420, Cap=3, PhaseOut=$20\n", + "Running reform 38/72: Age<12, Amount=$420, Cap=3, PhaseOut=$50\n", + "Running reform 39/72: Age<12, Amount=$420, Cap=3, PhaseOut=$100\n", + "Running reform 40/72: Age<12, Amount=$420, Cap=None, PhaseOut=$20\n", + "Running reform 41/72: Age<12, Amount=$420, Cap=None, PhaseOut=$50\n", + "Running reform 42/72: Age<12, Amount=$420, Cap=None, PhaseOut=$100\n", + "Running reform 43/72: Age<12, Amount=$1000, Cap=3, PhaseOut=$20\n", + "Running reform 44/72: Age<12, Amount=$1000, Cap=3, PhaseOut=$50\n", + "Running reform 45/72: Age<12, Amount=$1000, Cap=3, PhaseOut=$100\n", + "Running reform 46/72: Age<12, Amount=$1000, Cap=None, PhaseOut=$20\n", + "Running reform 47/72: Age<12, Amount=$1000, Cap=None, PhaseOut=$50\n", + "Running reform 48/72: Age<12, Amount=$1000, Cap=None, PhaseOut=$100\n", + "Running reform 49/72: Age<12, Amount=$1500, Cap=3, PhaseOut=$20\n", + "Running reform 50/72: Age<12, Amount=$1500, Cap=3, PhaseOut=$50\n", + "Running reform 51/72: Age<12, Amount=$1500, Cap=3, PhaseOut=$100\n", + "Running reform 52/72: Age<12, Amount=$1500, Cap=None, PhaseOut=$20\n", + "Running reform 53/72: Age<12, Amount=$1500, Cap=None, PhaseOut=$50\n", + "Running reform 54/72: Age<12, Amount=$1500, Cap=None, PhaseOut=$100\n", + "Running reform 55/72: Age<18, Amount=$420, Cap=3, PhaseOut=$20\n", + "Running reform 56/72: Age<18, Amount=$420, Cap=3, PhaseOut=$50\n", + "Running reform 57/72: Age<18, Amount=$420, Cap=3, PhaseOut=$100\n", + "Running reform 58/72: Age<18, Amount=$420, Cap=None, PhaseOut=$20\n", + "Running reform 59/72: Age<18, Amount=$420, Cap=None, PhaseOut=$50\n", + "Running reform 60/72: Age<18, Amount=$420, Cap=None, PhaseOut=$100\n", + "Running reform 61/72: Age<18, Amount=$1000, Cap=3, PhaseOut=$20\n", + "Running reform 62/72: Age<18, Amount=$1000, Cap=3, PhaseOut=$50\n", + "Running reform 63/72: Age<18, Amount=$1000, Cap=3, PhaseOut=$100\n", + "Running reform 64/72: Age<18, Amount=$1000, Cap=None, PhaseOut=$20\n", + "Running reform 65/72: Age<18, Amount=$1000, Cap=None, PhaseOut=$50\n", + "Running reform 66/72: Age<18, Amount=$1000, Cap=None, PhaseOut=$100\n", + "Running reform 67/72: Age<18, Amount=$1500, Cap=3, PhaseOut=$20\n", + "Running reform 68/72: Age<18, Amount=$1500, Cap=3, PhaseOut=$50\n", + "Running reform 69/72: Age<18, Amount=$1500, Cap=3, PhaseOut=$100\n", + "Running reform 70/72: Age<18, Amount=$1500, Cap=None, PhaseOut=$20\n", + "Running reform 71/72: Age<18, Amount=$1500, Cap=None, PhaseOut=$50\n", + "Running reform 72/72: Age<18, Amount=$1500, Cap=None, PhaseOut=$100\n", + "\n", + "All reforms completed!\n" + ] + } + ], + "source": [ + "# Run all reforms and collect results\n", + "results = []\n", + "\n", + "for i, (age, amount, cap, phase_out) in enumerate(combinations, 1):\n", + " print(f\"Running reform {i}/{len(combinations)}: Age<{age}, Amount=${amount}, Cap={cap if cap < 999 else 'None'}, PhaseOut=${phase_out}\")\n", + " \n", + " reform = create_reform(age, amount, cap, phase_out)\n", + " reform_sim = Microsimulation(dataset='hf://policyengine/test/DC.h5', reform=reform)\n", + " reform_ctc = reform_sim.calculate(\"dc_ctc\", period=2025, map_to=\"household\")\n", + " total_cost = reform_ctc.sum()\n", + " \n", + " results.append({\n", + " \"Age Threshold\": f\"Under {age}\",\n", + " \"Amount per Child\": f\"${amount:,}\",\n", + " \"Child Limit\": str(cap) if cap < 999 else \"None\",\n", + " \"Phase-out Amount\": f\"${phase_out}\",\n", + " \"Annual Cost\": f\"${total_cost:,.0f}\",\n", + " \"Cost (Numeric)\": total_cost,\n", + " \"Age (Numeric)\": age,\n", + " \"Amount (Numeric)\": amount,\n", + " \"Cap (Numeric)\": cap,\n", + " \"Phase-out (Numeric)\": phase_out\n", + " })\n", + "\n", + "print(\"\\nAll reforms completed!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "========================================================================================================================\n", + "DC CHILD TAX CREDIT REFORM SCENARIOS\n", + "Lower Income Thresholds: $50k (Single/HoH/Surviving), $75k (Joint), $37.5k (Separate)\n", + "========================================================================================================================\n", + "Age Threshold Amount per Child Child Limit Phase-out Amount Annual Cost\n", + " Under 6 $420 3 $20 $14,320,670\n", + " Under 6 $420 3 $50 $13,841,326\n", + " Under 6 $420 3 $100 $13,615,555\n", + " Under 6 $420 None $20 $14,555,760\n", + " Under 6 $420 None $50 $14,076,416\n", + " Under 6 $420 None $100 $13,850,645\n", + " Under 6 $1,000 3 $20 $36,101,632\n", + " Under 6 $1,000 3 $50 $34,013,107\n", + " Under 6 $1,000 3 $100 $33,109,273\n", + " Under 6 $1,000 None $20 $36,661,372\n", + " Under 6 $1,000 None $50 $34,572,846\n", + " Under 6 $1,000 None $100 $33,669,012\n", + " Under 6 $1,500 3 $20 $56,226,654\n", + " Under 6 $1,500 3 $50 $52,092,604\n", + " Under 6 $1,500 3 $100 $50,344,382\n", + " Under 6 $1,500 None $20 $57,066,263\n", + " Under 6 $1,500 None $50 $52,932,212\n", + " Under 6 $1,500 None $100 $51,183,991\n", + " Under 8 $420 3 $20 $18,751,082\n", + " Under 8 $420 3 $50 $17,958,771\n", + " Under 8 $420 3 $100 $17,637,315\n", + " Under 8 $420 None $20 $19,107,110\n", + " Under 8 $420 None $50 $18,314,799\n", + " Under 8 $420 None $100 $17,993,343\n", + " Under 8 $1,000 3 $20 $47,539,975\n", + " Under 8 $1,000 3 $50 $44,514,242\n", + " Under 8 $1,000 3 $100 $43,070,571\n", + " Under 8 $1,000 None $20 $48,387,661\n", + " Under 8 $1,000 None $50 $45,361,928\n", + " Under 8 $1,000 None $100 $43,918,257\n", + " Under 8 $1,500 3 $20 $74,144,075\n", + " Under 8 $1,500 3 $50 $68,512,361\n", + " Under 8 $1,500 3 $100 $65,765,723\n", + " Under 8 $1,500 None $20 $75,415,604\n", + " Under 8 $1,500 None $50 $69,783,890\n", + " Under 8 $1,500 None $100 $67,037,252\n", + " Under 12 $420 3 $20 $26,912,518\n", + " Under 12 $420 3 $50 $25,450,678\n", + " Under 12 $420 3 $100 $24,910,030\n", + " Under 12 $420 None $20 $28,476,680\n", + " Under 12 $420 None $50 $26,901,509\n", + " Under 12 $420 None $100 $26,313,513\n", + " Under 12 $1,000 3 $20 $68,648,053\n", + " Under 12 $1,000 3 $50 $63,852,646\n", + " Under 12 $1,000 3 $100 $61,119,811\n", + " Under 12 $1,000 None $20 $72,372,248\n", + " Under 12 $1,000 None $50 $67,576,840\n", + " Under 12 $1,000 None $100 $64,627,294\n", + " Under 12 $1,500 3 $20 $106,877,819\n", + " Under 12 $1,500 3 $50 $98,676,239\n", + " Under 12 $1,500 3 $100 $93,893,111\n", + " Under 12 $1,500 None $20 $112,464,111\n", + " Under 12 $1,500 None $50 $104,262,531\n", + " Under 12 $1,500 None $100 $99,438,296\n", + " Under 18 $420 3 $20 $39,362,370\n", + " Under 18 $420 3 $50 $37,038,891\n", + " Under 18 $420 3 $100 $36,180,594\n", + " Under 18 $420 None $20 $42,068,611\n", + " Under 18 $420 None $50 $39,591,351\n", + " Under 18 $420 None $100 $38,506,296\n", + " Under 18 $1,000 3 $20 $101,055,690\n", + " Under 18 $1,000 3 $50 $93,362,597\n", + " Under 18 $1,000 3 $100 $89,024,244\n", + " Under 18 $1,000 None $20 $107,513,605\n", + " Under 18 $1,000 None $50 $99,802,756\n", + " Under 18 $1,000 None $100 $95,192,601\n", + " Under 18 $1,500 3 $20 $157,496,839\n", + " Under 18 $1,500 3 $50 $144,690,176\n", + " Under 18 $1,500 3 $100 $137,036,196\n", + " Under 18 $1,500 None $20 $167,183,711\n", + " Under 18 $1,500 None $50 $154,370,886\n", + " Under 18 $1,500 None $100 $146,581,967\n", + "========================================================================================================================\n" + ] + } + ], + "source": [ + "# Create DataFrame and display results\n", + "df = pd.DataFrame(results)\n", + "\n", + "# Display table\n", + "print(\"\\n\" + \"=\"*120)\n", + "print(\"DC CHILD TAX CREDIT REFORM SCENARIOS\")\n", + "print(\"Lower Income Thresholds: $50k (Single/HoH/Surviving), $75k (Joint), $37.5k (Separate)\")\n", + "print(\"=\"*120)\n", + "print(df[['Age Threshold', 'Amount per Child', 'Child Limit', 'Phase-out Amount', 'Annual Cost']].to_string(index=False))\n", + "print(\"=\"*120)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Results exported to dc_ctc_reforms_comprehensive.csv\n" + ] + } + ], + "source": [ + "# Export to CSV\n", + "csv_filename = \"dc_ctc_reforms_comprehensive.csv\"\n", + "df[['Age Threshold', 'Amount per Child', 'Child Limit', 'Phase-out Amount', 'Annual Cost']].to_csv(csv_filename, index=False)\n", + "print(f\"\\nResults exported to {csv_filename}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "SUMMARY STATISTICS\n", + "Minimum cost: $13,615,555\n", + "Maximum cost: $167,183,711\n", + "Mean cost: $59,920,569\n", + "Median cost: $49,366,021\n" + ] + } + ], + "source": [ + "# Summary statistics\n", + "print(\"\\nSUMMARY STATISTICS\")\n", + "print(f\"Minimum cost: ${df['Cost (Numeric)'].min():,.0f}\")\n", + "print(f\"Maximum cost: ${df['Cost (Numeric)'].max():,.0f}\")\n", + "print(f\"Mean cost: ${df['Cost (Numeric)'].mean():,.0f}\")\n", + "print(f\"Median cost: ${df['Cost (Numeric)'].median():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RESULTS BY AGE THRESHOLD\n", + "\n", + "Under 6:\n", + "Amount per Child Child Limit Phase-out Amount Annual Cost\n", + " $420 3 $20 $14,320,670\n", + " $420 3 $50 $13,841,326\n", + " $420 3 $100 $13,615,555\n", + " $420 None $20 $14,555,760\n", + " $420 None $50 $14,076,416\n", + " $420 None $100 $13,850,645\n", + " $1,000 3 $20 $36,101,632\n", + " $1,000 3 $50 $34,013,107\n", + " $1,000 3 $100 $33,109,273\n", + " $1,000 None $20 $36,661,372\n", + " $1,000 None $50 $34,572,846\n", + " $1,000 None $100 $33,669,012\n", + " $1,500 3 $20 $56,226,654\n", + " $1,500 3 $50 $52,092,604\n", + " $1,500 3 $100 $50,344,382\n", + " $1,500 None $20 $57,066,263\n", + " $1,500 None $50 $52,932,212\n", + " $1,500 None $100 $51,183,991\n", + "\n", + "Under 8:\n", + "Amount per Child Child Limit Phase-out Amount Annual Cost\n", + " $420 3 $20 $18,751,082\n", + " $420 3 $50 $17,958,771\n", + " $420 3 $100 $17,637,315\n", + " $420 None $20 $19,107,110\n", + " $420 None $50 $18,314,799\n", + " $420 None $100 $17,993,343\n", + " $1,000 3 $20 $47,539,975\n", + " $1,000 3 $50 $44,514,242\n", + " $1,000 3 $100 $43,070,571\n", + " $1,000 None $20 $48,387,661\n", + " $1,000 None $50 $45,361,928\n", + " $1,000 None $100 $43,918,257\n", + " $1,500 3 $20 $74,144,075\n", + " $1,500 3 $50 $68,512,361\n", + " $1,500 3 $100 $65,765,723\n", + " $1,500 None $20 $75,415,604\n", + " $1,500 None $50 $69,783,890\n", + " $1,500 None $100 $67,037,252\n", + "\n", + "Under 12:\n", + "Amount per Child Child Limit Phase-out Amount Annual Cost\n", + " $420 3 $20 $26,912,518\n", + " $420 3 $50 $25,450,678\n", + " $420 3 $100 $24,910,030\n", + " $420 None $20 $28,476,680\n", + " $420 None $50 $26,901,509\n", + " $420 None $100 $26,313,513\n", + " $1,000 3 $20 $68,648,053\n", + " $1,000 3 $50 $63,852,646\n", + " $1,000 3 $100 $61,119,811\n", + " $1,000 None $20 $72,372,248\n", + " $1,000 None $50 $67,576,840\n", + " $1,000 None $100 $64,627,294\n", + " $1,500 3 $20 $106,877,819\n", + " $1,500 3 $50 $98,676,239\n", + " $1,500 3 $100 $93,893,111\n", + " $1,500 None $20 $112,464,111\n", + " $1,500 None $50 $104,262,531\n", + " $1,500 None $100 $99,438,296\n", + "\n", + "Under 18:\n", + "Amount per Child Child Limit Phase-out Amount Annual Cost\n", + " $420 3 $20 $39,362,370\n", + " $420 3 $50 $37,038,891\n", + " $420 3 $100 $36,180,594\n", + " $420 None $20 $42,068,611\n", + " $420 None $50 $39,591,351\n", + " $420 None $100 $38,506,296\n", + " $1,000 3 $20 $101,055,690\n", + " $1,000 3 $50 $93,362,597\n", + " $1,000 3 $100 $89,024,244\n", + " $1,000 None $20 $107,513,605\n", + " $1,000 None $50 $99,802,756\n", + " $1,000 None $100 $95,192,601\n", + " $1,500 3 $20 $157,496,839\n", + " $1,500 3 $50 $144,690,176\n", + " $1,500 3 $100 $137,036,196\n", + " $1,500 None $20 $167,183,711\n", + " $1,500 None $50 $154,370,886\n", + " $1,500 None $100 $146,581,967\n" + ] + } + ], + "source": [ + "# Show reforms grouped by age threshold\n", + "print(\"\\nRESULTS BY AGE THRESHOLD\")\n", + "for age in age_thresholds:\n", + " subset = df[df['Age (Numeric)'] == age]\n", + " print(f\"\\nUnder {age}:\")\n", + " print(subset[['Amount per Child', 'Child Limit', 'Phase-out Amount', 'Annual Cost']].to_string(index=False))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RESULTS BY AMOUNT PER CHILD\n", + "\n", + "$420 per child:\n", + "Age Threshold Child Limit Phase-out Amount Annual Cost\n", + " Under 6 3 $20 $14,320,670\n", + " Under 6 3 $50 $13,841,326\n", + " Under 6 3 $100 $13,615,555\n", + " Under 6 None $20 $14,555,760\n", + " Under 6 None $50 $14,076,416\n", + " Under 6 None $100 $13,850,645\n", + " Under 8 3 $20 $18,751,082\n", + " Under 8 3 $50 $17,958,771\n", + " Under 8 3 $100 $17,637,315\n", + " Under 8 None $20 $19,107,110\n", + " Under 8 None $50 $18,314,799\n", + " Under 8 None $100 $17,993,343\n", + " Under 12 3 $20 $26,912,518\n", + " Under 12 3 $50 $25,450,678\n", + " Under 12 3 $100 $24,910,030\n", + " Under 12 None $20 $28,476,680\n", + " Under 12 None $50 $26,901,509\n", + " Under 12 None $100 $26,313,513\n", + " Under 18 3 $20 $39,362,370\n", + " Under 18 3 $50 $37,038,891\n", + " Under 18 3 $100 $36,180,594\n", + " Under 18 None $20 $42,068,611\n", + " Under 18 None $50 $39,591,351\n", + " Under 18 None $100 $38,506,296\n", + "\n", + "$1,000 per child:\n", + "Age Threshold Child Limit Phase-out Amount Annual Cost\n", + " Under 6 3 $20 $36,101,632\n", + " Under 6 3 $50 $34,013,107\n", + " Under 6 3 $100 $33,109,273\n", + " Under 6 None $20 $36,661,372\n", + " Under 6 None $50 $34,572,846\n", + " Under 6 None $100 $33,669,012\n", + " Under 8 3 $20 $47,539,975\n", + " Under 8 3 $50 $44,514,242\n", + " Under 8 3 $100 $43,070,571\n", + " Under 8 None $20 $48,387,661\n", + " Under 8 None $50 $45,361,928\n", + " Under 8 None $100 $43,918,257\n", + " Under 12 3 $20 $68,648,053\n", + " Under 12 3 $50 $63,852,646\n", + " Under 12 3 $100 $61,119,811\n", + " Under 12 None $20 $72,372,248\n", + " Under 12 None $50 $67,576,840\n", + " Under 12 None $100 $64,627,294\n", + " Under 18 3 $20 $101,055,690\n", + " Under 18 3 $50 $93,362,597\n", + " Under 18 3 $100 $89,024,244\n", + " Under 18 None $20 $107,513,605\n", + " Under 18 None $50 $99,802,756\n", + " Under 18 None $100 $95,192,601\n", + "\n", + "$1,500 per child:\n", + "Age Threshold Child Limit Phase-out Amount Annual Cost\n", + " Under 6 3 $20 $56,226,654\n", + " Under 6 3 $50 $52,092,604\n", + " Under 6 3 $100 $50,344,382\n", + " Under 6 None $20 $57,066,263\n", + " Under 6 None $50 $52,932,212\n", + " Under 6 None $100 $51,183,991\n", + " Under 8 3 $20 $74,144,075\n", + " Under 8 3 $50 $68,512,361\n", + " Under 8 3 $100 $65,765,723\n", + " Under 8 None $20 $75,415,604\n", + " Under 8 None $50 $69,783,890\n", + " Under 8 None $100 $67,037,252\n", + " Under 12 3 $20 $106,877,819\n", + " Under 12 3 $50 $98,676,239\n", + " Under 12 3 $100 $93,893,111\n", + " Under 12 None $20 $112,464,111\n", + " Under 12 None $50 $104,262,531\n", + " Under 12 None $100 $99,438,296\n", + " Under 18 3 $20 $157,496,839\n", + " Under 18 3 $50 $144,690,176\n", + " Under 18 3 $100 $137,036,196\n", + " Under 18 None $20 $167,183,711\n", + " Under 18 None $50 $154,370,886\n", + " Under 18 None $100 $146,581,967\n" + ] + } + ], + "source": [ + "# Show reforms grouped by amount\n", + "print(\"\\nRESULTS BY AMOUNT PER CHILD\")\n", + "for amount in amounts:\n", + " subset = df[df['Amount (Numeric)'] == amount]\n", + " print(f\"\\n${amount:,} per child:\")\n", + " print(subset[['Age Threshold', 'Child Limit', 'Phase-out Amount', 'Annual Cost']].to_string(index=False))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "IMPACT OF CHILD CAP (3 vs Unlimited) by Age and Amount\n", + "Using Phase-out = $20\n", + "\n", + "Age<6, $420/child: Cap 3=$14,320,670, Unlimited=$14,555,760, Diff=$235,090 (+1.6%)\n", + "Age<6, $1,000/child: Cap 3=$36,101,632, Unlimited=$36,661,372, Diff=$559,739 (+1.6%)\n", + "Age<6, $1,500/child: Cap 3=$56,226,654, Unlimited=$57,066,263, Diff=$839,609 (+1.5%)\n", + "Age<8, $420/child: Cap 3=$18,751,082, Unlimited=$19,107,110, Diff=$356,028 (+1.9%)\n", + "Age<8, $1,000/child: Cap 3=$47,539,975, Unlimited=$48,387,661, Diff=$847,686 (+1.8%)\n", + "Age<8, $1,500/child: Cap 3=$74,144,075, Unlimited=$75,415,604, Diff=$1,271,529 (+1.7%)\n", + "Age<12, $420/child: Cap 3=$26,912,518, Unlimited=$28,476,680, Diff=$1,564,162 (+5.8%)\n", + "Age<12, $1,000/child: Cap 3=$68,648,053, Unlimited=$72,372,248, Diff=$3,724,195 (+5.4%)\n", + "Age<12, $1,500/child: Cap 3=$106,877,819, Unlimited=$112,464,111, Diff=$5,586,292 (+5.2%)\n", + "Age<18, $420/child: Cap 3=$39,362,370, Unlimited=$42,068,611, Diff=$2,706,241 (+6.9%)\n", + "Age<18, $1,000/child: Cap 3=$101,055,690, Unlimited=$107,513,605, Diff=$6,457,915 (+6.4%)\n", + "Age<18, $1,500/child: Cap 3=$157,496,839, Unlimited=$167,183,711, Diff=$9,686,873 (+6.2%)\n" + ] + } + ], + "source": [ + "# Compare effect of child cap\n", + "print(\"\\nIMPACT OF CHILD CAP (3 vs Unlimited) by Age and Amount\")\n", + "print(\"Using Phase-out = $20\\n\")\n", + "for age in age_thresholds:\n", + " for amount in amounts:\n", + " capped_data = df[(df['Age (Numeric)'] == age) & (df['Amount (Numeric)'] == amount) & (df['Cap (Numeric)'] == 3) & (df['Phase-out (Numeric)'] == 20)]\n", + " unlimited_data = df[(df['Age (Numeric)'] == age) & (df['Amount (Numeric)'] == amount) & (df['Cap (Numeric)'] == 999) & (df['Phase-out (Numeric)'] == 20)]\n", + " \n", + " if len(capped_data) > 0 and len(unlimited_data) > 0:\n", + " capped = capped_data['Cost (Numeric)'].values[0]\n", + " unlimited = unlimited_data['Cost (Numeric)'].values[0]\n", + " difference = unlimited - capped\n", + " pct_increase = (difference / capped) * 100 if capped > 0 else 0\n", + " print(f\"Age<{age}, ${amount:,}/child: Cap 3=${capped:,.0f}, Unlimited=${unlimited:,.0f}, Diff=${difference:,.0f} (+{pct_increase:.1f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "IMPACT OF PHASE-OUT AMOUNT ($20 vs $50 vs $100)\n", + "Using Child Cap = None\n", + "\n", + "Age<6, $420/child: $20=$14,555,760, $50=$14,076,416 (-$479,344), $100=$13,850,645 (-$705,115)\n", + "Age<6, $1,000/child: $20=$36,661,372, $50=$34,572,846 (-$2,088,525), $100=$33,669,012 (-$2,992,360)\n", + "Age<6, $1,500/child: $20=$57,066,263, $50=$52,932,212 (-$4,134,051), $100=$51,183,991 (-$5,882,273)\n", + "Age<8, $420/child: $20=$19,107,110, $50=$18,314,799 (-$792,311), $100=$17,993,343 (-$1,113,767)\n", + "Age<8, $1,000/child: $20=$48,387,661, $50=$45,361,928 (-$3,025,733), $100=$43,918,257 (-$4,469,404)\n", + "Age<8, $1,500/child: $20=$75,415,604, $50=$69,783,890 (-$5,631,714), $100=$67,037,252 (-$8,378,352)\n", + "Age<12, $420/child: $20=$28,476,680, $50=$26,901,509 (-$1,575,171), $100=$26,313,513 (-$2,163,167)\n", + "Age<12, $1,000/child: $20=$72,372,248, $50=$67,576,840 (-$4,795,408), $100=$64,627,294 (-$7,744,954)\n", + "Age<12, $1,500/child: $20=$112,464,111, $50=$104,262,531 (-$8,201,580), $100=$99,438,296 (-$13,025,815)\n", + "Age<18, $420/child: $20=$42,068,611, $50=$39,591,351 (-$2,477,260), $100=$38,506,296 (-$3,562,315)\n", + "Age<18, $1,000/child: $20=$107,513,605, $50=$99,802,756 (-$7,710,849), $100=$95,192,601 (-$12,321,004)\n", + "Age<18, $1,500/child: $20=$167,183,711, $50=$154,370,886 (-$12,812,826), $100=$146,581,967 (-$20,601,745)\n" + ] + } + ], + "source": [ + "# Compare effect of phase-out amount\n", + "print(\"\\nIMPACT OF PHASE-OUT AMOUNT ($20 vs $50 vs $100)\")\n", + "print(\"Using Child Cap = None\\n\")\n", + "for age in age_thresholds:\n", + " for amount in amounts:\n", + " phase20_data = df[(df['Age (Numeric)'] == age) & (df['Amount (Numeric)'] == amount) & (df['Cap (Numeric)'] == 999) & (df['Phase-out (Numeric)'] == 20)]\n", + " phase50_data = df[(df['Age (Numeric)'] == age) & (df['Amount (Numeric)'] == amount) & (df['Cap (Numeric)'] == 999) & (df['Phase-out (Numeric)'] == 50)]\n", + " phase100_data = df[(df['Age (Numeric)'] == age) & (df['Amount (Numeric)'] == amount) & (df['Cap (Numeric)'] == 999) & (df['Phase-out (Numeric)'] == 100)]\n", + " \n", + " if len(phase20_data) > 0 and len(phase50_data) > 0 and len(phase100_data) > 0:\n", + " cost20 = phase20_data['Cost (Numeric)'].values[0]\n", + " cost50 = phase50_data['Cost (Numeric)'].values[0]\n", + " cost100 = phase100_data['Cost (Numeric)'].values[0]\n", + " diff_50 = cost20 - cost50\n", + " diff_100 = cost20 - cost100\n", + " print(f\"Age<{age}, ${amount:,}/child: $20=${cost20:,.0f}, $50=${cost50:,.0f} (-${diff_50:,.0f}), $100=${cost100:,.0f} (-${diff_100:,.0f})\")" + ] + } + ], + "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": 4 +} diff --git a/us/states/dc/ctc_reforms_summary.csv b/us/states/dc/ctc_reforms_summary.csv new file mode 100644 index 0000000..f5ecd1f --- /dev/null +++ b/us/states/dc/ctc_reforms_summary.csv @@ -0,0 +1,20 @@ +Reform,Age Group,Income Threshold,Target Cost,Amount per Child,Actual Cost +Baseline (Current),Under 6,Current,Current,$420,"$19,300,033" +Reform 1: Preschool,Under 4,Standard,$5M,$135,"$4,919,397" +Reform 1: Preschool,Under 4,Standard,$10M,$270,"$9,838,793" +Reform 1: Preschool,Under 4,Standard,$15M,$405,"$14,758,190" +Reform 1B: Preschool,Under 4,Half,$5M,$270,"$9,838,793" +Reform 1B: Preschool,Under 4,Half,$10M,$540,"$19,677,586" +Reform 1B: Preschool,Under 4,Half,$15M,$810,"$29,516,379" +Reform 2: Early Childhood,Under 6,Standard,$5M,$110,"$5,054,771" +Reform 2: Early Childhood,Under 6,Standard,$10M,$220,"$10,109,541" +Reform 2: Early Childhood,Under 6,Standard,$15M,$330,"$15,164,312" +Reform 2B: Early Childhood,Under 6,Half,$5M,$220,"$10,109,541" +Reform 2B: Early Childhood,Under 6,Half,$10M,$440,"$20,219,082" +Reform 2B: Early Childhood,Under 6,Half,$15M,$660,"$30,328,624" +Reform 3: All Children,Under 18,Standard,$5M,$40,"$5,436,691" +Reform 3: All Children,Under 18,Standard,$10M,$80,"$10,873,382" +Reform 3: All Children,Under 18,Standard,$15M,$120,"$16,310,074" +Reform 3B: All Children,Under 18,Half,$5M,$80,"$10,873,382" +Reform 3B: All Children,Under 18,Half,$10M,$160,"$21,746,765" +Reform 3B: All Children,Under 18,Half,$15M,$240,"$32,620,147" diff --git a/us/states/dc/dataset_exploration.ipynb b/us/states/dc/dataset_exploration.ipynb new file mode 100644 index 0000000..770d540 --- /dev/null +++ b/us/states/dc/dataset_exploration.ipynb @@ -0,0 +1,395 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DC Dataset Exploration\n", + "\n", + "This notebook explores the DC dataset to understand household counts and income distribution." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [], + "source": [ + "# Load DC dataset\n", + "sim = Microsimulation(dataset='hf://policyengine/test/DC.h5')" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of households in dataset: 5,015\n", + "Household count (mapped): 220,449\n", + "Person count (mapped): 668,071\n" + ] + } + ], + "source": [ + "# Check dataset size\n", + "household_weight = sim.calculate(\"household_weight\", period=2025)\n", + "household_count = sim.calculate(\"household_count\", period=2025, map_to=\"household\")\n", + "person_count = sim.calculate(\"person_count\", period=2025, map_to=\"household\")\n", + "\n", + "print(f\"Number of households in dataset: {len(household_weight):,}\")\n", + "print(f\"Household count (mapped): {household_count.sum():,.0f}\")\n", + "print(f\"Person count (mapped): {person_count.sum():,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Income distribution:\n", + " Median AGI: $120,221\n", + " 75th percentile: $327,906\n", + " 90th percentile: $546,746\n", + " 95th percentile: $915,476\n", + " Max AGI: $3,229,514\n", + "\n", + "Households by income threshold:\n", + " Households over $80k: 135,495.6000130782\n", + " Households over $120k: 110,301.79662270736\n", + " Households over $160k: 91,709.29688587465\n", + " Households over $240k: 68,994.44427188052\n" + ] + } + ], + "source": [ + "# Check household income distribution (aggregate to household level using map_to)\n", + "agi = sim.calculate(\"adjusted_gross_income\", period=2025, map_to=\"household\")\n", + "print(f\"Income distribution:\")\n", + "print(f\" Median AGI: ${agi.median():,.0f}\")\n", + "print(f\" 75th percentile: ${agi.quantile(0.75):,.0f}\")\n", + "print(f\" 90th percentile: ${agi.quantile(0.90):,.0f}\")\n", + "print(f\" 95th percentile: ${agi.quantile(0.95):,.0f}\")\n", + "print(f\" Max AGI: ${agi.max():,.0f}\")\n", + "print(f\"\\nHouseholds by income threshold:\")\n", + "print(f\" Households over $80k: {(agi > 80_000).sum():,}\")\n", + "print(f\" Households over $120k: {(agi > 120_000).sum():,}\")\n", + "print(f\" Households over $160k: {(agi > 160_000).sum():,}\")\n", + "print(f\" Households over $240k: {(agi > 240_000).sum():,}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Households with children (weighted):\n", + " Total households with children: 70,469\n", + " Households with 1 child: 30,507\n", + " Households with 2 children: 23,254\n", + " Households with 3+ children: 16,708\n" + ] + } + ], + "source": [ + "# Check households with children (count at person level, aggregate to household)\n", + "is_child = sim.calculate(\"is_child\", period=2025, map_to=\"person\")\n", + "household_id = sim.calculate(\"household_id\", period=2025, map_to=\"person\")\n", + "household_weight = sim.calculate(\"household_weight\", period=2025, map_to=\"person\")\n", + "\n", + "# Create DataFrame for easier manipulation\n", + "df_households = pd.DataFrame({\n", + " 'household_id': household_id,\n", + " 'is_child': is_child,\n", + " 'household_weight': household_weight\n", + "})\n", + "\n", + "# Count children per household\n", + "children_per_household = df_households.groupby('household_id').agg({\n", + " 'is_child': 'sum',\n", + " 'household_weight': 'first' # household_weight is same for all members\n", + "}).reset_index()\n", + "\n", + "# Calculate weighted household counts\n", + "total_households_with_children = children_per_household[children_per_household['is_child'] > 0]['household_weight'].sum()\n", + "households_with_1_child = children_per_household[children_per_household['is_child'] == 1]['household_weight'].sum()\n", + "households_with_2_children = children_per_household[children_per_household['is_child'] == 2]['household_weight'].sum()\n", + "households_with_3plus_children = children_per_household[children_per_household['is_child'] >= 3]['household_weight'].sum()\n", + "\n", + "print(f\"\\nHouseholds with children (weighted):\")\n", + "print(f\" Total households with children: {total_households_with_children:,.0f}\")\n", + "print(f\" Households with 1 child: {households_with_1_child:,.0f}\")\n", + "print(f\" Households with 2 children: {households_with_2_children:,.0f}\")\n", + "print(f\" Households with 3+ children: {households_with_3plus_children:,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Children by age:\n", + " Total children under 18: 136,125\n", + " Children under 4: 31,892\n", + " Children under 6: 47,136\n", + " Children ages 6-17: 86,277\n", + "\n", + "Sample of children under 4:\n", + " household_id tax_unit_id person_id age\n", + "33 15 21 33 1.0\n", + "42 18 25 42 1.0\n", + "137 70 80 137 0.0\n", + "161 81 92 161 1.0\n", + "193 68 110 193 3.0\n", + "194 68 110 194 1.0\n", + "205 83 115 205 2.0\n", + "209 150 117 209 2.0\n", + "210 150 117 210 1.0\n", + "212 157 118 212 1.0\n" + ] + } + ], + "source": [ + "# Check children by age groups using Ben's workaround\n", + "import pandas as pd\n", + "df = pd.DataFrame({\n", + " \"household_id\": sim.calculate(\"household_id\", map_to=\"person\"),\n", + " \"tax_unit_id\": sim.calculate(\"tax_unit_id\", map_to=\"person\"),\n", + " \"person_id\": sim.calculate(\"person_id\", map_to=\"person\"),\n", + " \"age\": sim.calculate(\"age\", map_to=\"person\"),\n", + " \"person_weight\": sim.calculate(\"person_weight\", map_to=\"person\")\n", + "})\n", + "\n", + "# Filter for children and apply weights\n", + "children_under_4_df = df[df['age'] < 4]\n", + "children_under_6_df = df[df['age'] < 6]\n", + "children_under_18_df = df[df['age'] < 18]\n", + "children_6_17_df = df[(df['age'] >= 6) & (df['age'] < 18)]\n", + "\n", + "# Calculate weighted totals\n", + "is_child = sim.calculate(\"is_child\", period=2025)\n", + "total_children = is_child.sum()\n", + "children_under_4 = children_under_4_df['person_weight'].sum()\n", + "children_under_6 = children_under_6_df['person_weight'].sum()\n", + "children_6_17 = children_6_17_df['person_weight'].sum()\n", + "\n", + "print(f\"\\nChildren by age:\")\n", + "print(f\" Total children under 18: {total_children:,.0f}\")\n", + "print(f\" Children under 4: {children_under_4:,.0f}\")\n", + "print(f\" Children under 6: {children_under_6:,.0f}\")\n", + "print(f\" Children ages 6-17: {children_6_17:,.0f}\")\n", + "\n", + "print(f\"\\nSample of children under 4:\")\n", + "print(children_under_4_df[['household_id', 'tax_unit_id', 'person_id', 'age']].head(10))" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "DC DATASET SUMMARY - WEIGHTED (Population Estimates)\n", + "============================================================\n", + " Metric Value\n", + " Household count (weighted) 220,449\n", + " Person count (weighted) 668,071\n", + " Median AGI $120,221\n", + " 75th percentile AGI $327,906\n", + " 90th percentile AGI $546,746\n", + " 95th percentile AGI $915,476\n", + " Max AGI $3,229,514\n", + " Households over $80k 135,496\n", + " Households over $120k 110,302\n", + " Households over $160k 91,709\n", + " Households over $240k 68,994\n", + "Total households with children 70,469\n", + " Households with 1 child 30,507\n", + " Households with 2 children 23,254\n", + " Households with 3+ children 16,708\n", + " Total children under 18 136,125\n", + " Children under 4 31,892\n", + " Children under 6 47,136\n", + " Children ages 6-17 86,277\n", + "============================================================\n", + "\n", + "============================================================\n", + "DC DATASET SUMMARY - UNWEIGHTED (Sample Counts)\n", + "============================================================\n", + " Metric Value\n", + " Number of households in dataset 5,015\n", + " Number of persons in dataset 13,672\n", + " Households with children (unweighted) 1,587\n", + " Households with 1 child (unweighted) 793\n", + " Households with 2 children (unweighted) 563\n", + "Households with 3+ children (unweighted) 231\n", + " Children under 18 (unweighted) 2,697\n", + " Children under 4 (unweighted) 570\n", + " Children under 6 (unweighted) 863\n", + " Children ages 6-17 (unweighted) 1,834\n", + "============================================================\n", + "\n", + "Summaries saved to:\n", + " - dc_dataset_summary_weighted.csv\n", + " - dc_dataset_summary_unweighted.csv\n" + ] + } + ], + "source": [ + "# Create weighted summary table\n", + "weighted_summary_data = {\n", + " 'Metric': [\n", + " 'Household count (weighted)',\n", + " 'Person count (weighted)',\n", + " 'Median AGI',\n", + " '75th percentile AGI',\n", + " '90th percentile AGI',\n", + " '95th percentile AGI',\n", + " 'Max AGI',\n", + " 'Households over $80k',\n", + " 'Households over $120k',\n", + " 'Households over $160k',\n", + " 'Households over $240k',\n", + " 'Total households with children',\n", + " 'Households with 1 child',\n", + " 'Households with 2 children',\n", + " 'Households with 3+ children',\n", + " 'Total children under 18',\n", + " 'Children under 4',\n", + " 'Children under 6',\n", + " 'Children ages 6-17'\n", + " ],\n", + " 'Value': [\n", + " f\"{household_count.sum():,.0f}\",\n", + " f\"{person_count.sum():,.0f}\",\n", + " f\"${agi.median():,.0f}\",\n", + " f\"${agi.quantile(0.75):,.0f}\",\n", + " f\"${agi.quantile(0.90):,.0f}\",\n", + " f\"${agi.quantile(0.95):,.0f}\",\n", + " f\"${agi.max():,.0f}\",\n", + " f\"{(agi > 80_000).sum():,.0f}\",\n", + " f\"{(agi > 120_000).sum():,.0f}\",\n", + " f\"{(agi > 160_000).sum():,.0f}\",\n", + " f\"{(agi > 240_000).sum():,.0f}\",\n", + " f\"{total_households_with_children:,.0f}\",\n", + " f\"{households_with_1_child:,.0f}\",\n", + " f\"{households_with_2_children:,.0f}\",\n", + " f\"{households_with_3plus_children:,.0f}\",\n", + " f\"{total_children:,.0f}\",\n", + " f\"{children_under_4:,.0f}\",\n", + " f\"{children_under_6:,.0f}\",\n", + " f\"{children_6_17:,.0f}\"\n", + " ]\n", + "}\n", + "\n", + "# Get unique counts for unweighted table\n", + "unique_households = df['household_id'].nunique()\n", + "unique_persons = len(df)\n", + "\n", + "# Create unweighted summary table\n", + "unweighted_summary_data = {\n", + " 'Metric': [\n", + " 'Number of households in dataset',\n", + " 'Number of persons in dataset',\n", + " 'Households with children (unweighted)',\n", + " 'Households with 1 child (unweighted)',\n", + " 'Households with 2 children (unweighted)',\n", + " 'Households with 3+ children (unweighted)',\n", + " 'Children under 18 (unweighted)',\n", + " 'Children under 4 (unweighted)',\n", + " 'Children under 6 (unweighted)',\n", + " 'Children ages 6-17 (unweighted)'\n", + " ],\n", + " 'Value': [\n", + " f\"{unique_households:,}\",\n", + " f\"{unique_persons:,}\",\n", + " f\"{(children_per_household['is_child'] > 0).sum():,}\",\n", + " f\"{(children_per_household['is_child'] == 1).sum():,}\",\n", + " f\"{(children_per_household['is_child'] == 2).sum():,}\",\n", + " f\"{(children_per_household['is_child'] >= 3).sum():,}\",\n", + " f\"{len(children_under_18_df):,}\",\n", + " f\"{len(children_under_4_df):,}\",\n", + " f\"{len(children_under_6_df):,}\",\n", + " f\"{len(children_6_17_df):,}\"\n", + " ]\n", + "}\n", + "\n", + "weighted_df = pd.DataFrame(weighted_summary_data)\n", + "unweighted_df = pd.DataFrame(unweighted_summary_data)\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"DC DATASET SUMMARY - WEIGHTED (Population Estimates)\")\n", + "print(\"=\"*60)\n", + "print(weighted_df.to_string(index=False))\n", + "print(\"=\"*60)\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"DC DATASET SUMMARY - UNWEIGHTED (Sample Counts)\")\n", + "print(\"=\"*60)\n", + "print(unweighted_df.to_string(index=False))\n", + "print(\"=\"*60)\n", + "\n", + "# Save both tables\n", + "weighted_df.to_csv('dc_dataset_summary_weighted.csv', index=False)\n", + "unweighted_df.to_csv('dc_dataset_summary_unweighted.csv', index=False)\n", + "print(\"\\nSummaries saved to:\")\n", + "print(\" - dc_dataset_summary_weighted.csv\")\n", + "print(\" - dc_dataset_summary_unweighted.csv\")" + ] + } + ], + "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": 4 +} diff --git a/us/states/dc/dc_ctc_child_poverty_by_age.csv b/us/states/dc/dc_ctc_child_poverty_by_age.csv new file mode 100644 index 0000000..101011c --- /dev/null +++ b/us/states/dc/dc_ctc_child_poverty_by_age.csv @@ -0,0 +1,5 @@ +Age Eligibility,Baseline Poverty Rate,Reform Poverty Rate,Absolute Reduction (pp),Percentage Reduction,Annual Cost +Under 6,21.13%,20.86%,0.27,1.3%,"$25,164,361" +Under 8,21.13%,20.86%,0.27,1.3%,"$33,342,733" +Under 12,21.13%,20.33%,0.79,3.8%,"$53,009,724" +Under 18,21.13%,19.76%,1.36,6.4%,"$82,271,789" diff --git a/us/states/dc/dc_ctc_reform_summary.csv b/us/states/dc/dc_ctc_reform_summary.csv new file mode 100644 index 0000000..d9a5c6a --- /dev/null +++ b/us/states/dc/dc_ctc_reform_summary.csv @@ -0,0 +1,20 @@ +Reform,Age Group,Income Threshold,Target Cost,Amount per Child,Actual Cost +Baseline (Current),Under 6,Current,Current,$420,"$17,971,915" +Reform 1: Preschool,Under 4,Standard,$5M,$175,"$5,017,059" +Reform 1: Preschool,Under 4,Standard,$10M,$350,"$10,068,140" +Reform 1: Preschool,Under 4,Standard,$15M,$525,"$15,148,594" +Reform 1B: Preschool,Under 4,Half,$5M,$195,"$4,950,844" +Reform 1B: Preschool,Under 4,Half,$10M,$390,"$9,977,008" +Reform 1B: Preschool,Under 4,Half,$15M,$570,"$14,794,358" +Reform 2: Early Childhood,Under 6,Standard,$5M,$120,"$5,104,786" +Reform 2: Early Childhood,Under 6,Standard,$10M,$235,"$10,019,970" +Reform 2: Early Childhood,Under 6,Standard,$15M,$350,"$14,957,336" +Reform 2B: Early Childhood,Under 6,Half,$5M,$130,"$4,910,300" +Reform 2B: Early Childhood,Under 6,Half,$10M,$265,"$10,060,217" +Reform 2B: Early Childhood,Under 6,Half,$15M,$385,"$14,728,679" +Reform 3: All Children,Under 18,Standard,$5M,$45,"$5,302,008" +Reform 3: All Children,Under 18,Standard,$10M,$85,"$10,026,294" +Reform 3: All Children,Under 18,Standard,$15M,$125,"$14,760,191" +Reform 3B: All Children,Under 18,Half,$5M,$50,"$5,147,592" +Reform 3B: All Children,Under 18,Half,$10M,$95,"$9,823,450" +Reform 3B: All Children,Under 18,Half,$15M,$145,"$15,059,910" diff --git a/us/states/dc/dc_ctc_reforms_comprehensive.csv b/us/states/dc/dc_ctc_reforms_comprehensive.csv new file mode 100644 index 0000000..2ef3372 --- /dev/null +++ b/us/states/dc/dc_ctc_reforms_comprehensive.csv @@ -0,0 +1,73 @@ +Age Threshold,Amount per Child,Child Limit,Phase-out Amount,Annual Cost +Under 6,$420,3,$20,"$14,320,670" +Under 6,$420,3,$50,"$13,841,326" +Under 6,$420,3,$100,"$13,615,555" +Under 6,$420,None,$20,"$14,555,760" +Under 6,$420,None,$50,"$14,076,416" +Under 6,$420,None,$100,"$13,850,645" +Under 6,"$1,000",3,$20,"$36,101,632" +Under 6,"$1,000",3,$50,"$34,013,107" +Under 6,"$1,000",3,$100,"$33,109,273" +Under 6,"$1,000",None,$20,"$36,661,372" +Under 6,"$1,000",None,$50,"$34,572,846" +Under 6,"$1,000",None,$100,"$33,669,012" +Under 6,"$1,500",3,$20,"$56,226,654" +Under 6,"$1,500",3,$50,"$52,092,604" +Under 6,"$1,500",3,$100,"$50,344,382" +Under 6,"$1,500",None,$20,"$57,066,263" +Under 6,"$1,500",None,$50,"$52,932,212" +Under 6,"$1,500",None,$100,"$51,183,991" +Under 8,$420,3,$20,"$18,751,082" +Under 8,$420,3,$50,"$17,958,771" +Under 8,$420,3,$100,"$17,637,315" +Under 8,$420,None,$20,"$19,107,110" +Under 8,$420,None,$50,"$18,314,799" +Under 8,$420,None,$100,"$17,993,343" +Under 8,"$1,000",3,$20,"$47,539,975" +Under 8,"$1,000",3,$50,"$44,514,242" +Under 8,"$1,000",3,$100,"$43,070,571" +Under 8,"$1,000",None,$20,"$48,387,661" +Under 8,"$1,000",None,$50,"$45,361,928" +Under 8,"$1,000",None,$100,"$43,918,257" +Under 8,"$1,500",3,$20,"$74,144,075" +Under 8,"$1,500",3,$50,"$68,512,361" +Under 8,"$1,500",3,$100,"$65,765,723" +Under 8,"$1,500",None,$20,"$75,415,604" +Under 8,"$1,500",None,$50,"$69,783,890" +Under 8,"$1,500",None,$100,"$67,037,252" +Under 12,$420,3,$20,"$26,912,518" +Under 12,$420,3,$50,"$25,450,678" +Under 12,$420,3,$100,"$24,910,030" +Under 12,$420,None,$20,"$28,476,680" +Under 12,$420,None,$50,"$26,901,509" +Under 12,$420,None,$100,"$26,313,513" +Under 12,"$1,000",3,$20,"$68,648,053" +Under 12,"$1,000",3,$50,"$63,852,646" +Under 12,"$1,000",3,$100,"$61,119,811" +Under 12,"$1,000",None,$20,"$72,372,248" +Under 12,"$1,000",None,$50,"$67,576,840" +Under 12,"$1,000",None,$100,"$64,627,294" +Under 12,"$1,500",3,$20,"$106,877,819" +Under 12,"$1,500",3,$50,"$98,676,239" +Under 12,"$1,500",3,$100,"$93,893,111" +Under 12,"$1,500",None,$20,"$112,464,111" +Under 12,"$1,500",None,$50,"$104,262,531" +Under 12,"$1,500",None,$100,"$99,438,296" +Under 18,$420,3,$20,"$39,362,370" +Under 18,$420,3,$50,"$37,038,891" +Under 18,$420,3,$100,"$36,180,594" +Under 18,$420,None,$20,"$42,068,611" +Under 18,$420,None,$50,"$39,591,351" +Under 18,$420,None,$100,"$38,506,296" +Under 18,"$1,000",3,$20,"$101,055,690" +Under 18,"$1,000",3,$50,"$93,362,597" +Under 18,"$1,000",3,$100,"$89,024,244" +Under 18,"$1,000",None,$20,"$107,513,605" +Under 18,"$1,000",None,$50,"$99,802,756" +Under 18,"$1,000",None,$100,"$95,192,601" +Under 18,"$1,500",3,$20,"$157,496,839" +Under 18,"$1,500",3,$50,"$144,690,176" +Under 18,"$1,500",3,$100,"$137,036,196" +Under 18,"$1,500",None,$20,"$167,183,711" +Under 18,"$1,500",None,$50,"$154,370,886" +Under 18,"$1,500",None,$100,"$146,581,967" diff --git a/us/states/dc/dc_dataset_summary.csv b/us/states/dc/dc_dataset_summary.csv new file mode 100644 index 0000000..1c9f1e4 --- /dev/null +++ b/us/states/dc/dc_dataset_summary.csv @@ -0,0 +1,21 @@ +Metric,Value +Number of households in dataset,"13,672" +Household count (mapped to household),"220,449" +Person count (mapped to household),"668,071" +Median AGI,"$120,221" +75th percentile AGI,"$327,906" +90th percentile AGI,"$546,746" +95th percentile AGI,"$915,476" +Max AGI,"$3,229,514" +Households over $80k,"135,496" +Households over $120k,"110,302" +Households over $160k,"91,709" +Households over $240k,"68,994" +Total households with children,"70,469" +Households with 1 child,"30,507" +Households with 2 children,"23,254" +Households with 3+ children,"16,708" +Total children under 18,"136,125" +Children under 4,"31,892" +Children under 6,"47,136" +Children ages 6-17,"86,277" diff --git a/us/states/dc/dc_dataset_summary_unweighted.csv b/us/states/dc/dc_dataset_summary_unweighted.csv new file mode 100644 index 0000000..9d5230b --- /dev/null +++ b/us/states/dc/dc_dataset_summary_unweighted.csv @@ -0,0 +1,11 @@ +Metric,Value +Number of households in dataset,"5,015" +Number of persons in dataset,"13,672" +Households with children (unweighted),"1,587" +Households with 1 child (unweighted),793 +Households with 2 children (unweighted),563 +Households with 3+ children (unweighted),231 +Children under 18 (unweighted),"2,697" +Children under 4 (unweighted),570 +Children under 6 (unweighted),863 +Children ages 6-17 (unweighted),"1,834" diff --git a/us/states/dc/dc_dataset_summary_weighted.csv b/us/states/dc/dc_dataset_summary_weighted.csv new file mode 100644 index 0000000..8d49475 --- /dev/null +++ b/us/states/dc/dc_dataset_summary_weighted.csv @@ -0,0 +1,20 @@ +Metric,Value +Household count (weighted),"220,449" +Person count (weighted),"668,071" +Median AGI,"$120,221" +75th percentile AGI,"$327,906" +90th percentile AGI,"$546,746" +95th percentile AGI,"$915,476" +Max AGI,"$3,229,514" +Households over $80k,"135,496" +Households over $120k,"110,302" +Households over $160k,"91,709" +Households over $240k,"68,994" +Total households with children,"70,469" +Households with 1 child,"30,507" +Households with 2 children,"23,254" +Households with 3+ children,"16,708" +Total children under 18,"136,125" +Children under 4,"31,892" +Children under 6,"47,136" +Children ages 6-17,"86,277"