mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
267 lines
9.8 KiB
Python
267 lines
9.8 KiB
Python
"""
|
|
Simple script to take a standardised asset list and calculate the abs. We'll use this code to estimate
|
|
the ABS for properties, going forward
|
|
"""
|
|
import os
|
|
import pandas as pd
|
|
import numpy as np
|
|
from dotenv import load_dotenv
|
|
from etl.find_my_epc.AssetListEpcData import AssetListEpcData
|
|
from backend.Funding import Funding
|
|
from backend.app.utils import sap_to_epc
|
|
|
|
load_dotenv(dotenv_path="backend/.env")
|
|
EPC_AUTH_TOKEN = os.getenv("EPC_AUTH_TOKEN")
|
|
|
|
# project = pd.read_excel(
|
|
|
|
# )
|
|
#
|
|
# cavity = project[project["cavity_reason"].isin(
|
|
# ["EPC Shows Empty Cavity: SAP Rating 54 or less", "EPC Shows Empty Cavity: SAP Rating 55-68"]
|
|
# )]
|
|
|
|
asset_list = pd.read_excel(
|
|
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Abri/Abs Rates/Desktop ABRI data - Standardised After "
|
|
"Programmes.xlsx",
|
|
sheet_name="Reviewed List"
|
|
)
|
|
asset_list = asset_list[asset_list["cavity_reason"].isin(
|
|
["EPC Shows Empty Cavity: SAP Rating 54 or less", "EPC Shows Empty Cavity: SAP Rating 55-68"]
|
|
)]
|
|
|
|
abs_matrix = pd.read_csv(
|
|
"/Users/khalimconn-kowlessar/Downloads/ECO4 Full Project Scores Matrix.csv"
|
|
)
|
|
pps_matrix = pd.read_excel(
|
|
"/Users/khalimconn-kowlessar/Downloads/ECO4 Partial Project Scores Matrix v5.xlsx",
|
|
header=1
|
|
)
|
|
pps_matrix.columns = [c.strip() for c in pps_matrix.columns]
|
|
|
|
# We need to estimate the number of points the work will produce and the finishing band. For this, we assume 7 for
|
|
# cavity and 15 for solar. We'll be more specific in the future, but for now, this is a good enough estimate.
|
|
route = asset_list[["domna_address_1", "domna_postcode", "epc_os_uprn"]].rename(
|
|
columns={"domna_address_1": "address", "domna_postcode": "postcode", "epc_os_uprn": "uprn"}
|
|
)
|
|
route["address"] = route["address"].astype(str)
|
|
|
|
asset_list_epc_client = AssetListEpcData(
|
|
asset_list=route,
|
|
epc_auth_token=EPC_AUTH_TOKEN
|
|
)
|
|
|
|
asset_list_epc_client.get_data()
|
|
asset_list_epc_client.get_non_invasive_recommendations()
|
|
|
|
# solar_sap_points = []
|
|
# for r in asset_list_epc_client.non_invasive_recommendations:
|
|
# if not r.get("recommendations"):
|
|
# continue
|
|
# solar_recommendations = [
|
|
# x for x in r["recommendations"] if "solar_pv" in x["type"]
|
|
# ]
|
|
# if solar_recommendations:
|
|
# solar_recommendations = solar_recommendations[0]
|
|
# else:
|
|
# continue
|
|
#
|
|
# address = r["address"]
|
|
# postcode = r["postcode"]
|
|
#
|
|
# solar_sap_points.append(
|
|
# {
|
|
# "address": address,
|
|
# "postcode": postcode,
|
|
# "sap_points": solar_recommendations["sap_points"]
|
|
# }
|
|
# )
|
|
#
|
|
# solar_sap_points = pd.DataFrame(solar_sap_points)
|
|
# solar_sap_points.drop_duplicates(subset=["address", "postcode"], inplace=True)
|
|
# # Store the sap points in the cavity route to csv
|
|
# solar_sap_points.to_csv(
|
|
# "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Abri/Abs Rates/cwi_sap_points.csv",
|
|
# index=False
|
|
# )
|
|
#
|
|
# avg_solar_points_by_postcode = solar_sap_points.groupby(["postcode"]).agg({"sap_points": "mean"}).reset_index()
|
|
# avg_solar_points = solar_sap_points["sap_points"].median()
|
|
# asset_list["domna_address_1"] = asset_list["domna_address_1"].astype(str)
|
|
# asset_list = asset_list.merge(
|
|
# solar_sap_points, how="left", left_on=["domna_address_1", "domna_postcode"], right_on=["address", "postcode"]
|
|
# ).drop(
|
|
# columns=["address", "postcode"]
|
|
# )
|
|
#
|
|
# # Fill the sap points with the average cwi points
|
|
# asset_list = asset_list.merge(
|
|
# avg_solar_points_by_postcode.rename(columns={"postcode": "domna_postcode"}),
|
|
# how="left", on=["domna_postcode"], suffixes=("", "_avg")
|
|
# )
|
|
# asset_list["sap_points"] = asset_list["sap_points"].fillna(asset_list["sap_points_avg"])
|
|
# asset_list.drop(columns=["sap_points_avg"], inplace=True)
|
|
#
|
|
# asset_list["sap_points"] = asset_list["sap_points"].fillna(avg_solar_points)
|
|
# asset_list["post_works_sap"] = asset_list["epc_sap_score_on_register"] + asset_list["sap_points"]
|
|
# asset_list["post_works_epc"] = asset_list["post_works_sap"].apply(lambda x: sap_to_epc(x))
|
|
# asset_list["starting_half_band"] = asset_list["epc_sap_score_on_register"].apply(lambda x: Funding.get_sap_band(x))
|
|
# asset_list["ending_half_band"] = asset_list["post_works_sap"].apply(lambda x: Funding.get_sap_band(x))
|
|
# asset_list["floor_area_band"] = asset_list["epc_total_floor_area"].apply(lambda x: Funding.get_floor_area_band(x))
|
|
#
|
|
# asset_list["ending_half_band"] = np.where(
|
|
# (asset_list["post_works_epc"] == asset_list["epc_rating_on_register"]),
|
|
# "Low_C",
|
|
# asset_list["ending_half_band"]
|
|
# )
|
|
# # Realistically, we'll take the properties to a low C at worst
|
|
# asset_list["ending_half_band"] = np.where(
|
|
# (asset_list["post_works_sap"] < 69),
|
|
# "Low_C",
|
|
# asset_list["ending_half_band"]
|
|
# )
|
|
#
|
|
# asset_list = asset_list.merge(
|
|
# abs_matrix, how="left", left_on=["starting_half_band", "ending_half_band", "floor_area_band"],
|
|
# right_on=['Starting Band', 'Finishing Band', 'Floor Area Segment', ]
|
|
# )
|
|
# asset_list = asset_list.drop(columns=['Starting Band', 'Finishing Band', 'Floor Area Segment'])
|
|
#
|
|
# asset_list = asset_list.rename(
|
|
# columns={"Cost Savings": "funding_abs"}
|
|
# )
|
|
#
|
|
# print(asset_list["domna_property_id"].duplicated().sum())
|
|
#
|
|
# # Store this data
|
|
# asset_list.to_csv(
|
|
# "/Users/khalimconn-kowlessar/Documents/hestia/Instagroup Review/livewest_sw_solar_abs_estimates-solar.csv",
|
|
# index=False
|
|
# )
|
|
|
|
# Cavity process!
|
|
cwi_sap_points = []
|
|
for r in asset_list_epc_client.non_invasive_recommendations:
|
|
if not r.get("recommendations"):
|
|
continue
|
|
cwi_recommendations = [
|
|
x for x in r["recommendations"] if "cavity_wall_insulation" in x["type"]
|
|
]
|
|
if cwi_recommendations:
|
|
cwi_recommendations = cwi_recommendations[0]
|
|
else:
|
|
continue
|
|
|
|
address = r["address"]
|
|
postcode = r["postcode"]
|
|
|
|
cwi_sap_points.append(
|
|
{
|
|
"address": address,
|
|
"postcode": postcode,
|
|
"type": cwi_recommendations["type"],
|
|
"sap_points": cwi_recommendations["sap_points"]
|
|
}
|
|
)
|
|
|
|
cwi_sap_points = pd.DataFrame(cwi_sap_points)
|
|
cwi_sap_points = pd.read_csv(
|
|
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Abri/Abs Rates/cwi_sap_points.csv",
|
|
)
|
|
cwi_sap_points.drop_duplicates(subset=["address", "postcode"], inplace=True)
|
|
avg_cwi_points_by_postcode = cwi_sap_points.groupby(["postcode"]).agg({"sap_points": "mean"}).reset_index()
|
|
avg_cwi_points = cwi_sap_points["sap_points"].median()
|
|
asset_list = asset_list.merge(
|
|
cwi_sap_points, how="left", left_on=["domna_address_1", "domna_postcode"], right_on=["address", "postcode"]
|
|
).drop(
|
|
columns=["address", "postcode"]
|
|
)
|
|
|
|
# Fill the sap points with the average cwi points
|
|
asset_list = asset_list.merge(
|
|
avg_cwi_points_by_postcode.rename(columns={"postcode": "domna_postcode"}),
|
|
how="left", on=["domna_postcode"], suffixes=("", "_avg")
|
|
)
|
|
asset_list["sap_points"] = asset_list["sap_points"].fillna(asset_list["sap_points_avg"])
|
|
asset_list.drop(columns=["sap_points_avg"], inplace=True)
|
|
|
|
asset_list["sap_points"] = asset_list["sap_points"].fillna(avg_cwi_points)
|
|
asset_list["post_works_sap"] = asset_list["epc_sap_score_on_register"] + asset_list["sap_points"]
|
|
asset_list["post_works_epc"] = asset_list["post_works_sap"].apply(lambda x: sap_to_epc(x))
|
|
asset_list["starting_half_band"] = asset_list["epc_sap_score_on_register"].apply(lambda x: Funding.get_sap_band(x))
|
|
asset_list["ending_half_band"] = asset_list["post_works_sap"].apply(lambda x: Funding.get_sap_band(x))
|
|
asset_list["floor_area_band"] = asset_list["epc_total_floor_area"].apply(lambda x: Funding.get_floor_area_band(x))
|
|
|
|
asset_list["funding_scheme"] = np.where(
|
|
(
|
|
(asset_list["post_works_epc"] == asset_list["epc_rating_on_register"])
|
|
),
|
|
"GBIS",
|
|
"ECO4"
|
|
)
|
|
# Note - anything that is EPC E or below that doesn't go up to a C will be GBIS
|
|
# To detect this, if the starting sap score is 54 or below and the endding SAP sore is 68 or below
|
|
# we will assume it is GBIS
|
|
asset_list["funding_scheme"] = np.where(
|
|
(asset_list["post_works_sap"] < 69) & (asset_list["epc_sap_score_on_register"] < 55),
|
|
"GBIS",
|
|
asset_list["funding_scheme"]
|
|
)
|
|
|
|
asset_list = asset_list.merge(
|
|
abs_matrix, how="left", left_on=["starting_half_band", "ending_half_band", "floor_area_band"],
|
|
right_on=['Starting Band', 'Finishing Band', 'Floor Area Segment', ]
|
|
)
|
|
asset_list = asset_list.drop(columns=['Starting Band', 'Finishing Band', 'Floor Area Segment'])
|
|
|
|
# Using CWI 0.033 as the partial project score
|
|
cwi_pps_matrix = pps_matrix[
|
|
pps_matrix["Measure_Type"].isin(["CWI_0.033"])
|
|
]
|
|
# Merge on
|
|
asset_list = asset_list.merge(
|
|
cwi_pps_matrix[['Starting Band', 'Total Floor Area Band', 'Cost Savings']].rename(
|
|
columns={
|
|
"Cost Savings": "partial_project_score",
|
|
"Starting Band": "starting_half_band",
|
|
"Total Floor Area Band": "floor_area_band"
|
|
}
|
|
),
|
|
how="left",
|
|
on=["starting_half_band", "floor_area_band"],
|
|
)
|
|
asset_list["partial_project_score"] = np.where(
|
|
(asset_list["epc_sap_score_on_register"] > 69),
|
|
None,
|
|
asset_list["partial_project_score"]
|
|
)
|
|
|
|
asset_list["funding_abs"] = np.where(
|
|
asset_list["funding_scheme"] == "GBIS",
|
|
asset_list["partial_project_score"],
|
|
asset_list["Cost Savings"]
|
|
)
|
|
|
|
from recommendations.recommendation_utils import (
|
|
estimate_external_wall_area,
|
|
)
|
|
|
|
# For some reason, estimated insulation wall area is missing
|
|
asset_list["estimated_insulation_wall_area"] = asset_list.apply(
|
|
lambda x: estimate_external_wall_area(
|
|
num_floors=x["attribute_est_number_floors"],
|
|
floor_height=(
|
|
float(x["epc_floor_height"]) if
|
|
not pd.isnull(x["epc_floor_height"]) else 2.5
|
|
),
|
|
perimeter=x["attribute_est_perimter"],
|
|
built_form=x["epc_archetype"]
|
|
),
|
|
axis=1
|
|
)
|
|
|
|
# Store this data
|
|
asset_list.to_csv(
|
|
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Abri/Abs Rates/Abri CWI ABS Estimates.csv",
|
|
index=False
|
|
)
|