Skip to content

Instantly share code, notes, and snippets.

@MaxGhenis
Created October 2, 2025 15:25
Show Gist options
  • Select an option

  • Save MaxGhenis/763db9278ddecdf310f160a73e138c8a to your computer and use it in GitHub Desktop.

Select an option

Save MaxGhenis/763db9278ddecdf310f160a73e138c8a to your computer and use it in GitHub Desktop.
UC and CTC take-up rates - Enhanced FRS 2023-24
Display the source blob
Display the rendered blob
Raw
{
"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