neighbour_divergence: key cohorts on main-heating fuel

The neighbour SAP-divergence cohort was (postcode, property_type, built_form),
which mixed electric- and gas-heated dwellings. Electricity scores materially
lower in SAP than mains gas for identical fabric, so a mixed-fuel postcode
produced cross-fuel false outliers — an electric dwelling flagged only for being
electric among gas neighbours.

Add the main-heating fuel class to the cohort key (electricity variants — 29/30
+ off-peak 31-40 — collapse to one class; every other code is its own bucket).
Now every flagged divergence is a same-fuel comparison worth investigating. On
portfolio 814 this refined 20 raw divergences to 17 same-fuel ones while keeping
the genuine within-fuel outliers (e.g. the all-electric WC2B 4AW flats at SAP
26/38 vs a cohort median of 67).

Reaches the fuel via epc_main_heating_detail through the indexed property_id —
still never touches the recommendation table. Surfaced by the portfolio-814
recommendation audit (Work item B, #1388).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jun-te Kim 2026-07-01 14:24:31 +00:00
parent e95c3cf906
commit 009394bb19
3 changed files with 202 additions and 456 deletions

View file

@ -1,463 +1,121 @@
# Modelling anomaly audit
Scanned **31919** properties · flagged **10563** anomalies across **10** checks.
Scanned **338** properties · flagged **360** anomalies across **6** checks.
## impossible-sap-over-100 (HIGH) — 1
## plan-score-below-baseline (HIGH) — 3
- property **726993** (uprn 100061757571): SAP > 100: effective 102.0
- property **742302** (uprn 100022921559): post SAP 70.5 below effective baseline 72.0 (Δ-1.5)
- property **742367** (uprn 5300072135): post SAP 68.9 below effective baseline 70.0 (Δ-1.1)
- property **742368** (uprn 5300072136): post SAP 70.4 below effective baseline 71.0 (Δ-0.6)
## plan-below-baseline-band (HIGH) — 363
## plan-stops-short-of-goal (HIGH) — 311
- property **709810** (uprn 10096028301): post C (78.02813) worse than effective baseline B (85)
- property **709846** (uprn 10096399556): post C (79.7374) worse than effective baseline A (93)
- property **709847** (uprn 10096028354): post C (78.695816) worse than effective baseline B (91)
- property **709850** (uprn 10096028348): post C (78.750984) worse than effective baseline B (89)
- property **709959** (uprn 10096028306): post C (78.14567) worse than effective baseline B (84)
- property **710011** (uprn 10096028349): post C (78.750984) worse than effective baseline B (89)
- property **710071** (uprn 10002918889): post C (76.07915) worse than effective baseline B (82)
- property **710075** (uprn 10002918890): post C (79.84036) worse than effective baseline B (82)
- property **710117** (uprn 10096399566): post C (79.86282) worse than effective baseline A (93)
- property **710121** (uprn 10096028307): post C (78.790596) worse than effective baseline B (90)
- property **710131** (uprn 10096028350): post C (80.142784) worse than effective baseline A (94)
- property **710201** (uprn 10090944222): post C (74.58814) worse than effective baseline B (82)
- property **710222** (uprn 10096399567): post C (79.84616) worse than effective baseline A (93)
- property **710225** (uprn 10096028308): post C (78.78894) worse than effective baseline B (90)
- property **710241** (uprn 10096028351): post C (80.142784) worse than effective baseline A (94)
- property **710326** (uprn 10096028309): post C (78.610855) worse than effective baseline B (89)
- property **710335** (uprn 10096028352): post C (79.9757) worse than effective baseline A (94)
- property **710395** (uprn 10096028310): post C (79.46583) worse than effective baseline B (91)
- property **710474** (uprn 10096028355): post C (78.47655) worse than effective baseline B (91)
- property **710479** (uprn 10096028353): post C (80.291725) worse than effective baseline A (95)
- property **710537** (uprn 10096028311): post C (79.46583) worse than effective baseline B (91)
- property **710540** (uprn 100060714157): post D (68.24699) worse than effective baseline C (71)
- property **710760** (uprn 10096028302): post C (78.28315) worse than effective baseline B (85)
- property **710800** (uprn 10096399558): post C (79.7374) worse than effective baseline A (93)
- property **710802** (uprn 10096028356): post C (78.47655) worse than effective baseline B (91)
- property **710946** (uprn 44012846): post C (79.819626) worse than effective baseline B (81)
- property **711027** (uprn 10096028357): post C (77.96618) worse than effective baseline B (90)
- property **711178** (uprn 10091636026): post C (76.05113) worse than effective baseline B (81)
- property **711195** (uprn 10096028303): post C (80.00826) worse than effective baseline B (86)
- property **711236** (uprn 10096399560): post C (79.7374) worse than effective baseline A (93)
- property **711238** (uprn 10096028358): post C (78.695816) worse than effective baseline B (91)
- property **711312** (uprn 10096028346): post C (80.1876) worse than effective baseline A (93)
- property **711376** (uprn 10096028359): post C (78.47655) worse than effective baseline B (91)
- property **711489** (uprn 10096028304): post C (80.3187) worse than effective baseline B (86)
- property **711523** (uprn 10096399562): post C (79.7374) worse than effective baseline A (93)
- property **711524** (uprn 10096028360): post C (78.47655) worse than effective baseline B (91)
- property **711539** (uprn 68159801): post D (66.09142) worse than effective baseline C (71)
- property **711575** (uprn 10096028347): post C (80.1876) worse than effective baseline A (94)
- property **711639** (uprn 10096028361): post C (78.88584) worse than effective baseline B (91)
- property **711706** (uprn 10096028305): post C (78.71836) worse than effective baseline B (85)
- property **711715** (uprn 10013924857): post C (79.91303) worse than effective baseline B (81)
- property **711732** (uprn 100062190435): post C (77.935425) worse than effective baseline B (82)
- property **711795** (uprn 10090343115): post E (52.785263) worse than effective baseline C (73)
- property **711821** (uprn 10096399575): post C (80.209465) worse than effective baseline A (93)
- property **711824** (uprn 10094615095): post C (78.01443) worse than effective baseline A (92)
- property **711858** (uprn 22245014): post C (79.352325) worse than effective baseline B (81)
- property **711881** (uprn 10023444014): post C (79.504456) worse than effective baseline B (81)
- property **711897** (uprn 10012025246): post C (76.70494) worse than effective baseline B (81)
- property **711898** (uprn 10094615103): post C (79.97074) worse than effective baseline A (92)
- property **711917** (uprn 10012027840): post C (72.92677) worse than effective baseline B (81)
- … and 313 more (see CSV)
- property **742063** (uprn 10010200962): post D (60.29299) short of goal B on an unlimited-budget scenario (cost_of_works £10378)
- property **742064** (uprn 10010206037): post C (69.27856) short of goal B on an unlimited-budget scenario (cost_of_works £9339)
- property **742065** (uprn 10010206038): post C (78.81704) short of goal B on an unlimited-budget scenario (cost_of_works £1043)
- property **742066** (uprn 10010206039): post C (76.22735) short of goal B on an unlimited-budget scenario (cost_of_works £7876)
- property **742067** (uprn 10010206040): post C (72.775085) short of goal B on an unlimited-budget scenario (cost_of_works £7682)
- property **742068** (uprn 10010206041): post C (74.29278) short of goal B on an unlimited-budget scenario (cost_of_works £8510)
- property **742069** (uprn 10010206042): post C (70.24012) short of goal B on an unlimited-budget scenario (cost_of_works £7638)
- property **742070** (uprn 10010206043): post C (72.3706) short of goal B on an unlimited-budget scenario (cost_of_works £3702)
- property **742072** (uprn 34003067): post D (61.096947) short of goal B on an unlimited-budget scenario (cost_of_works £13391)
- property **742073** (uprn 34003068): post D (61.096947) short of goal B on an unlimited-budget scenario (cost_of_works £13391)
- property **742075** (uprn 34003070): post D (61.096947) short of goal B on an unlimited-budget scenario (cost_of_works £13391)
- property **742076** (uprn 34003071): post D (61.096947) short of goal B on an unlimited-budget scenario (cost_of_works £13391)
- property **742079** (uprn 12013027): post C (78.44673) short of goal B on an unlimited-budget scenario (cost_of_works £2892)
- property **742080** (uprn 12013028): post D (62.603214) short of goal B on an unlimited-budget scenario (cost_of_works £3372)
- property **742081** (uprn 12013029): post C (74.525345) short of goal B on an unlimited-budget scenario (cost_of_works £1029)
- property **742082** (uprn 12013030): post C (78.44673) short of goal B on an unlimited-budget scenario (cost_of_works £2892)
- property **742083** (uprn 12013031): post C (78.44673) short of goal B on an unlimited-budget scenario (cost_of_works £2892)
- property **742084** (uprn 12013032): post C (73.37248) short of goal B on an unlimited-budget scenario (cost_of_works £1057)
- property **742085** (uprn 12013033): post D (68.01724) short of goal B on an unlimited-budget scenario (cost_of_works £1057)
- property **742086** (uprn 12013034): post D (61.581734) short of goal B on an unlimited-budget scenario (cost_of_works £3610)
- property **742087** (uprn 12013038): post C (78.44673) short of goal B on an unlimited-budget scenario (cost_of_works £2892)
- property **742088** (uprn 12013042): post C (74.92009) short of goal B on an unlimited-budget scenario (cost_of_works £3404)
- property **742090** (uprn 12013044): post C (73.35894) short of goal B on an unlimited-budget scenario (cost_of_works £1057)
- property **742091** (uprn 12013045): post C (73.37248) short of goal B on an unlimited-budget scenario (cost_of_works £1057)
- property **742092** (uprn 12013046): post D (60.531925) short of goal B on an unlimited-budget scenario (cost_of_works £1029)
- property **742093** (uprn 12013047): post C (74.26961) short of goal B on an unlimited-budget scenario (cost_of_works £2899)
- property **742094** (uprn 12013048): post C (78.44673) short of goal B on an unlimited-budget scenario (cost_of_works £2892)
- property **742095** (uprn 100020233237): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742096** (uprn 100020233238): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742097** (uprn 100020233239): post C (72.782684) short of goal B on an unlimited-budget scenario (cost_of_works £7684)
- property **742098** (uprn 100020233240): post D (67.203026) short of goal B on an unlimited-budget scenario (cost_of_works £633)
- property **742099** (uprn 100020233241): post D (67.30785) short of goal B on an unlimited-budget scenario (cost_of_works £3400)
- property **742100** (uprn 100020233242): post C (68.658844) short of goal B on an unlimited-budget scenario (cost_of_works £35)
- property **742101** (uprn 100020233243): post D (66.59807) short of goal B on an unlimited-budget scenario (cost_of_works £3285)
- property **742102** (uprn 100020233244): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742103** (uprn 100020233204): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742104** (uprn 100020233205): post D (66.40878) short of goal B on an unlimited-budget scenario (cost_of_works £32)
- property **742105** (uprn 100020233206): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742106** (uprn 100020233207): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742107** (uprn 100020233208): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742108** (uprn 100020233209): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742109** (uprn 100020233210): post C (74.14777) short of goal B on an unlimited-budget scenario (cost_of_works £3070)
- property **742110** (uprn 100020233211): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742111** (uprn 100020233212): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742112** (uprn 100020233213): post C (68.751595) short of goal B on an unlimited-budget scenario (cost_of_works £0)
- property **742113** (uprn 100020233235): post C (69.19524) short of goal B on an unlimited-budget scenario (cost_of_works £4861)
- property **742114** (uprn 100020233236): post C (73.46247) short of goal B on an unlimited-budget scenario (cost_of_works £7126)
- property **742116** (uprn 100020942574): post D (67.459236) short of goal B on an unlimited-budget scenario (cost_of_works £28)
- property **742117** (uprn 100020942575): post D (67.459236) short of goal B on an unlimited-budget scenario (cost_of_works £28)
- property **742118** (uprn 100020942576): post D (67.459236) short of goal B on an unlimited-budget scenario (cost_of_works £28)
- … and 261 more (see CSV)
## plan-score-below-baseline (HIGH) — 1631
## already-meets-goal-with-works (MEDIUM) — 4
- property **709790** (uprn 10023443426): post SAP 74.2 below effective baseline 76.0 (Δ-1.8)
- property **709810** (uprn 10096028301): post SAP 78.0 below effective baseline 85.0 (Δ-7.0)
- property **709846** (uprn 10096399556): post SAP 79.7 below effective baseline 93.0 (Δ-13.3)
- property **709847** (uprn 10096028354): post SAP 78.7 below effective baseline 91.0 (Δ-12.3)
- property **709850** (uprn 10096028348): post SAP 78.8 below effective baseline 89.0 (Δ-10.2)
- property **709959** (uprn 10096028306): post SAP 78.1 below effective baseline 84.0 (Δ-5.9)
- property **709970** (uprn 10013924859): post SAP 79.2 below effective baseline 80.0 (Δ-0.8)
- property **709975** (uprn 200001466609): post SAP 72.3 below effective baseline 79.0 (Δ-6.7)
- property **710011** (uprn 10096028349): post SAP 78.8 below effective baseline 89.0 (Δ-10.2)
- property **710071** (uprn 10002918889): post SAP 76.1 below effective baseline 82.0 (Δ-5.9)
- property **710075** (uprn 10002918890): post SAP 79.8 below effective baseline 82.0 (Δ-2.2)
- property **710117** (uprn 10096399566): post SAP 79.9 below effective baseline 93.0 (Δ-13.1)
- property **710121** (uprn 10096028307): post SAP 78.8 below effective baseline 90.0 (Δ-11.2)
- property **710122** (uprn 100090187902): post SAP 72.4 below effective baseline 74.0 (Δ-1.6)
- property **710131** (uprn 10096028350): post SAP 80.1 below effective baseline 94.0 (Δ-13.9)
- property **710140** (uprn 10023302889): post SAP 76.9 below effective baseline 79.0 (Δ-2.1)
- property **710201** (uprn 10090944222): post SAP 74.6 below effective baseline 82.0 (Δ-7.4)
- property **710222** (uprn 10096399567): post SAP 79.8 below effective baseline 93.0 (Δ-13.2)
- property **710225** (uprn 10096028308): post SAP 78.8 below effective baseline 90.0 (Δ-11.2)
- property **710241** (uprn 10096028351): post SAP 80.1 below effective baseline 94.0 (Δ-13.9)
- property **710274** (uprn 10013924864): post SAP 74.8 below effective baseline 76.0 (Δ-1.2)
- property **710326** (uprn 10096028309): post SAP 78.6 below effective baseline 89.0 (Δ-10.4)
- property **710335** (uprn 10096028352): post SAP 80.0 below effective baseline 94.0 (Δ-14.0)
- property **710362** (uprn 10090317710): post SAP 75.5 below effective baseline 79.0 (Δ-3.5)
- property **710395** (uprn 10096028310): post SAP 79.5 below effective baseline 91.0 (Δ-11.5)
- property **710472** (uprn 10013918445): post SAP 76.9 below effective baseline 79.0 (Δ-2.1)
- property **710474** (uprn 10096028355): post SAP 78.5 below effective baseline 91.0 (Δ-12.5)
- property **710479** (uprn 10096028353): post SAP 80.3 below effective baseline 95.0 (Δ-14.7)
- property **710525** (uprn 10012028784): post SAP 69.6 below effective baseline 79.0 (Δ-9.4)
- property **710537** (uprn 10096028311): post SAP 79.5 below effective baseline 91.0 (Δ-11.5)
- property **710540** (uprn 100060714157): post SAP 68.2 below effective baseline 71.0 (Δ-2.8)
- property **710544** (uprn 10008052006): post SAP 81.1 below effective baseline 83.0 (Δ-1.9)
- property **710552** (uprn 100060706143): post SAP 83.0 below effective baseline 85.0 (Δ-2.0)
- property **710569** (uprn 200000546526): post SAP 70.8 below effective baseline 73.0 (Δ-2.2)
- property **710576** (uprn 100090187795): post SAP 72.4 below effective baseline 75.0 (Δ-2.6)
- property **710645** (uprn 10009433145): post SAP 82.4 below effective baseline 83.0 (Δ-0.6)
- property **710650** (uprn 200001530089): post SAP 72.9 below effective baseline 74.0 (Δ-1.1)
- property **710686** (uprn 10009433147): post SAP 82.1 below effective baseline 83.0 (Δ-0.9)
- property **710760** (uprn 10096028302): post SAP 78.3 below effective baseline 85.0 (Δ-6.7)
- property **710785** (uprn 44006007): post SAP 75.3 below effective baseline 76.0 (Δ-0.7)
- property **710792** (uprn 5300059024): post SAP 75.7 below effective baseline 79.0 (Δ-3.3)
- property **710800** (uprn 10096399558): post SAP 79.7 below effective baseline 93.0 (Δ-13.3)
- property **710802** (uprn 10096028356): post SAP 78.5 below effective baseline 91.0 (Δ-12.5)
- property **710841** (uprn 200003688154): post SAP 70.3 below effective baseline 72.0 (Δ-1.7)
- property **710895** (uprn 100020475290): post SAP 72.4 below effective baseline 73.0 (Δ-0.6)
- property **710911** (uprn 10010221820): post SAP 82.2 below effective baseline 84.0 (Δ-1.8)
- property **710946** (uprn 44012846): post SAP 79.8 below effective baseline 81.0 (Δ-1.2)
- property **710955** (uprn 10090844951): post SAP 78.1 below effective baseline 79.0 (Δ-0.9)
- property **710988** (uprn 10023371802): post SAP 73.3 below effective baseline 75.0 (Δ-1.7)
- property **711014** (uprn 5300088717): post SAP 72.5 below effective baseline 74.0 (Δ-1.5)
- … and 1581 more (see CSV)
- property **742077** (uprn 34156817): already B >= goal B but cost_of_works £4515
- property **742078** (uprn 34156818): already B >= goal B but cost_of_works £4515
- property **742207** (uprn 100081143001): already B >= goal B but cost_of_works £1029
- property **742269** (uprn 100022769436): already B >= goal B but cost_of_works £1029
## already-meets-goal-with-works (MEDIUM) — 1162
## zero-works-post-differs (MEDIUM) — 2
- property **709775** (uprn 100020933699): already C >= goal C but cost_of_works £32
- property **709875** (uprn 100020973465): already C >= goal C but cost_of_works £38
- property **709986** (uprn 200000539408): already C >= goal C but cost_of_works £32
- property **709992** (uprn 100022908998): already C >= goal C but cost_of_works £555
- property **710005** (uprn 100090178307): already C >= goal C but cost_of_works £21
- property **710033** (uprn 100022920891): already C >= goal C but cost_of_works £855
- property **710084** (uprn 200003444301): already C >= goal C but cost_of_works £505
- property **710185** (uprn 100020650847): already C >= goal C but cost_of_works £455
- property **710221** (uprn 6701328): already C >= goal C but cost_of_works £655
- property **710247** (uprn 100020432467): already C >= goal C but cost_of_works £555
- property **710298** (uprn 100020220397): already C >= goal C but cost_of_works £4515
- property **710331** (uprn 100020492824): already C >= goal C but cost_of_works £855
- property **710400** (uprn 100021011618): already C >= goal C but cost_of_works £3725
- property **710484** (uprn 100060316083): already C >= goal C but cost_of_works £24
- property **710517** (uprn 100020951618): already C >= goal C but cost_of_works £1029
- property **710525** (uprn 10012028784): already C >= goal C but cost_of_works £11539
- property **710539** (uprn 100021973960): already C >= goal C but cost_of_works £505
- property **710540** (uprn 100060714157): already C >= goal C but cost_of_works £11600
- property **710555** (uprn 100060718869): already C >= goal C but cost_of_works £28
- property **710574** (uprn 100020947162): already C >= goal C but cost_of_works £28
- property **710690** (uprn 200003688150): already C >= goal C but cost_of_works £505
- property **710703** (uprn 100020438146): already C >= goal C but cost_of_works £32
- property **710707** (uprn 100061820799): already C >= goal C but cost_of_works £32
- property **710713** (uprn 200003497667): already C >= goal C but cost_of_works £11082
- property **710828** (uprn 100060714174): already C >= goal C but cost_of_works £21
- property **710889** (uprn 200003469113): already C >= goal C but cost_of_works £455
- property **711058** (uprn 5300059062): already C >= goal C but cost_of_works £3962
- property **711096** (uprn 100020455891): already C >= goal C but cost_of_works £555
- property **711099** (uprn 100020229279): already C >= goal C but cost_of_works £1029
- property **711334** (uprn 5300036435): already C >= goal C but cost_of_works £476
- property **711390** (uprn 100023263012): already C >= goal C but cost_of_works £505
- property **711539** (uprn 68159801): already C >= goal C but cost_of_works £2436
- property **711679** (uprn 100021005287): already C >= goal C but cost_of_works £455
- property **711694** (uprn 100062191221): already C >= goal C but cost_of_works £18
- property **711795** (uprn 10090343115): already C >= goal C but cost_of_works £662
- property **712249** (uprn 100021939292): already C >= goal C but cost_of_works £1029
- property **712279** (uprn 10090343152): already C >= goal C but cost_of_works £1029
- property **712426** (uprn 100062208849): already C >= goal C but cost_of_works £530
- property **712446** (uprn 10090343167): already C >= goal C but cost_of_works £1029
- property **712690** (uprn 10035061455): already C >= goal C but cost_of_works £2790
- property **712697** (uprn 100060742520): already C >= goal C but cost_of_works £416
- property **712764** (uprn 100060675900): already C >= goal C but cost_of_works £32
- property **712766** (uprn 100021961011): already C >= goal C but cost_of_works £2566
- property **712801** (uprn 100061734876): already C >= goal C but cost_of_works £555
- property **712831** (uprn 100061736377): already C >= goal C but cost_of_works £1282
- property **712864** (uprn 100061738178): already C >= goal C but cost_of_works £455
- property **712865** (uprn 100061738325): already C >= goal C but cost_of_works £14266
- property **712869** (uprn 100061738604): already C >= goal C but cost_of_works £18
- property **712874** (uprn 100061757360): already C >= goal C but cost_of_works £755
- property **712899** (uprn 100061739860): already C >= goal C but cost_of_works £28
- … and 1112 more (see CSV)
- property **742302** (uprn 100022921559): £0 works but post SAP 70.5 != effective 72.0
- property **742367** (uprn 5300072135): £0 works but post SAP 68.9 != effective 70.0
## excessive-solar-sap (MEDIUM) — 51
## effective-lodged-divergence (LOW) — 9
- property **710374** (uprn 10090342188): solar PV alone earns 26.1 SAP points (likely oversized array)
- property **713238** (uprn 200004784741): solar PV alone earns 32.6 SAP points (likely oversized array)
- property **714227** (uprn 100061738603): solar PV alone earns 33.9 SAP points (likely oversized array)
- property **714257** (uprn 100061740105): solar PV alone earns 29.8 SAP points (likely oversized array)
- property **714511** (uprn 100061761168): solar PV alone earns 32.3 SAP points (likely oversized array)
- property **714977** (uprn 100061761946): solar PV alone earns 31.4 SAP points (likely oversized array)
- property **715563** (uprn 100061761947): solar PV alone earns 28.5 SAP points (likely oversized array)
- property **715595** (uprn 10002468656): solar PV alone earns 29.3 SAP points (likely oversized array)
- property **715740** (uprn 100061764300): solar PV alone earns 27.3 SAP points (likely oversized array)
- property **716734** (uprn 10002469029): solar PV alone earns 31.0 SAP points (likely oversized array)
- property **716740** (uprn 100061753334): solar PV alone earns 31.1 SAP points (likely oversized array)
- property **717201** (uprn 100091206047): solar PV alone earns 31.3 SAP points (likely oversized array)
- property **718323** (uprn 10002472608): solar PV alone earns 25.2 SAP points (likely oversized array)
- property **718371** (uprn 100061764075): solar PV alone earns 35.5 SAP points (likely oversized array)
- property **718890** (uprn 100062344151): solar PV alone earns 31.9 SAP points (likely oversized array)
- property **719064** (uprn 100021004675): solar PV alone earns 25.6 SAP points (likely oversized array)
- property **719080** (uprn 100091206033): solar PV alone earns 31.3 SAP points (likely oversized array)
- property **719829** (uprn 100091206052): solar PV alone earns 31.6 SAP points (likely oversized array)
- property **720039** (uprn 100061741993): solar PV alone earns 32.6 SAP points (likely oversized array)
- property **720104** (uprn 100061764078): solar PV alone earns 29.9 SAP points (likely oversized array)
- property **721044** (uprn 100061764081): solar PV alone earns 33.9 SAP points (likely oversized array)
- property **721222** (uprn 100062480566): solar PV alone earns 27.0 SAP points (likely oversized array)
- property **722986** (uprn 100061742571): solar PV alone earns 29.8 SAP points (likely oversized array)
- property **723096** (uprn 100061763625): solar PV alone earns 34.5 SAP points (likely oversized array)
- property **723516** (uprn 100061741124): solar PV alone earns 31.0 SAP points (likely oversized array)
- property **723528** (uprn 100061742003): solar PV alone earns 30.9 SAP points (likely oversized array)
- property **724609** (uprn 100061742008): solar PV alone earns 27.0 SAP points (likely oversized array)
- property **725224** (uprn 100062480573): solar PV alone earns 27.6 SAP points (likely oversized array)
- property **725266** (uprn 10034506076): solar PV alone earns 38.5 SAP points (likely oversized array)
- property **725603** (uprn 100061761161): solar PV alone earns 35.6 SAP points (likely oversized array)
- property **727422** (uprn 200001645537): solar PV alone earns 29.4 SAP points (likely oversized array)
- property **727688** (uprn 100061761162): solar PV alone earns 28.8 SAP points (likely oversized array)
- property **727699** (uprn 200004784746): solar PV alone earns 27.3 SAP points (likely oversized array)
- property **727968** (uprn 100061740165): solar PV alone earns 34.5 SAP points (likely oversized array)
- property **728344** (uprn 100061764582): solar PV alone earns 26.9 SAP points (likely oversized array)
- property **729028** (uprn 100061735428): solar PV alone earns 32.0 SAP points (likely oversized array)
- property **729329** (uprn 100061749297): solar PV alone earns 30.2 SAP points (likely oversized array)
- property **729415** (uprn 100091206037): solar PV alone earns 31.5 SAP points (likely oversized array)
- property **731052** (uprn 100021958934): solar PV alone earns 29.3 SAP points (likely oversized array)
- property **731481** (uprn 100021935669): solar PV alone earns 25.1 SAP points (likely oversized array)
- property **731812** (uprn 200001645541): solar PV alone earns 32.1 SAP points (likely oversized array)
- property **731994** (uprn 10023371767): solar PV alone earns 25.3 SAP points (likely oversized array)
- property **732041** (uprn 100061761165): solar PV alone earns 30.1 SAP points (likely oversized array)
- property **732050** (uprn 100061764295): solar PV alone earns 30.5 SAP points (likely oversized array)
- property **732860** (uprn 100061733678): solar PV alone earns 32.7 SAP points (likely oversized array)
- property **733394** (uprn 100061748753): solar PV alone earns 25.1 SAP points (likely oversized array)
- property **739556** (uprn 100061754547): solar PV alone earns 31.3 SAP points (likely oversized array)
- property **739814** (uprn 200003724253): solar PV alone earns 31.6 SAP points (likely oversized array)
- property **739998** (uprn 100090224018): solar PV alone earns 25.9 SAP points (likely oversized array)
- property **740214** (uprn 100061762820): solar PV alone earns 30.4 SAP points (likely oversized array)
- … and 1 more (see CSV)
- property **742131** (uprn 148013838): effective 62 vs lodged 47 (Δ+15, reason=pre_sap10)
- property **742132** (uprn 148013839): effective 62 vs lodged 47 (Δ+15, reason=pre_sap10)
- property **742204** (uprn 100081142998): effective 69 vs lodged 54 (Δ+15, reason=pre_sap10)
- property **742206** (uprn 100081143000): effective 69 vs lodged 54 (Δ+15, reason=pre_sap10)
- property **742208** (uprn 100081143002): effective 59 vs lodged 44 (Δ+15, reason=pre_sap10)
- property **742216** (uprn 100081143009): effective 69 vs lodged 54 (Δ+15, reason=pre_sap10)
- property **742355** (uprn 100022982934): effective 63 vs lodged 47 (Δ+16, reason=pre_sap10)
- property **742394** (uprn 100022909582): effective 71 vs lodged 86 (Δ-15, reason=pre_sap10)
- property **742395** (uprn 100022909583): effective 72 vs lodged 87 (Δ-15, reason=pre_sap10)
## low-solar-bill-savings (MEDIUM) — 83
## negative-bill-savings (LOW) — 31
- property **710178** (uprn 100020465019): solar PV bill saving only £49/yr — check self-consumption / SEG export
- property **711663** (uprn 100020481859): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **712943** (uprn 100061741910): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **713299** (uprn 100060331540): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **713607** (uprn 100090108855): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **713631** (uprn 10002470912): solar PV bill saving only £49/yr — check self-consumption / SEG export
- property **713743** (uprn 100060359906): solar PV bill saving only £36/yr — check self-consumption / SEG export
- property **715182** (uprn 100060726237): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **715701** (uprn 100021001715): solar PV bill saving only £50/yr — check self-consumption / SEG export
- property **716152** (uprn 100090108859): solar PV bill saving only £43/yr — check self-consumption / SEG export
- property **716268** (uprn 100061763778): solar PV bill saving only £36/yr — check self-consumption / SEG export
- property **716289** (uprn 200003688201): solar PV bill saving only £43/yr — check self-consumption / SEG export
- property **716659** (uprn 100061747951): solar PV bill saving only £41/yr — check self-consumption / SEG export
- property **716693** (uprn 100061733911): solar PV bill saving only £39/yr — check self-consumption / SEG export
- property **717392** (uprn 100020450723): solar PV bill saving only £45/yr — check self-consumption / SEG export
- property **717661** (uprn 6176751): solar PV bill saving only £42/yr — check self-consumption / SEG export
- property **718073** (uprn 100021017285): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **718298** (uprn 100061741870): solar PV bill saving only £43/yr — check self-consumption / SEG export
- property **718567** (uprn 100091206050): solar PV bill saving only £50/yr — check self-consumption / SEG export
- property **719647** (uprn 100020590930): solar PV bill saving only £49/yr — check self-consumption / SEG export
- property **720335** (uprn 100020594071): solar PV bill saving only £36/yr — check self-consumption / SEG export
- property **720677** (uprn 100020969500): solar PV bill saving only £30/yr — check self-consumption / SEG export
- property **721018** (uprn 202140958): solar PV bill saving only £44/yr — check self-consumption / SEG export
- property **721529** (uprn 100060696301): solar PV bill saving only £43/yr — check self-consumption / SEG export
- property **721664** (uprn 100061765249): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **721895** (uprn 100060726253): solar PV bill saving only £48/yr — check self-consumption / SEG export
- property **722155** (uprn 100061758903): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **722390** (uprn 100020944918): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **722910** (uprn 10009428749): solar PV bill saving only £41/yr — check self-consumption / SEG export
- property **723298** (uprn 202140961): solar PV bill saving only £45/yr — check self-consumption / SEG export
- property **723578** (uprn 100020986231): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **723748** (uprn 100061757556): solar PV bill saving only £48/yr — check self-consumption / SEG export
- property **723965** (uprn 100061761860): solar PV bill saving only £50/yr — check self-consumption / SEG export
- property **724311** (uprn 100061765331): solar PV bill saving only £30/yr — check self-consumption / SEG export
- property **724331** (uprn 100022008224): solar PV bill saving only £22/yr — check self-consumption / SEG export
- property **724850** (uprn 100060719545): solar PV bill saving only £50/yr — check self-consumption / SEG export
- property **725287** (uprn 100062187008): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **725585** (uprn 100061752475): solar PV bill saving only £44/yr — check self-consumption / SEG export
- property **725807** (uprn 100020996065): solar PV bill saving only £40/yr — check self-consumption / SEG export
- property **725969** (uprn 202141567): solar PV bill saving only £31/yr — check self-consumption / SEG export
- property **726419** (uprn 100061809723): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **726507** (uprn 100061752706): solar PV bill saving only £48/yr — check self-consumption / SEG export
- property **726627** (uprn 100061152652): solar PV bill saving only £42/yr — check self-consumption / SEG export
- property **726735** (uprn 100061809725): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **726998** (uprn 100061809727): solar PV bill saving only £46/yr — check self-consumption / SEG export
- property **727114** (uprn 100061809728): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **727143** (uprn 202141571): solar PV bill saving only £45/yr — check self-consumption / SEG export
- property **727820** (uprn 100061809729): solar PV bill saving only £47/yr — check self-consumption / SEG export
- property **727994** (uprn 202141572): solar PV bill saving only £45/yr — check self-consumption / SEG export
- property **728027** (uprn 10090265602): solar PV bill saving only £45/yr — check self-consumption / SEG export
- … and 33 more (see CSV)
## zero-works-post-differs (MEDIUM) — 5624
- property **709772** (uprn 10093116528): £0 works but post SAP 80.3 != effective 79.0
- property **709773** (uprn 10093116543): £0 works but post SAP 78.5 != effective 77.0
- property **709774** (uprn 10093116529): £0 works but post SAP 76.8 != effective 75.0
- property **709777** (uprn 10094601392): £0 works but post SAP 77.2 != effective 74.0
- property **709778** (uprn 10023444324): £0 works but post SAP 76.9 != effective 75.0
- property **709779** (uprn 10092970673): £0 works but post SAP 70.9 != effective 61.0
- property **709780** (uprn 10094601287): £0 works but post SAP 77.7 != effective 75.0
- property **709783** (uprn 10094601162): £0 works but post SAP 78.1 != effective 74.0
- property **709784** (uprn 10090844948): £0 works but post SAP 76.4 != effective 73.0
- property **709786** (uprn 10093114053): £0 works but post SAP 81.3 != effective 76.0
- property **709787** (uprn 10091568921): £0 works but post SAP 79.4 != effective 77.0
- property **709788** (uprn 10093718424): £0 works but post SAP 80.0 != effective 78.0
- property **709790** (uprn 10023443426): £0 works but post SAP 74.2 != effective 76.0
- property **709791** (uprn 10093412452): £0 works but post SAP 80.2 != effective 79.0
- property **709792** (uprn 6199384): £0 works but post SAP 80.5 != effective 78.0
- property **709793** (uprn 10014314798): £0 works but post SAP 73.8 != effective 72.0
- property **709794** (uprn 10094601294): £0 works but post SAP 78.1 != effective 76.0
- property **709795** (uprn 10090343335): £0 works but post SAP 84.0 != effective 82.0
- property **709796** (uprn 10093115480): £0 works but post SAP 78.8 != effective 77.0
- property **709798** (uprn 10094601226): £0 works but post SAP 77.3 != effective 75.0
- property **709800** (uprn 6701369): £0 works but post SAP 82.5 != effective 78.0
- property **709801** (uprn 202211152): £0 works but post SAP 81.8 != effective 79.0
- property **709803** (uprn 10093394010): £0 works but post SAP 79.9 != effective 78.0
- property **709806** (uprn 10090341811): £0 works but post SAP 80.2 != effective 78.0
- property **709808** (uprn 10093117227): £0 works but post SAP 77.6 != effective 76.0
- property **709809** (uprn 10023444170): £0 works but post SAP 80.3 != effective 78.0
- property **709810** (uprn 10096028301): £0 works but post SAP 78.0 != effective 85.0
- property **709813** (uprn 10094601280): £0 works but post SAP 77.9 != effective 75.0
- property **709814** (uprn 10093386418): £0 works but post SAP 78.8 != effective 76.0
- property **709817** (uprn 10094895444): £0 works but post SAP 79.6 != effective 77.0
- property **709818** (uprn 10092973960): £0 works but post SAP 77.6 != effective 74.0
- property **709819** (uprn 10012028763): £0 works but post SAP 83.3 != effective 82.0
- property **709820** (uprn 10093049867): £0 works but post SAP 78.7 != effective 75.0
- property **709821** (uprn 10093116336): £0 works but post SAP 79.9 != effective 78.0
- property **709823** (uprn 10093116334): £0 works but post SAP 79.0 != effective 78.0
- property **709824** (uprn 44042992): £0 works but post SAP 79.9 != effective 79.0
- property **709825** (uprn 10014314853): £0 works but post SAP 72.0 != effective 70.0
- property **709828** (uprn 10091636116): £0 works but post SAP 75.8 != effective 71.0
- property **709829** (uprn 10094601381): £0 works but post SAP 78.4 != effective 74.0
- property **709830** (uprn 10093049853): £0 works but post SAP 81.5 != effective 78.0
- property **709831** (uprn 10093390790): £0 works but post SAP 74.9 != effective 72.0
- property **709832** (uprn 10093116330): £0 works but post SAP 80.1 != effective 79.0
- property **709833** (uprn 10093116326): £0 works but post SAP 80.1 != effective 79.0
- property **709834** (uprn 10094601351): £0 works but post SAP 79.0 != effective 76.0
- property **709835** (uprn 10090317693): £0 works but post SAP 77.5 != effective 76.0
- property **709836** (uprn 10090034872): £0 works but post SAP 81.4 != effective 79.0
- property **709837** (uprn 10093115985): £0 works but post SAP 79.5 != effective 77.0
- property **709842** (uprn 202211170): £0 works but post SAP 82.1 != effective 79.0
- property **709845** (uprn 6701311): £0 works but post SAP 81.4 != effective 78.0
- property **709846** (uprn 10096399556): £0 works but post SAP 79.7 != effective 93.0
- … and 5574 more (see CSV)
## effective-lodged-divergence (LOW) — 1527
- property **709779** (uprn 10092970673): effective 61 vs lodged 86 (Δ-25, reason=pre_sap10)
- property **709802** (uprn 100020665611): effective 52 vs lodged 37 (Δ+15, reason=pre_sap10)
- property **709804** (uprn 10093388044): effective 33 vs lodged 93 (Δ-60, reason=pre_sap10)
- property **709815** (uprn 100090108846): effective 57 vs lodged 79 (Δ-22, reason=pre_sap10)
- property **709828** (uprn 10091636116): effective 71 vs lodged 88 (Δ-17, reason=pre_sap10)
- property **709860** (uprn 100061086424): effective 60 vs lodged 83 (Δ-23, reason=pre_sap10)
- property **709863** (uprn 10090342180): effective 39 vs lodged 78 (Δ-39, reason=pre_sap10)
- property **709874** (uprn 10093388053): effective 35 vs lodged 94 (Δ-59, reason=pre_sap10)
- property **709892** (uprn 10090343767): effective 75 vs lodged 91 (Δ-16, reason=pre_sap10)
- property **709945** (uprn 10090342181): effective 42 vs lodged 81 (Δ-39, reason=pre_sap10)
- property **709993** (uprn 15043874): effective 68 vs lodged 49 (Δ+19, reason=pre_sap10)
- property **710003** (uprn 10091636410): effective 71 vs lodged 86 (Δ-15, reason=pre_sap10)
- property **710009** (uprn 100022895379): effective 62 vs lodged 80 (Δ-18, reason=pre_sap10)
- property **710019** (uprn 10090342182): effective 44 vs lodged 80 (Δ-36, reason=pre_sap10)
- property **710025** (uprn 10093388055): effective 55 vs lodged 93 (Δ-38, reason=pre_sap10)
- property **710037** (uprn 100090108857): effective 56 vs lodged 86 (Δ-30, reason=pre_sap10)
- property **710091** (uprn 100061086427): effective 60 vs lodged 83 (Δ-23, reason=pre_sap10)
- property **710114** (uprn 10096026315): effective 74 vs lodged 89 (Δ-15, reason=pre_sap10)
- property **710134** (uprn 10096026271): effective 73 vs lodged 88 (Δ-15, reason=pre_sap10)
- property **710139** (uprn 10090342183): effective 41 vs lodged 77 (Δ-36, reason=pre_sap10)
- property **710144** (uprn 10014314832): effective 63 vs lodged 83 (Δ-20, reason=pre_sap10)
- property **710148** (uprn 10093388056): effective 57 vs lodged 94 (Δ-37, reason=pre_sap10)
- property **710191** (uprn 10090342184): effective 49 vs lodged 79 (Δ-30, reason=pre_sap10)
- property **710198** (uprn 10012138502): effective 65 vs lodged 85 (Δ-20, reason=pre_sap10)
- property **710199** (uprn 10093388057): effective 38 vs lodged 95 (Δ-57, reason=pre_sap10)
- property **710202** (uprn 10090342864): effective 68 vs lodged 84 (Δ-16, reason=pre_sap10)
- property **710244** (uprn 10010249676): effective 74 vs lodged 90 (Δ-16, reason=pre_sap10)
- property **710246** (uprn 100061086430): effective 59 vs lodged 83 (Δ-24, reason=pre_sap10)
- property **710250** (uprn 10090342185): effective 62 vs lodged 81 (Δ-19, reason=pre_sap10)
- property **710260** (uprn 10093388058): effective 47 vs lodged 95 (Δ-48, reason=pre_sap10)
- property **710261** (uprn 10090341825): effective 75 vs lodged 91 (Δ-16, reason=pre_sap10)
- property **710300** (uprn 10090341826): effective 75 vs lodged 91 (Δ-16, reason=pre_sap10)
- property **710342** (uprn 10090342187): effective 37 vs lodged 77 (Δ-40, reason=pre_sap10)
- property **710348** (uprn 10090341827): effective 76 vs lodged 91 (Δ-15, reason=pre_sap10)
- property **710429** (uprn 10093388045): effective 49 vs lodged 93 (Δ-44, reason=pre_sap10)
- property **710449** (uprn 100020993501): effective 56 vs lodged 5 (Δ+51, reason=pre_sap10)
- property **710491** (uprn 10014314835): effective 69 vs lodged 84 (Δ-15, reason=pre_sap10)
- property **710536** (uprn 100062482536): effective 38 vs lodged 53 (Δ-15, reason=pre_sap10)
- property **710640** (uprn 10014316004): effective 71 vs lodged 88 (Δ-17, reason=pre_sap10)
- property **710658** (uprn 10014316005): effective 70 vs lodged 88 (Δ-18, reason=pre_sap10)
- property **710659** (uprn 22061763): effective 50 vs lodged 70 (Δ-20, reason=pre_sap10)
- property **710664** (uprn 10096026322): effective 74 vs lodged 89 (Δ-15, reason=pre_sap10)
- property **710672** (uprn 200003378407): effective 48 vs lodged 28 (Δ+20, reason=pre_sap10)
- property **710683** (uprn 10014316006): effective 70 vs lodged 88 (Δ-18, reason=pre_sap10)
- property **710704** (uprn 10014316007): effective 71 vs lodged 88 (Δ-17, reason=pre_sap10)
- property **710745** (uprn 10093386244): effective 50 vs lodged 83 (Δ-33, reason=pre_sap10)
- property **710752** (uprn 10093388046): effective 47 vs lodged 94 (Δ-47, reason=pre_sap10)
- property **710779** (uprn 10091636118): effective 71 vs lodged 88 (Δ-17, reason=pre_sap10)
- property **710814** (uprn 10014316008): effective 71 vs lodged 88 (Δ-17, reason=pre_sap10)
- property **710837** (uprn 10014316009): effective 71 vs lodged 88 (Δ-17, reason=pre_sap10)
- … and 1477 more (see CSV)
## negative-bill-savings (LOW) — 100
- property **712847** (uprn 100061737192): energy_bill_savings £-30/yr on £16110 of works
- property **713453** (uprn 100061739869): energy_bill_savings £-68/yr on £14533 of works
- property **713721** (uprn 100061753373): energy_bill_savings £-18/yr on £14554 of works
- property **713743** (uprn 100060359906): energy_bill_savings £-98/yr on £18823 of works
- property **713791** (uprn 10013528635): energy_bill_savings £-130/yr on £1029 of works
- property **713970** (uprn 10013528640): energy_bill_savings £-130/yr on £1029 of works
- property **714001** (uprn 10013528641): energy_bill_savings £-130/yr on £1029 of works
- property **714038** (uprn 10013528642): energy_bill_savings £-130/yr on £1029 of works
- property **714373** (uprn 100062185281): energy_bill_savings £-113/yr on £14800 of works
- property **714420** (uprn 10010242243): energy_bill_savings £-162/yr on £1029 of works
- property **715227** (uprn 100061753375): energy_bill_savings £-18/yr on £14554 of works
- property **715561** (uprn 100061739874): energy_bill_savings £-69/yr on £14533 of works
- property **715999** (uprn 100061737204): energy_bill_savings £-13/yr on £14533 of works
- property **716169** (uprn 100061747915): energy_bill_savings £-53/yr on £14533 of works
- property **716251** (uprn 100061753377): energy_bill_savings £-18/yr on £14554 of works
- property **716548** (uprn 100061765632): energy_bill_savings £-70/yr on £14533 of works
- property **716811** (uprn 22106963): energy_bill_savings £-3/yr on £4785 of works
- property **717209** (uprn 100061753379): energy_bill_savings £-20/yr on £14554 of works
- property **717675** (uprn 6176752): energy_bill_savings £-75/yr on £15067 of works
- property **717998** (uprn 100061749651): energy_bill_savings £-7/yr on £14533 of works
- property **719002** (uprn 10002476550): energy_bill_savings £-101/yr on £14533 of works
- property **719091** (uprn 100061753365): energy_bill_savings £-46/yr on £14533 of works
- property **719449** (uprn 100061753383): energy_bill_savings £-18/yr on £14554 of works
- property **719680** (uprn 100061741246): energy_bill_savings £-34/yr on £17072 of works
- property **719811** (uprn 100060327562): energy_bill_savings £-92/yr on £14533 of works
- property **720349** (uprn 100021812910): energy_bill_savings £-122/yr on £1029 of works
- property **720364** (uprn 100061741682): energy_bill_savings £-51/yr on £15070 of works
- property **720800** (uprn 100061753387): energy_bill_savings £-20/yr on £14554 of works
- property **720889** (uprn 10023224588): energy_bill_savings £-172/yr on £1029 of works
- property **720989** (uprn 100061764553): energy_bill_savings £-143/yr on £14533 of works
- property **721034** (uprn 100061758484): energy_bill_savings £-145/yr on £15105 of works
- property **721070** (uprn 100061749663): energy_bill_savings £-69/yr on £14800 of works
- property **722402** (uprn 100061737194): energy_bill_savings £-73/yr on £14266 of works
- property **722448** (uprn 100061739862): energy_bill_savings £-68/yr on £14533 of works
- property **722732** (uprn 100061750203): energy_bill_savings £-155/yr on £16445 of works
- property **722808** (uprn 100062186150): energy_bill_savings £-61/yr on £14533 of works
- property **723367** (uprn 100061753394): energy_bill_savings £-56/yr on £14533 of works
- property **723503** (uprn 10010242632): energy_bill_savings £-112/yr on £1029 of works
- property **723540** (uprn 100061743541): energy_bill_savings £-35/yr on £14533 of works
- property **723771** (uprn 200001645519): energy_bill_savings £-58/yr on £14533 of works
- property **723782** (uprn 100061743542): energy_bill_savings £-30/yr on £17032 of works
- property **725039** (uprn 100061748331): energy_bill_savings £-4/yr on £14800 of works
- property **725350** (uprn 100061743145): energy_bill_savings £-189/yr on £15067 of works
- property **725715** (uprn 100061736694): energy_bill_savings £-42/yr on £14533 of works
- property **725731** (uprn 100061763962): energy_bill_savings £-71/yr on £14533 of works
- property **725988** (uprn 100061749671): energy_bill_savings £-13/yr on £14533 of works
- property **726184** (uprn 100061752891): energy_bill_savings £-66/yr on £14533 of works
- property **726268** (uprn 100061741268): energy_bill_savings £-76/yr on £14266 of works
- property **726271** (uprn 100061741692): energy_bill_savings £-63/yr on £14533 of works
- property **726302** (uprn 202141568): energy_bill_savings £-73/yr on £15721 of works
- … and 50 more (see CSV)
## unusually-high-post-sap (LOW) — 21
- property **714511** (uprn 100061761168): post SAP 100.0 (near band A) — confirm not over-credited
- property **716734** (uprn 10002469029): post SAP 100.0 (near band A) — confirm not over-credited
- property **716740** (uprn 100061753334): post SAP 100.0 (near band A) — confirm not over-credited
- property **717201** (uprn 100091206047): post SAP 100.0 (near band A) — confirm not over-credited
- property **718890** (uprn 100062344151): post SAP 100.0 (near band A) — confirm not over-credited
- property **719080** (uprn 100091206033): post SAP 100.0 (near band A) — confirm not over-credited
- property **719829** (uprn 100091206052): post SAP 100.0 (near band A) — confirm not over-credited
- property **721222** (uprn 100062480566): post SAP 98.6 (near band A) — confirm not over-credited
- property **723516** (uprn 100061741124): post SAP 100.0 (near band A) — confirm not over-credited
- property **725224** (uprn 100062480573): post SAP 95.3 (near band A) — confirm not over-credited
- property **725440** (uprn 100061746447): post SAP 100.0 (near band A) — confirm not over-credited
- property **725627** (uprn 10008885879): post SAP 99.6 (near band A) — confirm not over-credited
- property **726993** (uprn 100061757571): post SAP 100.0 (near band A) — confirm not over-credited
- property **727688** (uprn 100061761162): post SAP 97.6 (near band A) — confirm not over-credited
- property **727699** (uprn 200004784746): post SAP 100.0 (near band A) — confirm not over-credited
- property **729329** (uprn 100061749297): post SAP 99.2 (near band A) — confirm not over-credited
- property **729415** (uprn 100091206037): post SAP 100.0 (near band A) — confirm not over-credited
- property **732041** (uprn 100061761165): post SAP 97.9 (near band A) — confirm not over-credited
- property **732050** (uprn 100061764295): post SAP 98.1 (near band A) — confirm not over-credited
- property **740214** (uprn 100061762820): post SAP 99.4 (near band A) — confirm not over-credited
- property **740234** (uprn 100061761814): post SAP 100.0 (near band A) — confirm not over-credited
- property **742065** (uprn 10010206038): energy_bill_savings £-454/yr on £1043 of works
- property **742066** (uprn 10010206039): energy_bill_savings £-417/yr on £7876 of works
- property **742068** (uprn 10010206041): energy_bill_savings £-442/yr on £8510 of works
- property **742145** (uprn 5300022461): energy_bill_savings £-799/yr on £3196 of works
- property **742146** (uprn 5300022470): energy_bill_savings £-799/yr on £3196 of works
- property **742147** (uprn 5300022471): energy_bill_savings £-799/yr on £3196 of works
- property **742148** (uprn 5300022472): energy_bill_savings £-685/yr on £3270 of works
- property **742149** (uprn 5300022473): energy_bill_savings £-799/yr on £3196 of works
- property **742150** (uprn 5300022474): energy_bill_savings £-799/yr on £3196 of works
- property **742151** (uprn 5300022475): energy_bill_savings £-799/yr on £3196 of works
- property **742153** (uprn 5300022477): energy_bill_savings £-746/yr on £3196 of works
- property **742155** (uprn 5300022479): energy_bill_savings £-799/yr on £3196 of works
- property **742156** (uprn 5300022462): energy_bill_savings £-799/yr on £3196 of works
- property **742157** (uprn 5300022480): energy_bill_savings £-517/yr on £11607 of works
- property **742158** (uprn 5300022481): energy_bill_savings £-799/yr on £3196 of works
- property **742159** (uprn 5300022482): energy_bill_savings £-799/yr on £3196 of works
- property **742160** (uprn 5300022483): energy_bill_savings £-799/yr on £3196 of works
- property **742161** (uprn 5300022484): energy_bill_savings £-799/yr on £3196 of works
- property **742162** (uprn 5300022485): energy_bill_savings £-799/yr on £3196 of works
- property **742163** (uprn 5300022486): energy_bill_savings £-799/yr on £3196 of works
- property **742164** (uprn 5300022487): energy_bill_savings £-799/yr on £3196 of works
- property **742166** (uprn 5300022489): energy_bill_savings £-799/yr on £3196 of works
- property **742167** (uprn 5300022463): energy_bill_savings £-799/yr on £3196 of works
- property **742168** (uprn 5300022490): energy_bill_savings £-799/yr on £3196 of works
- property **742169** (uprn 5300022491): energy_bill_savings £-799/yr on £3196 of works
- property **742170** (uprn 5300022492): energy_bill_savings £-799/yr on £3196 of works
- property **742171** (uprn 5300022464): energy_bill_savings £-799/yr on £3196 of works
- property **742172** (uprn 5300022465): energy_bill_savings £-799/yr on £3196 of works
- property **742174** (uprn 5300022467): energy_bill_savings £-922/yr on £1057 of works
- property **742176** (uprn 5300022469): energy_bill_savings £-799/yr on £3196 of works
- property **742265** (uprn 10033526327): energy_bill_savings £-896/yr on £10682 of works

View file

@ -23,9 +23,15 @@ Writes ``neighbour_divergence.md`` + ``neighbour_divergence.csv`` and prints a
summary. Read-only: never writes to the DB.
A cohort is the set of a portfolio's properties sharing (postcode, property_type,
built_form). Within a cohort of >= 2, any member whose effective SAP is >=
``--min-gap`` points from the cohort median is flagged. Floor area is reported,
not keyed on, so the reviewer can discount a genuinely bigger/smaller neighbour;
built_form, main-heating fuel class). Within a cohort of >= 2, any member whose
effective SAP is >= ``--min-gap`` points from the cohort median is flagged.
Heating **fuel** is part of the key because electricity scores materially lower
in SAP than mains gas for identical fabric mixing fuels in one cohort produces
cross-fuel false outliers (an electric dwelling flagged only for being electric
among gas neighbours). Keying on fuel ensures like-vs-like, so every flagged
divergence is a same-fuel one worth investigating (on portfolio 814 this refined
20 raw divergences to 17 same-fuel comparisons). Floor area is reported, not
keyed on, so the reviewer can discount a genuinely bigger/smaller neighbour;
promoting an area guard into the cohort key is a clean future change once the
false-positive rate is measured on a real portfolio (skill Phase 6).
"""
@ -67,6 +73,7 @@ class Neighbour:
floor_area_m2: Optional[float]
effective_sap: Optional[float]
effective_band: Optional[str]
main_fuel_type: Optional[int] # gov-API main-heating fuel code (None if unmapped)
@dataclass(frozen=True)
@ -84,16 +91,24 @@ _QUERY = text(
"""
SELECT p.id, p.uprn, p.postcode,
ep.property_type, ep.built_form, ep.total_floor_area_m2,
pbp.effective_sap_score, pbp.effective_epc_band
pbp.effective_sap_score, pbp.effective_epc_band,
mh.main_fuel_type
FROM property p
JOIN property_baseline_performance pbp ON pbp.property_id = p.id
LEFT JOIN LATERAL (
SELECT property_type, built_form, total_floor_area_m2
SELECT id, property_type, built_form, total_floor_area_m2
FROM epc_property e
WHERE e.property_id = p.id
ORDER BY e.id DESC
LIMIT 1
) ep ON TRUE
LEFT JOIN LATERAL (
SELECT main_fuel_type
FROM epc_main_heating_detail m
WHERE m.epc_property_id = ep.id
ORDER BY m.id
LIMIT 1
) mh ON TRUE
WHERE p.portfolio_id = :portfolio_id
ORDER BY p.id
"""
@ -117,18 +132,58 @@ def _load(portfolio_id: int) -> list[Neighbour]:
floor_area_m2=m["total_floor_area_m2"],
effective_sap=m["effective_sap_score"],
effective_band=m["effective_epc_band"],
main_fuel_type=_coerce_fuel(m["main_fuel_type"]),
)
)
return out
def _coerce_fuel(raw: object) -> Optional[int]:
"""The main-heating fuel code as an int, or None. ``main_fuel_type`` is a
JSONB column (int or str depending on the source mapper), so coerce defensively
a non-numeric value groups as "unmapped" rather than raising."""
if raw is None:
return None
try:
return int(raw) # type: ignore[arg-type]
except (TypeError, ValueError):
return None
# Electricity main-heating fuel codes (gov-API / SAP Table 12): standard tariff
# (30), the off-peak tariffs (31-40), and code 29, which real electric certs in
# the corpus lodge for "room heaters, electric". Collapsing these to one class
# keeps all-electric dwellings comparable to each other; every OTHER fuel keeps
# its raw code as its own bucket (we don't guess a taxonomy for gas/oil/community).
_ELECTRICITY_FUEL_CODES: frozenset[int] = frozenset({29, 30, 31, 32, 33, 34, 35, 38, 40})
def _fuel_class(fuel: Optional[int]) -> str:
"""A coarse main-heating-fuel label for the cohort key. Electricity variants
collapse to one class; any other code is its own bucket; None is "unmapped"."""
if fuel is None:
return "fuel?"
if fuel in _ELECTRICITY_FUEL_CODES:
return "electric"
return f"fuel{fuel}"
def _cohort_key(n: Neighbour) -> Optional[str]:
"""A stable cohort label, or None when the neighbour can't be placed (no
postcode or no property type it has no comparable peers to diverge from)."""
postcode or no property type it has no comparable peers to diverge from).
The main-heating **fuel** is part of the key: electricity scores materially
lower in SAP than mains gas for identical fabric, so mixing fuels in a cohort
produces cross-fuel false outliers. Keying on fuel keeps like compared with
like, so a flagged divergence is a genuine same-fuel anomaly, not just an
electric dwelling sitting among gas neighbours."""
if not n.postcode or not n.property_type:
return None
form = n.built_form or "?"
return f"{n.postcode.strip().upper()} · {n.property_type} · {form}"
return (
f"{n.postcode.strip().upper()} · {n.property_type} · {form} "
f"· {_fuel_class(n.main_fuel_type)}"
)
def find_divergences(

View file

@ -11,6 +11,7 @@ def _n(
property_type: str = "Flat",
built_form: str = "Mid-Terrace",
floor_area_m2: float = 60.0,
main_fuel_type: Optional[int] = 26, # default: mains gas
) -> Neighbour:
return Neighbour(
property_id=property_id,
@ -21,6 +22,7 @@ def _n(
floor_area_m2=floor_area_m2,
effective_sap=effective_sap,
effective_band=None,
main_fuel_type=main_fuel_type,
)
@ -74,3 +76,34 @@ class TestFindDivergences:
# Assert
assert result == []
def test_electric_and_gas_are_separate_cohorts(self) -> None:
# Arrange — same postcode/type/form, but an electric dwelling (fuel 29)
# scores a band below its gas neighbours (fuel 26). Electricity is
# inherently lower-SAP, so this is expected stock, not a divergence.
mixed = [
_n(1, effective_sap=70.0, main_fuel_type=26), # gas
_n(2, effective_sap=72.0, main_fuel_type=26), # gas
_n(3, effective_sap=52.0, main_fuel_type=29), # electric — its own cohort
]
# Act
result = find_divergences(mixed, min_gap=12.0)
# Assert — the electric singleton has no same-fuel peers, so nothing fires.
assert result == []
def test_electric_outlier_still_flagged_within_its_own_fuel_cohort(self) -> None:
# Arrange — three electric dwellings; one genuinely diverges. Keying on
# fuel must not blind the detector to real within-fuel outliers.
electric = [
_n(1, effective_sap=55.0, main_fuel_type=29),
_n(2, effective_sap=57.0, main_fuel_type=30), # 30 also electric-class
_n(3, effective_sap=30.0, main_fuel_type=29), # Δ-25 vs median
]
# Act
result = find_divergences(electric, min_gap=12.0)
# Assert
assert [d.property_id for d in result] == [3]