Model/etl/customers/l_and_g/risk_matrix.py
2025-06-05 17:54:55 +01:00

185 lines
6.1 KiB
Python

from itertools import product
from recommendations.recommendation_utils import estimate_external_wall_area, estimate_windows
import numpy as np
import pandas as pd
def app():
# Given a combination of variables, this code attempts to break down the costs of works to achieve upgrade
# targets
upgrade_path = [
"wall_insulation", "roof_insulation", "ventilation", "windows", "low_energy_lighting",
"heating", "solar"
]
pricing_matrix = {
"Cavity wall insulation": 14.5,
"ventilation": 350,
"Room Roof Insulation": 210,
"Loft insulation": 15,
"Internal wall insulation": 131,
"External wall insulation": 298.35,
"Solid wall insulation": 131,
"LEDs": 35, # per light
"Flat Roof Insulation": 195,
"Double Glazing": 1140,
"secondary_glazing": 970,
"5kw ASHP feeding heating & Hot water (dual tariff)": 14738,
"11.2kw ASHP feeding heating & Hot water (dual tariff)": 16541,
"3 kWp Solar PV": 4552.32,
"4 kWp Solar PV": 4892.8,
"4.3 kWp Solar PV": 4961.44,
"4.8 kWp Solar PV": 5414,
'5 kWp Solar PV': 5509.71,
'5.5 kWp Solar PV': 5631.92,
"HHRSH (dual tariff)": 1000, # per heater
"Suspended floor insulation": 75
}
dwelling_types = [
"Semi Detached House",
"Detached house",
"Mid Terrace house",
"Mid Floor Flat",
"Top Floor Flat",
"Ground Floor Flat"
]
num_floors_map = {
"Semi-detached house": 2,
"Detached house": 2,
"Mid Terrace house": 2,
"Mid Floor Flat": 1,
"Top Floor Flat": 1,
"Ground Floor Flat": 1
}
built_form_map = {
"Semi-detached house": "Semi-Detached",
"Detached house": "Detached",
"Mid Terrace house": "Mid Terrace",
"Mid Floor Flat": "Semi-Detached",
"Top Floor Flat": "Semi-Detached",
"Ground Floor Flat": "Semi-Detached"
}
lighting_count = {
"Semi-detached house": 15,
"Detached house": 19,
"Mid Terrace house": 12,
"Mid Floor Flat": 10,
"Top Floor Flat": 10,
"Ground Floor Flat": 10
}
contingency = 0.26
epr_data = pd.read_excel(
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/L&G/Risk Matrix/EPR Data V2.xlsx", header=1
)
epr_data["Measure added"].value_counts()
epr_data["row_id"] = epr_data.index
# We need to calculate the costs
cost_data = []
for _, row in epr_data.iterrows():
epc = row["EPC"][0]
sap = int(row["EPC"][1:])
n_floors = num_floors_map[row["Property Type"]]
bf = built_form_map[row["Property Type"]]
pt = "House" if "flat" not in row["Property Type"].lower() else "Flat"
# Model the home as a box
ground_floor_area = row["area"] / n_floors
perimeter = np.sqrt(ground_floor_area) * 4
# This is the amount of insulation required
external_wall_area = estimate_external_wall_area(
num_floors=n_floors,
floor_height=2.5,
perimeter=perimeter,
built_form=bf
)
n_rooms = np.floor(row["area"] / 15)
n_windows = estimate_windows(
property_type=pt,
built_form=bf,
construction_age_band="",
floor_area=row["area"],
number_habitable_rooms=n_rooms
)
cost_upper_bound = None
if pd.isnull(row["Measure added"]):
unit_cost = None
else:
measure = row["Measure added"]
unit_cost = pricing_matrix[measure]
if pd.isnull(row["Measure added"]):
cost = None
elif row["Measure added"] == "Loft insulation":
cost = unit_cost * ground_floor_area
elif row["Measure added"] in ["Cavity wall insulation", "Internal wall insulation"]:
cost = unit_cost * external_wall_area + pricing_matrix["ventilation"] * 3
elif row["Measure added"] == "Solid wall insulation":
cost = unit_cost * external_wall_area + pricing_matrix["ventilation"] * 3
cost_upper_bound = pricing_matrix["External wall insulation"] * external_wall_area + pricing_matrix[
"ventilation"] * 3
elif row["Measure added"] == "Double Glazing":
cost = unit_cost * n_windows
elif row["Measure added"] == "LEDs":
cost = unit_cost * lighting_count[row["Property Type"]]
elif row["Measure added"] in [
'5kw ASHP feeding heating & Hot water (dual tariff)',
'11.2kw ASHP feeding heating & Hot water (dual tariff)',
"3 kWp Solar PV",
'4 kWp Solar PV',
"4.3 kWp Solar PV",
'4.8 kWp Solar PV',
'5 kWp Solar PV',
'5.5 kWp Solar PV'
]:
cost = unit_cost
elif row["Measure added"] == "HHRSH (dual tariff)":
cost = unit_cost * (n_rooms + 1)
elif row["Measure added"] == "Suspended floor insulation":
cost = unit_cost * ground_floor_area
else:
raise Exception()
cost_data.append(
{
"row_id": row["row_id"],
"epc": epc,
"sap": sap,
"cost": cost,
"cost upper bound": cost_upper_bound
}
)
cost_data = pd.DataFrame(cost_data)
risk_matrix = pd.merge(
epr_data,
cost_data,
on="row_id",
)
risk_matrix["contingency"] = risk_matrix["cost"] * contingency
risk_matrix["upper bound coningency"] = risk_matrix["cost upper bound"] * contingency
pricing_df = pd.DataFrame(
[
{
"Measure": k,
"Unit Cost": v
}
for k, v in pricing_matrix.items()
]
)
with pd.ExcelWriter(
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/L&G/Risk Matrix/risk_matrix V2.xlsx") as writer:
risk_matrix.to_excel(writer, sheet_name="Risk Matrix", index=False)
pricing_df.to_excel(writer, sheet_name="Pricing Assumptions", index=False)