mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
185 lines
6.1 KiB
Python
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)
|