mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
westward complete
This commit is contained in:
parent
67f3e8ab70
commit
ddfbf33494
5 changed files with 94 additions and 61 deletions
|
|
@ -286,7 +286,7 @@ class AssetList:
|
||||||
# This SAP threshold is a key search criteria for properties that may be eligible for extraction
|
# This SAP threshold is a key search criteria for properties that may be eligible for extraction
|
||||||
FILLED_CAVITY_SAP_THRESHOLD = 75
|
FILLED_CAVITY_SAP_THRESHOLD = 75
|
||||||
# This SAP the
|
# This SAP the
|
||||||
EMPTY_CAVITY_SAP_THRESHOLD = 71
|
EMPTY_CAVITY_SAP_THRESHOLD = 75
|
||||||
# Any EPC deemed to have been conducted prior to this year is deemed to be unreliable
|
# Any EPC deemed to have been conducted prior to this year is deemed to be unreliable
|
||||||
EPC_YEAR_THRESHOLD = pd.Timestamp.now().year - 5
|
EPC_YEAR_THRESHOLD = pd.Timestamp.now().year - 5
|
||||||
|
|
||||||
|
|
@ -956,13 +956,28 @@ class AssetList:
|
||||||
(~self.standardised_asset_list[self.STANDARD_PROPERTY_TYPE].isin(["bedsit"])) &
|
(~self.standardised_asset_list[self.STANDARD_PROPERTY_TYPE].isin(["bedsit"])) &
|
||||||
(self.standardised_asset_list['non-intrusives: Construction'] == "CAVITY") &
|
(self.standardised_asset_list['non-intrusives: Construction'] == "CAVITY") &
|
||||||
self.standardised_asset_list['non-intrusives: Insulated'].isin(["EMPTY", "PARTIAL"]) &
|
self.standardised_asset_list['non-intrusives: Insulated'].isin(["EMPTY", "PARTIAL"]) &
|
||||||
(self.standardised_asset_list[self.STANDARD_YEAR_BUILT] <= 2000) &
|
(self.standardised_asset_list[self.STANDARD_YEAR_BUILT] <= 2002) &
|
||||||
(
|
(
|
||||||
self.standardised_asset_list[
|
self.standardised_asset_list[
|
||||||
self.EPC_API_DATA_NAMES["current-energy-efficiency"]
|
self.EPC_API_DATA_NAMES["current-energy-efficiency"]
|
||||||
] <= self.EMPTY_CAVITY_SAP_THRESHOLD
|
] <= self.EMPTY_CAVITY_SAP_THRESHOLD
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
# Let's also flag work that looks eligible without the SAP filter
|
||||||
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity_no_sap_filter"] = (
|
||||||
|
(~self.standardised_asset_list[self.STANDARD_PROPERTY_TYPE].isin(["bedsit"])) &
|
||||||
|
(self.standardised_asset_list['non-intrusives: Construction'] == "CAVITY") &
|
||||||
|
self.standardised_asset_list['non-intrusives: Insulated'].isin(["EMPTY", "PARTIAL"]) &
|
||||||
|
(self.standardised_asset_list[self.STANDARD_YEAR_BUILT] <= 2002)
|
||||||
|
)
|
||||||
|
|
||||||
|
# If non_intrusive_indicates_empty_cavity is True,
|
||||||
|
# set non_intrusive_indicates_empty_cavity_no_sap_filter to False
|
||||||
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity_no_sap_filter"] = np.where(
|
||||||
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity"],
|
||||||
|
False,
|
||||||
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity_no_sap_filter"]
|
||||||
|
)
|
||||||
|
|
||||||
self.standardised_asset_list["epc_indicates_empty_cavity"] = (
|
self.standardised_asset_list["epc_indicates_empty_cavity"] = (
|
||||||
self.standardised_asset_list[self.EPC_API_DATA_NAMES["walls-description"]].str.lower().isin(
|
self.standardised_asset_list[self.EPC_API_DATA_NAMES["walls-description"]].str.lower().isin(
|
||||||
|
|
@ -977,17 +992,16 @@ class AssetList:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
z0 = self.standardised_asset_list[
|
# If the EPC is esimtated, we defer to the non-intrusives
|
||||||
self.standardised_asset_list["epc_indicates_empty_cavity"] & (
|
self.standardised_asset_list["epc_indicates_empty_cavity"] = np.where(
|
||||||
~self.standardised_asset_list["non_intrusive_indicates_empty_cavity"]
|
(
|
||||||
)
|
self.standardised_asset_list["epc_indicates_empty_cavity"] &
|
||||||
]
|
~self.standardised_asset_list["non_intrusive_indicates_empty_cavity"] &
|
||||||
z0['non-intrusives: Construction'].value_counts()
|
self.standardised_asset_list["estimated"]
|
||||||
z0['non-intrusives: Insulated'].value_counts()
|
),
|
||||||
z00 = z0[z0['non-intrusives: Insulated'] == "EWI"]
|
False,
|
||||||
|
self.standardised_asset_list["epc_indicates_empty_cavity"]
|
||||||
# If the EPC is estimated, perhaps we should defer to the non-intrusives?
|
)
|
||||||
z00[""]
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
# Extraction
|
# Extraction
|
||||||
|
|
@ -997,33 +1011,14 @@ class AssetList:
|
||||||
self.standardised_asset_list["non_intrusive_indicates_cavity_extraction"] = (
|
self.standardised_asset_list["non_intrusive_indicates_cavity_extraction"] = (
|
||||||
(self.standardised_asset_list["non-intrusives: Construction"] == "CAVITY") &
|
(self.standardised_asset_list["non-intrusives: Construction"] == "CAVITY") &
|
||||||
(self.standardised_asset_list["non-intrusives: Insulated"].isin(["RETRO DRILLED", "FILLED AT BUILD"])) &
|
(self.standardised_asset_list["non-intrusives: Insulated"].isin(["RETRO DRILLED", "FILLED AT BUILD"])) &
|
||||||
(~self.standardised_asset_list['non-intrusives: Material'].isin(["GREY LOOSE BEAD", "COMPACTED BEAD"])
|
(~self.standardised_asset_list['non-intrusives: Material'].isin(
|
||||||
|
["GREY LOOSE BEAD", "COMPACTED BEAD", "FIBRE BATT NO CAVITY", "EMPTY NARROW BELOW 30mm"]
|
||||||
|
)
|
||||||
) & (
|
) & (
|
||||||
self.standardised_asset_list[self.ATTRIBUTE_SAP_THRESHOLD_AND_BELOW]
|
self.standardised_asset_list[self.ATTRIBUTE_SAP_THRESHOLD_AND_BELOW]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# z3 = self.standardised_asset_list[
|
|
||||||
# self.standardised_asset_list["non_intrusive_indicates_cavity_extraction"]
|
|
||||||
# ]
|
|
||||||
# z3['non-intrusives: Material'].value_counts()
|
|
||||||
# self.standardised_asset_list['non-intrusives: Material'].value_counts()
|
|
||||||
#
|
|
||||||
# z = self.standardised_asset_list[
|
|
||||||
# self.standardised_asset_list["non-intrusives: CIGA Check Required"] == "YES"
|
|
||||||
# ]
|
|
||||||
# z["non-intrusives: Insulated"].value_counts()
|
|
||||||
# z["non-intrusives: Material"].value_counts()
|
|
||||||
# z[self.ATTRIBUTE_SAP_THRESHOLD_AND_BELOW].value_counts()
|
|
||||||
# z[self.EPC_API_DATA_NAMES["current-energy-efficiency"]].max()
|
|
||||||
# z[self.EPC_API_DATA_NAMES["current-energy-efficiency"]].min()
|
|
||||||
# z[self.STANDARD_YEAR_BUILT].describe()
|
|
||||||
#
|
|
||||||
# zz = z[z[self.EPC_API_DATA_NAMES["current-energy-efficiency"]] == 105]
|
|
||||||
# z2 = self.standardised_asset_list[
|
|
||||||
# self.standardised_asset_list["non-intrusives: CIGA Check Required"] == "NO"
|
|
||||||
# ]
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
# Solar
|
# Solar
|
||||||
######################################################
|
######################################################
|
||||||
|
|
@ -1114,7 +1109,7 @@ class AssetList:
|
||||||
) | (
|
) | (
|
||||||
self.standardised_asset_list[
|
self.standardised_asset_list[
|
||||||
"walls_u_value"].apply(
|
"walls_u_value"].apply(
|
||||||
lambda x: x <= 0.3 if not pd.isnull(
|
lambda x: x <= 0.7 if not pd.isnull(
|
||||||
x) else False
|
x) else False
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -1141,7 +1136,7 @@ class AssetList:
|
||||||
"|".join(self.EPC_INSULATED_ROOF_SUBSTRINGS), regex=False
|
"|".join(self.EPC_INSULATED_ROOF_SUBSTRINGS), regex=False
|
||||||
) | (
|
) | (
|
||||||
self.standardised_asset_list[self.ATTRIBUTE_EPC_ROOF_INSULATION_THICKNESS].apply(
|
self.standardised_asset_list[self.ATTRIBUTE_EPC_ROOF_INSULATION_THICKNESS].apply(
|
||||||
lambda x: int(x) >= 270 if str(x).isdigit() else False
|
lambda x: int(x) >= 200 if str(x).isdigit() else False
|
||||||
)
|
)
|
||||||
) | (
|
) | (
|
||||||
self.standardised_asset_list["roof_u_value"].apply(
|
self.standardised_asset_list["roof_u_value"].apply(
|
||||||
|
|
@ -1152,7 +1147,7 @@ class AssetList:
|
||||||
|
|
||||||
self.standardised_asset_list["solar_epc_loft_needs_topup"] = self.standardised_asset_list[
|
self.standardised_asset_list["solar_epc_loft_needs_topup"] = self.standardised_asset_list[
|
||||||
self.ATTRIBUTE_EPC_ROOF_INSULATION_THICKNESS].apply(
|
self.ATTRIBUTE_EPC_ROOF_INSULATION_THICKNESS].apply(
|
||||||
lambda x: int(x) < 270 if str(x).isdigit() else False
|
lambda x: int(x) < 200 if str(x).isdigit() else False
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: Fill with False - should be temp!
|
# TODO: Fill with False - should be temp!
|
||||||
|
|
@ -1187,7 +1182,7 @@ class AssetList:
|
||||||
) & (
|
) & (
|
||||||
# We do not utilise estimated EPCs for this method because we will always find that
|
# We do not utilise estimated EPCs for this method because we will always find that
|
||||||
# "epc_has_floor_recommendation" is False
|
# "epc_has_floor_recommendation" is False
|
||||||
~self.standardised_asset_list["estimated"]
|
(self.standardised_asset_list["estimated"] == False)
|
||||||
)
|
)
|
||||||
) | (
|
) | (
|
||||||
(
|
(
|
||||||
|
|
@ -1212,7 +1207,7 @@ class AssetList:
|
||||||
) & (
|
) & (
|
||||||
# We do not utilise estimated EPCs for this method because we will always find that
|
# We do not utilise estimated EPCs for this method because we will always find that
|
||||||
# "epc_has_floor_recommendation" is False
|
# "epc_has_floor_recommendation" is False
|
||||||
~self.standardised_asset_list["estimated"]
|
self.standardised_asset_list["estimated"] == False
|
||||||
)
|
)
|
||||||
) | (
|
) | (
|
||||||
(
|
(
|
||||||
|
|
@ -1274,6 +1269,7 @@ class AssetList:
|
||||||
)
|
)
|
||||||
|
|
||||||
# Other floor type, fully insulated
|
# Other floor type, fully insulated
|
||||||
|
|
||||||
self.standardised_asset_list["solar_eligible_other_floor"] = (
|
self.standardised_asset_list["solar_eligible_other_floor"] = (
|
||||||
# Landlord data or EPC data indicates the heating system is appropriate
|
# Landlord data or EPC data indicates the heating system is appropriate
|
||||||
(
|
(
|
||||||
|
|
@ -1332,6 +1328,9 @@ class AssetList:
|
||||||
"Empty Cavity (non-intrusives)": (
|
"Empty Cavity (non-intrusives)": (
|
||||||
self.standardised_asset_list["non_intrusive_indicates_empty_cavity"].sum()
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity"].sum()
|
||||||
),
|
),
|
||||||
|
"Empty Cavity (non-intrusives, no SAP filter)": (
|
||||||
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity_no_sap_filter"].sum()
|
||||||
|
),
|
||||||
"Empty Cavity (EPC)": (
|
"Empty Cavity (EPC)": (
|
||||||
(
|
(
|
||||||
self.standardised_asset_list["epc_indicates_empty_cavity"] &
|
self.standardised_asset_list["epc_indicates_empty_cavity"] &
|
||||||
|
|
@ -1359,6 +1358,17 @@ class AssetList:
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# We produce a breakdown of the property types, for cavity fills
|
||||||
|
cavity_fills = self.standardised_asset_list[
|
||||||
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity"] | (
|
||||||
|
self.standardised_asset_list["epc_indicates_empty_cavity"]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.work_type_breakdowns = {
|
||||||
|
"empty_cavity": cavity_fills[self.STANDARD_PROPERTY_TYPE].value_counts()
|
||||||
|
}
|
||||||
|
|
||||||
# Finally, we note why each property has been flagged
|
# Finally, we note why each property has been flagged
|
||||||
self.standardised_asset_list["cavity_reason"] = None
|
self.standardised_asset_list["cavity_reason"] = None
|
||||||
self.standardised_asset_list["cavity_reason"] = np.where(
|
self.standardised_asset_list["cavity_reason"] = np.where(
|
||||||
|
|
@ -1366,6 +1376,11 @@ class AssetList:
|
||||||
"Non-Intrusive Data Showed Empty Cavity",
|
"Non-Intrusive Data Showed Empty Cavity",
|
||||||
self.standardised_asset_list["cavity_reason"]
|
self.standardised_asset_list["cavity_reason"]
|
||||||
)
|
)
|
||||||
|
self.standardised_asset_list["cavity_reason"] = np.where(
|
||||||
|
self.standardised_asset_list["non_intrusive_indicates_empty_cavity_no_sap_filter"],
|
||||||
|
"Non-Intrusive Data Showed Empty Cavity but all SAP scores allowed",
|
||||||
|
self.standardised_asset_list["cavity_reason"]
|
||||||
|
)
|
||||||
self.standardised_asset_list["cavity_reason"] = np.where(
|
self.standardised_asset_list["cavity_reason"] = np.where(
|
||||||
(
|
(
|
||||||
self.standardised_asset_list["epc_indicates_empty_cavity"] &
|
self.standardised_asset_list["epc_indicates_empty_cavity"] &
|
||||||
|
|
|
||||||
|
|
@ -246,22 +246,40 @@ def app():
|
||||||
# - We want: fully insulated property (all wall types), EPC D or below (floors should be solid)
|
# - We want: fully insulated property (all wall types), EPC D or below (floors should be solid)
|
||||||
# - Or the insulation required is loft/cavity (floors should be solid)
|
# - Or the insulation required is loft/cavity (floors should be solid)
|
||||||
|
|
||||||
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Colchester"
|
# data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Colchester"
|
||||||
data_filename = "Warmfront data- Colchester Borough Homes (Complete).xlsx"
|
# data_filename = "Warmfront data- Colchester Borough Homes (Complete).xlsx"
|
||||||
|
# sheet_name = "Sheet1"
|
||||||
|
# postcode_column = 'Full Address.1'
|
||||||
|
# fulladdress_column = "Full Address"
|
||||||
|
# address1_column = None
|
||||||
|
# address1_method = "first_word"
|
||||||
|
# address_cols_to_concat = []
|
||||||
|
# missing_postcodes_method = None
|
||||||
|
# landlord_year_built = "Build Date"
|
||||||
|
# landlord_os_uprn = None
|
||||||
|
# landlord_property_type = "Property Type"
|
||||||
|
# landlord_wall_construction = "Wallinsul"
|
||||||
|
# landlord_heating_system = "HeatSorc"
|
||||||
|
# landlord_existing_pv = None
|
||||||
|
# landlord_property_id = "Property Reference"
|
||||||
|
|
||||||
|
# For Westward
|
||||||
|
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Westward"
|
||||||
|
data_filename = "WESTWARD - completed list..xlsx"
|
||||||
sheet_name = "Sheet1"
|
sheet_name = "Sheet1"
|
||||||
postcode_column = 'Full Address.1'
|
postcode_column = "WFT EDIT Postcode"
|
||||||
fulladdress_column = "Full Address"
|
fulladdress_column = "Address"
|
||||||
address1_column = None
|
address1_column = None
|
||||||
address1_method = "first_word"
|
address1_method = "house_number_extraction"
|
||||||
address_cols_to_concat = []
|
address_cols_to_concat = []
|
||||||
missing_postcodes_method = None
|
missing_postcodes_method = None
|
||||||
landlord_year_built = "Build Date"
|
landlord_year_built = "Build date"
|
||||||
landlord_os_uprn = None
|
landlord_os_uprn = "UPRN"
|
||||||
landlord_property_type = "Property Type"
|
landlord_property_type = "Location type"
|
||||||
landlord_wall_construction = "Wallinsul"
|
landlord_wall_construction = "Wall Construction (EPC)"
|
||||||
landlord_heating_system = "HeatSorc"
|
landlord_heating_system = "Heat Source"
|
||||||
landlord_existing_pv = None
|
landlord_existing_pv = "PV (Y/N)"
|
||||||
landlord_property_id = "Property Reference"
|
landlord_property_id = "Place ref"
|
||||||
|
|
||||||
# Maps addresses to uprn in problematic cases
|
# Maps addresses to uprn in problematic cases
|
||||||
MANUAL_UPRN_MAP = {}
|
MANUAL_UPRN_MAP = {}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ WALL_CONSTRUCTION_MAPPINGS = {
|
||||||
'Timber frame, as built, no insulation (assumed)': 'timber frame',
|
'Timber frame, as built, no insulation (assumed)': 'timber frame',
|
||||||
'Timber frame, as built, partial insulation (assumed)': 'timber frame',
|
'Timber frame, as built, partial insulation (assumed)': 'timber frame',
|
||||||
'Timber frame, with additional insulation': 'timber frame',
|
'Timber frame, with additional insulation': 'timber frame',
|
||||||
'CAVITY': 'partial unknown cavity',
|
'CAVITY': 'cavity unknown insulation',
|
||||||
'COMB': 'unknown',
|
'COMB': 'unknown',
|
||||||
'NONE': 'unknown',
|
'NONE': 'unknown',
|
||||||
'NOTKNOWN': 'unknown',
|
'NOTKNOWN': 'unknown',
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from dotenv import load_dotenv
|
||||||
from utils.s3 import save_csv_to_s3
|
from utils.s3 import save_csv_to_s3
|
||||||
from etl.find_my_epc.AssetListEpcData import AssetListEpcData
|
from etl.find_my_epc.AssetListEpcData import AssetListEpcData
|
||||||
|
|
||||||
PORTFOLIO_ID = 133
|
PORTFOLIO_ID = 137
|
||||||
USER_ID = 8
|
USER_ID = 8
|
||||||
|
|
||||||
load_dotenv(dotenv_path="backend/.env")
|
load_dotenv(dotenv_path="backend/.env")
|
||||||
|
|
@ -19,10 +19,10 @@ def app():
|
||||||
|
|
||||||
asset_list = [
|
asset_list = [
|
||||||
{
|
{
|
||||||
"address": "40",
|
"address": "41 Gainsborough Way",
|
||||||
"postcode": "PE4 5BB",
|
"postcode": "BA21 5XU",
|
||||||
"uprn": 100090220519,
|
"uprn": 30016708,
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
asset_list = pd.DataFrame(asset_list)
|
asset_list = pd.DataFrame(asset_list)
|
||||||
|
|
||||||
|
|
@ -52,8 +52,8 @@ def app():
|
||||||
|
|
||||||
valuation_data = [
|
valuation_data = [
|
||||||
{
|
{
|
||||||
"uprn": 100090220519,
|
"uprn": 30016708,
|
||||||
"valuation": 135_000
|
"valuation": 189000
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
# Store valuation data to s3
|
# Store valuation data to s3
|
||||||
|
|
|
||||||
|
|
@ -993,7 +993,7 @@ class HeatingRecommender:
|
||||||
# We check if there's a mains connection and the hot water is inefficient, as this will improve with a boiler
|
# We check if there's a mains connection and the hot water is inefficient, as this will improve with a boiler
|
||||||
has_inefficient_water = (
|
has_inefficient_water = (
|
||||||
self.property.data["mains-gas-flag"] and
|
self.property.data["mains-gas-flag"] and
|
||||||
self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor", "Average"]
|
self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor"]
|
||||||
)
|
)
|
||||||
|
|
||||||
non_invasive_recommendation = next((
|
non_invasive_recommendation = next((
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue