Created
October 2, 2025 15:25
-
-
Save MaxGhenis/763db9278ddecdf310f160a73e138c8a to your computer and use it in GitHub Desktop.
UC and CTC take-up rates - Enhanced FRS 2023-24
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", | |
| "metadata": {}, | |
| "source": [ | |
| "# UC and CTC Take-up Rate Analysis\n", | |
| "\n", | |
| "Enhanced FRS 2023-24 | PolicyEngine UK v2.53.1 | 2025-10-02" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "from policyengine_uk import Microsimulation\n", | |
| "import pandas as pd\n", | |
| "import numpy as np" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Universal Credit 2026" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "metadata": {}, | |
| "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>Benefit units (millions)</th>\n", | |
| " <th>Spending (£bn)</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>Baseline (55% take-up)</th>\n", | |
| " <td>6.81</td>\n", | |
| " <td>81.38</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>100% take-up</th>\n", | |
| " <td>9.09</td>\n", | |
| " <td>124.58</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Benefit units (millions) Spending (£bn)\n", | |
| "Baseline (55% take-up) 6.81 81.38\n", | |
| "100% take-up 9.09 124.58" | |
| ] | |
| }, | |
| "execution_count": 2, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# Baseline with calibrated take-up\n", | |
| "baseline = Microsimulation()\n", | |
| "uc_baseline_2026 = baseline.calculate('universal_credit', period=2026)\n", | |
| "\n", | |
| "# 100% take-up scenario\n", | |
| "full_takeup = Microsimulation(reform={\n", | |
| " 'gov.dwp.universal_credit.takeup_rate': {\n", | |
| " '2015-01-01.2100-12-31': 1.0\n", | |
| " }\n", | |
| "})\n", | |
| "uc_full_2026 = full_takeup.calculate('universal_credit', period=2026)\n", | |
| "\n", | |
| "pd.DataFrame({\n", | |
| " 'Benefit units (millions)': [\n", | |
| " (uc_baseline_2026 > 0).sum() / 1e6,\n", | |
| " (uc_full_2026 > 0).sum() / 1e6\n", | |
| " ],\n", | |
| " 'Spending (£bn)': [\n", | |
| " uc_baseline_2026.sum() / 1e9,\n", | |
| " uc_full_2026.sum() / 1e9\n", | |
| " ]\n", | |
| "}, index=['Baseline (55% take-up)', '100% take-up']).round(2)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "74.9" | |
| ] | |
| }, | |
| "execution_count": 3, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# Take-up rate (baseline recipients / full take-up recipients)\n", | |
| "uc_takeup_2026 = ((uc_baseline_2026 > 0).sum() / (uc_full_2026 > 0).sum()) * 100\n", | |
| "round(uc_takeup_2026, 1)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Child Tax Credit 2026" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "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>Benefit units (thousands)</th>\n", | |
| " <th>Spending (£bn)</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>Baseline (100% take-up)</th>\n", | |
| " <td>207</td>\n", | |
| " <td>1.43</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>100% take-up</th>\n", | |
| " <td>207</td>\n", | |
| " <td>1.43</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Benefit units (thousands) Spending (£bn)\n", | |
| "Baseline (100% take-up) 207 1.43\n", | |
| "100% take-up 207 1.43" | |
| ] | |
| }, | |
| "execution_count": 4, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# CTC already has 100% take-up parameter\n", | |
| "ctc_baseline_2026 = baseline.calculate('child_tax_credit', period=2026)\n", | |
| "ctc_full_2026 = full_takeup.calculate('child_tax_credit', period=2026)\n", | |
| "\n", | |
| "pd.DataFrame({\n", | |
| " 'Benefit units (thousands)': [\n", | |
| " int((ctc_baseline_2026 > 0).sum() / 1000),\n", | |
| " int((ctc_full_2026 > 0).sum() / 1000)\n", | |
| " ],\n", | |
| " 'Spending (£bn)': [\n", | |
| " round(ctc_baseline_2026.sum() / 1e9, 2),\n", | |
| " round(ctc_full_2026.sum() / 1e9, 2)\n", | |
| " ]\n", | |
| "}, index=['Baseline (100% take-up)', '100% take-up'])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "100.0" | |
| ] | |
| }, | |
| "execution_count": 5, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# Take-up rate\n", | |
| "ctc_takeup_2026 = ((ctc_baseline_2026 > 0).sum() / (ctc_full_2026 > 0).sum()) * 100\n", | |
| "round(ctc_takeup_2026, 1)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Universal Credit 2029" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "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>Benefit units (millions)</th>\n", | |
| " <th>Spending (£bn)</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>Baseline (55% take-up)</th>\n", | |
| " <td>6.94</td>\n", | |
| " <td>87.62</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>100% take-up</th>\n", | |
| " <td>9.24</td>\n", | |
| " <td>133.97</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Benefit units (millions) Spending (£bn)\n", | |
| "Baseline (55% take-up) 6.94 87.62\n", | |
| "100% take-up 9.24 133.97" | |
| ] | |
| }, | |
| "execution_count": 6, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "uc_baseline_2029 = baseline.calculate('universal_credit', period=2029)\n", | |
| "uc_full_2029 = full_takeup.calculate('universal_credit', period=2029)\n", | |
| "\n", | |
| "pd.DataFrame({\n", | |
| " 'Benefit units (millions)': [\n", | |
| " (uc_baseline_2029 > 0).sum() / 1e6,\n", | |
| " (uc_full_2029 > 0).sum() / 1e6\n", | |
| " ],\n", | |
| " 'Spending (£bn)': [\n", | |
| " uc_baseline_2029.sum() / 1e9,\n", | |
| " uc_full_2029.sum() / 1e9\n", | |
| " ]\n", | |
| "}, index=['Baseline (55% take-up)', '100% take-up']).round(2)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "75.1" | |
| ] | |
| }, | |
| "execution_count": 7, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# Take-up rate\n", | |
| "uc_takeup_2029 = ((uc_baseline_2029 > 0).sum() / (uc_full_2029 > 0).sum()) * 100\n", | |
| "round(uc_takeup_2029, 1)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Child Tax Credit 2029" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "metadata": {}, | |
| "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>Benefit units (thousands)</th>\n", | |
| " <th>Spending (£bn)</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>Baseline (100% take-up)</th>\n", | |
| " <td>208</td>\n", | |
| " <td>1.53</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>100% take-up</th>\n", | |
| " <td>208</td>\n", | |
| " <td>1.53</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Benefit units (thousands) Spending (£bn)\n", | |
| "Baseline (100% take-up) 208 1.53\n", | |
| "100% take-up 208 1.53" | |
| ] | |
| }, | |
| "execution_count": 8, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "ctc_baseline_2029 = baseline.calculate('child_tax_credit', period=2029)\n", | |
| "ctc_full_2029 = full_takeup.calculate('child_tax_credit', period=2029)\n", | |
| "\n", | |
| "pd.DataFrame({\n", | |
| " 'Benefit units (thousands)': [\n", | |
| " int((ctc_baseline_2029 > 0).sum() / 1000),\n", | |
| " int((ctc_full_2029 > 0).sum() / 1000)\n", | |
| " ],\n", | |
| " 'Spending (£bn)': [\n", | |
| " round(ctc_baseline_2029.sum() / 1e9, 2),\n", | |
| " round(ctc_full_2029.sum() / 1e9, 2)\n", | |
| " ]\n", | |
| "}, index=['Baseline (100% take-up)', '100% take-up'])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "100.0" | |
| ] | |
| }, | |
| "execution_count": 9, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "# Take-up rate\n", | |
| "ctc_takeup_2029 = ((ctc_baseline_2029 > 0).sum() / (ctc_full_2029 > 0).sum()) * 100\n", | |
| "round(ctc_takeup_2029, 1)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "## Summary" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "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>2026</th>\n", | |
| " <th>2029</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>UC take-up (%)</th>\n", | |
| " <td>74.9</td>\n", | |
| " <td>75.1</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>CTC take-up (%)</th>\n", | |
| " <td>100.0</td>\n", | |
| " <td>100.0</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " 2026 2029\n", | |
| "UC take-up (%) 74.9 75.1\n", | |
| "CTC take-up (%) 100.0 100.0" | |
| ] | |
| }, | |
| "execution_count": 10, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "pd.DataFrame({\n", | |
| " '2026': [round(uc_takeup_2026, 1), round(ctc_takeup_2026, 1)],\n", | |
| " '2029': [round(uc_takeup_2029, 1), round(ctc_takeup_2029, 1)]\n", | |
| "}, index=['UC take-up (%)', 'CTC take-up (%)'])" | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "language": "python", | |
| "name": "python3" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.13.0" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 4 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment