Getting started#
PolicyEngine has two main use-cases:
I want to simulate policy over specific households.
I want to run microsimulation analyses over large datasets.
Anyone can do the former in a few minutes of setup, but the UK’s large household surveys are only available to academics, researchers and nonprofits, so getting set up takes a bit longer (and you should get in touch so we can make it as fast as possible).
If you can, please use Google Colab. It’s free, and more importantly, it enables everyone to use the same computing environment, saving all the trouble of fiddling around with bad Python installations, etc. It means that the below snippet is all you need to use the full microsimulation model:
!export HUGGING_FACE_TOKEN=<your_token>
!pip install policyengine-uk
Household-level analysis#
The PolicyEngine UK Python package can be installed just like any other. Here’s an example below.
First, we need to install the package (please make sure you’re using Python >=3.7):
pip install policyengine-uk
Simulating current law#
This example shows how to define a situation (you need to define the people, benefit units and households, and their variables in specific time periods) and simulate the current tax-benefit system.
# The `Simulation` class is the most important class in PolicyEngine- it runs the actual simulation.
from policyengine_uk import Simulation
situation = {
"people": {
"person": {
"age": {2025: 30},
"employment_income": {2025: 30_000},
},
},
"benunits": {
"benunit": {
"members": ["person"],
},
},
"households": {
"household": {
"members": ["person"],
}
},
}
simulation = Simulation(situation=situation)
simulation.calculate("income_tax", 2025)
/Users/nikhilwoodruff/policyengine/policyengine-uk/.venv/lib/python3.11/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
from .autonotebook import tqdm as notebook_tqdm
array([3486.], dtype=float32)
Simulating a policy reform#
Now, let’s simulate a policy reform that changes a policy parameter. The OpenFisca documentation has some excellent documentation on the syntax here.
from policyengine_core.model_api import *
increase_basic_rate = {"gov.hmrc.income_tax.rates.uk[0].rate": 0.25}
baseline = Simulation(situation=situation)
reformed = Simulation(situation=situation, reform=increase_basic_rate)
baseline_income_tax = baseline.calculate("income_tax", 2025)[0]
reformed_income_tax = reformed.calculate("income_tax", 2025)[0]
print(
f"Raising the basic rate to 25% would increase this person's income tax by £{reformed_income_tax - baseline_income_tax:.2f}"
)
Raising the basic rate to 25% would increase this person's income tax by £871.50
Microsimulation analysis#
PolicyEngine UK has all the code needed to actually generate the microsimulation datasets from the raw dataset files if you have them, but it’s easiest to download our final datasets. To do this, you’ll need to do the following:
Make sure you’ve got a HuggingFace account.
Get a personal access token via the settings.
Set HUGGING_FACE_TOKEN as an environment variable.
For example, in a bash shell:
export HUGGING_FACE_TOKEN=your_token_here
If you don’t want to set it, it’ll also just prompt you when you try to access the data.
Getting set up#
Now the datasets will be downloaded automatically as you select them. Here’s an example:
from policyengine_uk import Microsimulation
sim = Microsimulation(dataset="hf://policyengine/policyengine-uk-data/enhanced_frs_2022_23.h5")
# The hf:// points to the private data-
# hf:// <- go get the data from huggingface
# policyengine/policyengine-uk-data <- the repo
# enhanced_frs_2022_23.h5 <- the file in the repo
sim.calculate("universal_credit", 2025).sum() / 1e9
79.42656804925272
Running reform analyses#
Reforms work in exactly the same way as in the household-level analysis above. Here’s the same example reform:
ENHANCED_FRS = "hf://policyengine/policyengine-uk-data/enhanced_frs_2022_23.h5"
baseline = Microsimulation(dataset=ENHANCED_FRS) # Enhanced FRS 2022 by default
reformed = Microsimulation(dataset=ENHANCED_FRS, reform=increase_basic_rate)
revenue = (
-(
reformed.calculate("household_net_income", 2025)
- baseline.calculate("household_net_income", 2025)
).sum()
/ 1e9
)
print(
f"Raising the basic rate to 25% would raise the UK £{revenue:.2f}bn per year"
)
Raising the basic rate to 25% would raise the UK £35.54bn per year
The PolicyEngine web app actually has a helpful tool for this: if you can generate a household or reform on the app, scroll down in the bottom left to the Reproduce in Python
section, and you’ll see an automatically-generated code snippet to reproduce the same analysis in Python.