Repository navigation
Uprate electricity_consumption and gas_consumption - #1860
Conversation
juaristi22
left a comment
There was a problem hiding this comment.
Verified locally on the cached enhanced_frs_2024_25 (household means, 2024 → 2027):
- before:
electricity_consumption838.45 → 838.45 (0.0 %),gas_consumption658.40 → 658.40 (0.0 %) - after: 838.45 → 904.64 (+7.9 %), 658.40 → 710.38 (+7.9 %);
electricity + gas=domestic_energy_consumption= 1615.01 in 2027
So the diff does what it says and the documented identity is restored.
CI. The red Test job is not this PR. All 28 failures (3 failed + 25 errors) are the same PermissionError: file /Users/runner/.cache/huggingface/hub/blobs/... exists but it can not be written at Microsimulation() construction, i.e. the macOS runner's HF cache. main's last run (2026-09-16) and every other PR branch this month were green on the same job, so a re-run should clear it.
Root cause, worth stating in the PR body. The class-level uprating = "..." attribute is dead metadata: nothing in policyengine-uk reads it, and policyengine-core only looks at it to refuse combining it with its own @uprated decorator. data/uprating_indices.yaml is the only mechanism (apply_single_year_uprating / reset_growthfactor_uprating in data/economic_assumptions.py). A declaration without a YAML entry therefore does nothing, which is exactly what #1859 observed.
Same gap elsewhere — see the inline comment on the YAML. Happy for that to be a follow-up issue rather than scope creep here.
Downstream note: the populace UK build levels LCFS energy to the FY2024 base year and binds the NEED/DESNZ targets there, so base-year targets don't move; projected-year energy outputs from populace datasets will rise with CPI once this lands, which is the intended correction.
| - communication_consumption | ||
| - domestic_energy_consumption | ||
| - education_consumption | ||
| - electricity_consumption |
There was a problem hiding this comment.
Four more dataset columns declare uprating but are missing from this list, and I measured them flat 2024 → 2027 on the same dataset:
water_and_sewerage_charges(declaresindices.ofwat.water_bills) — 375.34 in both yearshousing_service_charges(indices.obr.lagged_average_earnings) — 91.89pension_contributions_via_salary_sacrifice(indices.obr.average_earnings) — 417.07rail_usage(gov.dft.rail.ridership_index) — 483.10
Also savings_interest_income declares indices.ons.household_interest_income, but this file applies per_capita.gdp to it.
Since the class attribute is never read, the durable fix is a code-health test (natural home: policyengine_uk/tests/code_health/) asserting that every variable declaring uprating appears in this file under the matching index. Two of the four above point at indices that may have no yoy_growth parameter yet, so they probably need their own PR — but the guard would make the gap visible instead of silent.
|
Thanks — the root-cause framing is better than mine and I've moved it into the PR body: the class-level CI. I verified your diagnosis independently before accepting it: 56 The other four. Reproduced all of them on I'd agree the code-health guard is the durable fix: it would have caught this at the point it was introduced, rather than in a downstream study three data releases later. On the downstream note — that is exactly our situation. Our cost-of-living study has the energy channel as its largest component, and the baseline it multiplies was carrying 2024 prices labelled 2027-28. Once this lands we regenerate, and the headline moves by roughly CPI. |
|
Test job: three re-runs, three identical failures — it is the runner's Hugging Face cache, not this PR. I am not going to re-run it a fourth time; flagging for whoever owns the workflow instead. Evidence:
It is a write-permission failure on an already-present cached blob, so an HF token would not change anything — the fix is on the runner side, most likely a restored cache with bad ownership, or not restoring the HF cache across runs. Happy to rebase on main if that would pick up a cache-key change, but I do not think there is anything to fix in the diff. |
juaristi22
left a comment
There was a problem hiding this comment.
Correction to my earlier review: this is not a runner flake, and re-runs won't help.
huggingface_hub 1.32.0 (released 2026-09-17) introduced a shared blob store that keeps downloads read-only under hub/blobs/<prefix>/<hash> — the exact path in every error here — and dataset_schema.py opened HDF5 files in pandas' default append mode. The last green PR run on 2026-09-16 installed hub 1.31.0; every run today installed 1.32.0. So the failure is deterministic on any branch without the loader fix.
The fix (mode="r" in dataset_schema.py) reached main today via #1861 (b1e5305). The cgt-schedules-1858 branch went green at 10:55 on that commit, not from cache recovery — its 10:27 failure was on the commit before it. This PR is based on 709a9b6, before the fix, which is why three re-runs failed identically.
Verified the post-rebase state locally. Cherry-picking this PR onto current main applies cleanly (#1861's edit to uprating_indices.yaml is in the per_capita.gdp block). On that tree the full policyengine_uk/tests suite passes with zero failures, and the five modules that were red here — test_reform_impacts, test_uc_deductions_aggregates, test_salary_sacrifice_cap_reform, test_state_pension_reform, test_behavioral_responses — pass 37/37 with the dataset token set.
Approving on the condition of a rebase onto main. The diff is correct and needs no change; please rebase (or merge main), let the run go green, and merge then. #1862 stands for the other four columns.
Both variables declare
uprating = "gov.economic_assumptions.indices.obr.consumer_price_index"
but were missing from data/uprating_indices.yaml, which is the list
reset_growthfactor_uprating actually reads. They therefore returned identical
values in every year while every other consumption variable on the same index
rose with CPI.
On enhanced_frs_2024_25, 2024 -> 2027:
before electricity_consumption 838.29 -> 838.29 (+0.0%)
gas_consumption 658.36 -> 658.36 (+0.0%)
domestic_energy_consumption 1496.65 -> 1614.79 (+7.9%)
after electricity_consumption 838.29 -> 904.47 (+7.9%)
gas_consumption 658.36 -> 710.33 (+7.9%)
domestic_energy_consumption 1496.65 -> 1614.79 (+7.9%)
This also restores the identity the documentation implies. In the raw dataset
domestic_energy_consumption equals electricity_consumption + gas_consumption
exactly; after uprating they diverged by 7.9% from 2025 onward, because only
the combined variable was in the list. They now agree in every year.
The entries are inserted alphabetically within the CPI block, matching the
surrounding style. The list as a whole is not fully sorted, so this does not
reorder anything else.
Fixes #1859.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
73f65e4 to
c71d5ea
Compare
|
Rebased onto main ( I had concluded "flaky runner cache" from the fact that Verified your explanation before acting on it: Post-rebase, as you predicted:
The lesson I'll take: "it passed on re-run elsewhere" is weak evidence for a flake when the two runs sat on different base commits. I should have diffed the bases before concluding infrastructure. Waiting on the run to go green, then this is ready to merge. #1862 still stands for the other four columns and the code-health guard. |
Addresses the three findings on this PR. C1: the changelog fragment had no type component, so towncrier omitted it entirely — the draft rendered "No significant changes". Renamed to energy-not-cpi-uprated.fixed.md, per changelog.d/<branch>.<type>.md in CONTRIBUTING, and the leading bullet removed so towncrier does not double it. Verified the draft now renders it under Fixed. A1: the wording claimed more than the change delivers, and the reviewer is right. uprating_indices.yaml governs dataset projection. It does not govern the class-level `uprating` attribute, which policyengine-core still uses to carry a direct situation input forward: a 2024 electricity_consumption input queried at 2027 returns 1078.93 against 1000, which I confirmed directly. That path is deliberately left alone. A value a user supplies for 2024 may be their own contemporaneous bill rather than this build's artifact, so it has no claim on the build's price basis. The YAML header, the test docstring and the test name now say "projection" rather than making a global claim. Worth recording because #1860 and #1862 both described the class-level attribute as dead metadata that nothing reads. That is true of dataset projection and false of the direct-input path; core reads it there. A2: docs/book/assumptions/growthfactors.md still listed domestic_energy_consumption under "all consumption categories" get CPI. The list now excludes the three energy variables and states why. Full suite: 266 passed, 45 skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Stop CPI-uprating energy, which the data build already prices Reverses the direction of #1860, which I wrote. Fixes #1867. policyengine-uk-data calibrates the energy variables to NEED mean kWh by income band and converts to pounds at Ofgem Q2 2026 unit rates. Its imputations/consumption.py says so outright: "the stored £/yr values represent FY26/27 price levels. Energy variables are not CPI-uprated, so this avoids the need for price-level adjustment at simulation time." uprating_indices.yaml uprates from the dataset's DATA year, 2024. So applying CPI to these variables re-applies 2024-2026 price changes the build had already priced in — about 5.8pp of a 7.9% uplift. The cap parameter falls over this period, which makes the stored price level testable. On enhanced_frs_2024_25 the modelled mean of electricity + gas is £1,584, against cap parameters of £2,389 (2024), £1,849 (2025) and £1,641 (2026). A 2024-priced series would have to sit near the 2024 cap; it sits just below the 2026 one, which is the April 2026 level the docstring describes. #1859 read the symptom backwards and #1860 followed it. The flat pair was right — accidentally, being absent from the YAML rather than deliberately excluded — and domestic_energy_consumption, on the CPI list since before 2.90.2, was carrying the double count. #1860 restored the documented identity by propagating the defect to all three. Removing all three restores the identity AND holds the level: electricity £895 + gas £689 = £1,584 = domestic, in every year from 2024 to 2027. Other consumption variables come from the LCFS at data-year prices and do need uprating, so only these three are excluded. The rationale is recorded at the top of the YAML, and a code-health test asserts they appear under no index. Verified that test fails when one is re-added rather than only passing today. Downstream: modelled energy spending in projected years falls about 8%, back to the build's own price level. Anyone with pinned regression values on domestic_energy_consumption will see them move; that movement is the correction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Scope the energy exclusion to dataset projection, and fix the fragment Addresses the three findings on this PR. C1: the changelog fragment had no type component, so towncrier omitted it entirely — the draft rendered "No significant changes". Renamed to energy-not-cpi-uprated.fixed.md, per changelog.d/<branch>.<type>.md in CONTRIBUTING, and the leading bullet removed so towncrier does not double it. Verified the draft now renders it under Fixed. A1: the wording claimed more than the change delivers, and the reviewer is right. uprating_indices.yaml governs dataset projection. It does not govern the class-level `uprating` attribute, which policyengine-core still uses to carry a direct situation input forward: a 2024 electricity_consumption input queried at 2027 returns 1078.93 against 1000, which I confirmed directly. That path is deliberately left alone. A value a user supplies for 2024 may be their own contemporaneous bill rather than this build's artifact, so it has no claim on the build's price basis. The YAML header, the test docstring and the test name now say "projection" rather than making a global claim. Worth recording because #1860 and #1862 both described the class-level attribute as dead metadata that nothing reads. That is true of dataset projection and false of the direct-input path; core reads it there. A2: docs/book/assumptions/growthfactors.md still listed domestic_energy_consumption under "all consumption categories" get CPI. The list now excludes the three energy variables and states why. Full suite: 266 passed, 45 skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follow-up to #1860, closing most of #1862. Three variables declared an uprating index but were missing from uprating_indices.yaml, so they were never uprated. On enhanced_frs_2024_25, 2024 -> 2027: water_and_sewerage_charges 375.51 -> 522.12 (+39.0%) housing_service_charges 91.81 -> 105.06 (+14.4%) pension_contributions_via_salary_sacrifice 418.69 -> 466.81 (+11.5%) Each matches its index compounded over the same years exactly: ofwat water bills +39.0%, OBR lagged average earnings +14.4%, OBR average earnings +11.5%. All three indices already had the yoy_growth twin the YAML needs, so this is a YAML-only change. rail_usage is deliberately NOT included. Its declared index, gov.dft.rail.ridership_index, is a CUMULATIVE index with 2020 = 1.0 — "Used for uprating the quantity component of rail subsidy spending" — not a year-on-year rate. Adding it to a yoy_growth block compounds the level and uprates the variable by about 684% over 2024-27. Uprating it properly needs a year-on-year series, which is more than a YAML entry. The durable fix is the code-health test suggested in review of #1860: policyengine_uk/tests/code_health/test_uprating_declarations.py asserts that every variable declaring `uprating` appears in the YAML under the matching index. Verified it fails when an entry is removed, rather than only passing today. Three exceptions are listed with reasons rather than silently tolerated: rail_usage and employee_pension_contributions_reported as not uprated, and savings_interest_income as uprated by a different index from the one it declares — the mismatch noted in #1862, left for someone with the context to say which is intended. A third test keeps those lists honest by asserting each entry still exists and still declares uprating. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follow-up to #1860, closing most of #1862. Three variables declared an uprating index but were missing from uprating_indices.yaml, so they were never uprated. On enhanced_frs_2024_25, 2024 -> 2027: water_and_sewerage_charges 375.51 -> 522.12 (+39.0%) housing_service_charges 91.81 -> 105.06 (+14.4%) pension_contributions_via_salary_sacrifice 418.69 -> 466.81 (+11.5%) Each matches its index compounded over the same years exactly: ofwat water bills +39.0%, OBR lagged average earnings +14.4%, OBR average earnings +11.5%. All three indices already had the yoy_growth twin the YAML needs, so this is a YAML-only change. rail_usage is deliberately NOT included. Its declared index, gov.dft.rail.ridership_index, is a CUMULATIVE index with 2020 = 1.0 — "Used for uprating the quantity component of rail subsidy spending" — not a year-on-year rate. Adding it to a yoy_growth block compounds the level and uprates the variable by about 684% over 2024-27. Uprating it properly needs a year-on-year series, which is more than a YAML entry. The durable fix is the code-health test suggested in review of #1860: policyengine_uk/tests/code_health/test_uprating_declarations.py asserts that every variable declaring `uprating` appears in the YAML under the matching index. Verified it fails when an entry is removed, rather than only passing today. Three exceptions are listed with reasons rather than silently tolerated: rail_usage and employee_pension_contributions_reported as not uprated, and savings_interest_income as uprated by a different index from the one it declares — the mismatch noted in #1862, left for someone with the context to say which is intended. A third test keeps those lists honest by asserting each entry still exists and still declares uprating. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fixes #1859.
Root cause
The class-level
uprating = "..."attribute on aVariableis dead metadata: nothing in policyengine-uk reads it, and policyengine-core only inspects it to refuse combining it with its own@uprateddecorator.data/uprating_indices.yamlis the only mechanism that actually applies uprating (apply_single_year_uprating/reset_growthfactor_upratingindata/economic_assumptions.py).So a variable can declare an index and silently never be uprated. That is exactly what happened here.
The bug
electricity_consumptionandgas_consumptionboth declarein
variables/input/consumption/energy.py, but they were missing fromdata/uprating_indices.yaml— the listreset_growthfactor_upratingactually reads. So they returned identical values in every year while every other consumption variable on the same index rose with CPI.Effect, on
enhanced_frs_2024_25electricity_consumptiongas_consumptiondomestic_energy_consumptionIt also fixes the second symptom in the issue
domestic_energy_consumptionis documented as "Combined gas and electric bills". In the raw dataset it equalselectricity_consumption + gas_consumptionexactly — I verified this directly against the HDF5. But after uprating they diverged by 7.9% from 2025 onward, because only the combined variable was in the list.With this change they agree in every year: elec+gas = 1614.79 = domestic in 2027. So the two symptoms had one cause, and there is no separate calibration difference to reconcile.
Why it matters
2024 was near the tail of the energy crisis —
gov.ofgem.energy_price_capfalls from £2,389 (2024) to £1,641 (2026 onward) — so a frozen 2024 energy base is materially mis-levelled against later years. Any downstream study using these variables carried a 2024-priced energy baseline labelled as its target year. We hit this in a cost-of-living study where the energy channel is the largest single component.Verification
policyengine_uk/testssuite, no failures.CI
The red Test job is not this PR: all failures are
PermissionError: file /Users/runner/.cache/huggingface/hub/blobs/... exists but it can not be writtenatMicrosimulation()construction — the macOS runner's HF cache. I counted 56 such errors in the failed log and zero mentions ofelectricity_consumption,gas_consumptionoruprating_indices. Re-run requested.Same gap elsewhere
Four more variables declare
upratingbut are missing from the YAML, and measure flat 2024 → 2027:water_and_sewerage_charges,housing_service_charges,pension_contributions_via_salary_sacrifice,rail_usage(plus an index mismatch onsavings_interest_income). Filed separately as #1862 with a suggested code-health guard, to keep this PR to the energy fix.Note on scope
This changes modelled energy spending in every year after the base year, so downstream results that use these variables will move by roughly CPI. That is the intended correction, but it is worth flagging for anyone with pinned regression values.
🤖 Generated with Claude Code