PolicyEngine / PolicyEngine/policyengine-uk-data
Housing association rents ~20% above benchmark; housing/rent_social target missed by 1.55x
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1
- Forks
- 2
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 4
Description
[!WARNING]
This body has been corrected. The original asserted social rents ran 25-35% high against an RSH "general needs" benchmark, and that scaling the housing element by -25% reproduced the administrative capped count. Both were wrong: the benchmark excluded affordable-rent tenancies, and the counterfactual cut private rents that are not overstated. Corrected figures below; the original text is preserved in the first comment.
Problem
Modelled rents in the enhanced FRS exceed published averages, with the error concentrated in the housing association sector. Council and private rents are close to benchmark.
| tenure | model (2026) | EHS 2024-25 (England) | uprated ~12% to 2026 | gap |
|---|---|---|---|---|
| council | GBP 145/wk (median 128) | GBP 120 | ~GBP 135 | +7% |
| housing association | GBP 181/wk (median 161) | GBP 134 | ~GBP 151 | +20% |
| social, blended | GBP 166/wk | GBP 129 | ~GBP 145 | +14% |
| private | GBP 261/wk (median 225) | GBP 250 | ~GBP 275 | −5% |
Source: English Housing Survey 2024-25, chapter 2. EHS is England-only while the model is UK-wide; devolved social rents are lower, so the true gap is probably slightly larger than shown.
Comparability caveat that is not yet resolved: FRS HHRENT, the basis for the model's rent, is defined net of service charges and water, whereas EHS mean weekly rents for social tenants generally include service charges. That biases the model low in this comparison, which makes the +20% housing association gap harder to explain rather than easier. Quantifying this should be the first step before acting on the gap.
Enhanced FRS 2023/24 v1.40.3, simulated 2026.
The calibration target is being missed
This is the sharper statement of the problem. housing/rent_social already targets this quantity and is not converging, while the private target is:
| target (2025) | model | target | ratio |
|---|---|---|---|
housing/rent_private |
GBP 92.9bn | GBP 89.0bn | 1.04x |
housing/rent_social |
GBP 47.6bn | GBP 30.7bn | 1.55x |
The social miss decomposes as 5.77m households against the target's 5.0m basis (1.15x) times GBP 159/wk against the GBP 118/wk basis (1.35x).
Note the private figures cannot both be right: this issue puts model private rent 5% below the EHS-uprated benchmark, while the target basis (ONS PRHI, GBP 317/wk) puts it 19% below. ONS PRHI mixes new lets into a stock measure, so part of the private "count 30% high / mean 19% low" decomposition may be an artefact of the basis rather than model error. The two comparators need reconciling.
Why it matters
The benefit cap is a threshold effect and unusually sensitive to level errors in its inputs (PolicyEngine/policyengine-uk#1818). Housing is 46% of capped benefits, and the median excess over the cap is only GBP 2,733/yr against a mean housing element of GBP 11,604/yr.
Applying tenure-specific corrections (council −7%, HA −20%, private 0%) moves modelled capping from 222k households to 145k, against DWP's 111k — closing about 69% of the excess. The residual belongs to other causes tracked in #1818.
Downstream this makes benefit-cap-interacting reform estimates roughly 2x too large, blocking JRF-style protected minimum floor analysis (PolicyEngine/policyengine-uk#1814).
Household counts
| model (2025) | UK benchmark | |
|---|---|---|
| total households | 31.76m | 29.0m (ONS 2025) |
| owner-occupied | 59.9% | 65% (FRS 2024-25) |
| private rent | 22.0% | 19% |
| social rent | 18.2% | 17% |
The household total is ~9.5% high and renting is over-represented. A concrete candidate: targets/sources/ons_tenure.py is documented as ONS "subnational dwelling stock by tenure" but targets/compute/households.py matches it against modelled household counts, and dwellings exceed households by roughly 8% in England.
What would help
- Quantify the service-charge basis difference between FRS
HHRENTand EHS rents before treating the +20% as pure model error. - Diagnose why
housing/rent_socialdoes not converge whilehousing/rent_privatedoes. This is the same class of failure as the benefit cap targets in #1818, which are missed by 2.0x and 3.1x — a shared cause is plausible. - Reconcile the dwelling-stock vs household-count mismatch in the tenure targets.
- Pair rent totals with household-count constraints, or target mean rent by tenure, so count and mean errors cannot cancel. Note
datasets/local_areas/constituencies/devolved_housing.pyalready does exactly this for Wales and Scotland. - Add mean rent by tenure to per-release validation against EHS.
Related, found alongside
num_bedrooms is identically zero for every household in the dataset. The variable is declared in the model (variables/household/demographic/num_bedrooms.py) with no formula, nothing populates it, and nothing references it. Harmless today, but it makes the under-occupancy deduction (removal of the spare room subsidy) unimplementable — that policy is absent from the model entirely, and social renters receive full rent as their housing costs element.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by quantifying the FRS HHRENT versus EHS service-charge difference, then inspect targets/sources/ons_tenure.py and targets/compute/households.py for the dwelling-versus-household mismatch. Compare the rent targets with datasets/local_areas/constituencies/devolved_housing.py, and inspect variables/household/demographic/num_bedrooms.py for the related zero-value issue. Done should include an explained social-rent miss, reconciled count and rent validation, and documented per-release checks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- data
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100