Created
March 24, 2026 20:05
-
-
Save MaxGhenis/bf9e48ef6d935c088abad871fb1f5f2f to your computer and use it in GitHub Desktop.
PolicyEngine 2025 top income thresholds (top 1% and 0.1% AGI minimums)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "id": "6a5f4915", | |
| "metadata": {}, | |
| "source": [ | |
| "# Top income thresholds in PolicyEngine's 2025 microsimulation\n", | |
| "\n", | |
| "AGI minimums for top 1% and top 0.1% of tax units in 2025,\n", | |
| "with IRS SOI TY 2022 for comparison." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "id": "b404f6b4", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-03-24T20:04:39.052571Z", | |
| "iopub.status.busy": "2026-03-24T20:04:39.052299Z", | |
| "iopub.status.idle": "2026-03-24T20:05:53.500369Z", | |
| "shell.execute_reply": "2026-03-24T20:05:53.499949Z" | |
| } | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "from policyengine_us import Microsimulation\n", | |
| "import numpy as np\n", | |
| "import pandas as pd\n", | |
| "\n", | |
| "sim = Microsimulation()\n", | |
| "YEAR = 2025\n", | |
| "\n", | |
| "weight = np.array(sim.calc(\"tax_unit_weight\", period=YEAR))\n", | |
| "agi = np.array(sim.calc(\"adjusted_gross_income\", period=YEAR))\n", | |
| "is_filer = np.array(sim.calc(\"tax_unit_is_filer\", period=YEAR)).astype(bool)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "063f551c", | |
| "metadata": {}, | |
| "source": [ | |
| "## All tax units (including non-filers)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "id": "808c2c2b", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-03-24T20:05:53.501657Z", | |
| "iopub.status.busy": "2026-03-24T20:05:53.501582Z", | |
| "iopub.status.idle": "2026-03-24T20:05:53.506338Z", | |
| "shell.execute_reply": "2026-03-24T20:05:53.505974Z" | |
| } | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "total_all = weight.sum()\n", | |
| "sort_idx = np.argsort(agi)\n", | |
| "agi_sorted = agi[sort_idx]\n", | |
| "wt_sorted = weight[sort_idx]\n", | |
| "cum_pct = np.cumsum(wt_sorted) / total_all\n", | |
| "\n", | |
| "idx_99 = np.searchsorted(cum_pct, 0.99)\n", | |
| "idx_999 = np.searchsorted(cum_pct, 0.999)\n", | |
| "\n", | |
| "all_top1_min = agi_sorted[idx_99]\n", | |
| "all_top1_units = wt_sorted[idx_99:].sum()\n", | |
| "all_top01_min = agi_sorted[idx_999]\n", | |
| "all_top01_units = wt_sorted[idx_999:].sum()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "5f6e70a8", | |
| "metadata": {}, | |
| "source": [ | |
| "## Filers only" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "id": "5e2c5d8f", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-03-24T20:05:53.507330Z", | |
| "iopub.status.busy": "2026-03-24T20:05:53.507266Z", | |
| "iopub.status.idle": "2026-03-24T20:05:53.511485Z", | |
| "shell.execute_reply": "2026-03-24T20:05:53.511123Z" | |
| } | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "agi_f = agi[is_filer]\n", | |
| "wt_f = weight[is_filer]\n", | |
| "total_filers = wt_f.sum()\n", | |
| "\n", | |
| "sort_idx_f = np.argsort(agi_f)\n", | |
| "agi_sorted_f = agi_f[sort_idx_f]\n", | |
| "wt_sorted_f = wt_f[sort_idx_f]\n", | |
| "cum_pct_f = np.cumsum(wt_sorted_f) / total_filers\n", | |
| "\n", | |
| "idx_99_f = np.searchsorted(cum_pct_f, 0.99)\n", | |
| "idx_999_f = np.searchsorted(cum_pct_f, 0.999)\n", | |
| "\n", | |
| "filer_top1_min = agi_sorted_f[idx_99_f]\n", | |
| "filer_top1_units = wt_sorted_f[idx_99_f:].sum()\n", | |
| "filer_top01_min = agi_sorted_f[idx_999_f]\n", | |
| "filer_top01_units = wt_sorted_f[idx_999_f:].sum()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "c3ac8b33", | |
| "metadata": {}, | |
| "source": [ | |
| "## Comparison table" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "id": "6397bd93", | |
| "metadata": { | |
| "execution": { | |
| "iopub.execute_input": "2026-03-24T20:05:53.512256Z", | |
| "iopub.status.busy": "2026-03-24T20:05:53.512205Z", | |
| "iopub.status.idle": "2026-03-24T20:05:53.521889Z", | |
| "shell.execute_reply": "2026-03-24T20:05:53.521598Z" | |
| } | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>PolicyEngine 2025 (all)</th>\n", | |
| " <th>PolicyEngine 2025 (filers)</th>\n", | |
| " <th>IRS SOI TY 2022</th>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Metric</th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>Total tax units</th>\n", | |
| " <td>194,116,928</td>\n", | |
| " <td>151,335,680</td>\n", | |
| " <td>153,801,397</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Top 1% AGI minimum</th>\n", | |
| " <td>$645,448</td>\n", | |
| " <td>$753,655</td>\n", | |
| " <td>$663,164</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Top 1% tax units</th>\n", | |
| " <td>1,985,947</td>\n", | |
| " <td>1,513,074</td>\n", | |
| " <td>1,538,014</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Top 0.1% AGI minimum</th>\n", | |
| " <td>$3,715,259</td>\n", | |
| " <td>$4,075,306</td>\n", | |
| " <td>$3,271,387</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Top 0.1% tax units</th>\n", | |
| " <td>197,571</td>\n", | |
| " <td>153,729</td>\n", | |
| " <td>153,801</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " PolicyEngine 2025 (all) PolicyEngine 2025 (filers) \\\n", | |
| "Metric \n", | |
| "Total tax units 194,116,928 151,335,680 \n", | |
| "Top 1% AGI minimum $645,448 $753,655 \n", | |
| "Top 1% tax units 1,985,947 1,513,074 \n", | |
| "Top 0.1% AGI minimum $3,715,259 $4,075,306 \n", | |
| "Top 0.1% tax units 197,571 153,729 \n", | |
| "\n", | |
| " IRS SOI TY 2022 \n", | |
| "Metric \n", | |
| "Total tax units 153,801,397 \n", | |
| "Top 1% AGI minimum $663,164 \n", | |
| "Top 1% tax units 1,538,014 \n", | |
| "Top 0.1% AGI minimum $3,271,387 \n", | |
| "Top 0.1% tax units 153,801 " | |
| ] | |
| }, | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "comparison = pd.DataFrame({\n", | |
| " \"Metric\": [\n", | |
| " \"Total tax units\",\n", | |
| " \"Top 1% AGI minimum\",\n", | |
| " \"Top 1% tax units\",\n", | |
| " \"Top 0.1% AGI minimum\",\n", | |
| " \"Top 0.1% tax units\",\n", | |
| " ],\n", | |
| " \"PolicyEngine 2025 (all)\": [\n", | |
| " f\"{total_all:,.0f}\",\n", | |
| " f\"${all_top1_min:,.0f}\",\n", | |
| " f\"{all_top1_units:,.0f}\",\n", | |
| " f\"${all_top01_min:,.0f}\",\n", | |
| " f\"{all_top01_units:,.0f}\",\n", | |
| " ],\n", | |
| " \"PolicyEngine 2025 (filers)\": [\n", | |
| " f\"{total_filers:,.0f}\",\n", | |
| " f\"${filer_top1_min:,.0f}\",\n", | |
| " f\"{filer_top1_units:,.0f}\",\n", | |
| " f\"${filer_top01_min:,.0f}\",\n", | |
| " f\"{filer_top01_units:,.0f}\",\n", | |
| " ],\n", | |
| " \"IRS SOI TY 2022\": [\n", | |
| " \"153,801,397\",\n", | |
| " \"$663,164\",\n", | |
| " \"1,538,014\",\n", | |
| " \"$3,271,387\",\n", | |
| " \"153,801\",\n", | |
| " ],\n", | |
| "})\n", | |
| "comparison.set_index(\"Metric\")" | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "jupytext": { | |
| "cell_metadata_filter": "-all", | |
| "main_language": "python", | |
| "notebook_metadata_filter": "-all" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.14.0" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 5 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment