diff --git a/asset_list/AssetList.py b/asset_list/AssetList.py index 056f8b5d..ffe53d40 100644 --- a/asset_list/AssetList.py +++ b/asset_list/AssetList.py @@ -341,6 +341,8 @@ class AssetList: # Read in the data self.raw_asset_list = pd.read_excel(local_filepath, header=header, sheet_name=sheet_name) self.standardised_asset_list = self.raw_asset_list.copy() + # Will be used to store aggregated figures against the various work types + self.work_type_figures = {} # We detect the presence of the non-intrusive columns self.non_intrusives_present = True if "CIGA Check Required" in self.raw_asset_list.columns else False @@ -1062,6 +1064,23 @@ class AssetList: self.standardised_asset_list["epc_has_floor_recommendation"].fillna(False) ) + # We merge on the u-value for average thermal transmittance + floors_uvalue_data = pd.DataFrame(cleaned["floor-description"]) + floors_uvalue_data = floors_uvalue_data[ + ~pd.isnull(floors_uvalue_data["thermal_transmittance"]) + ][["original_description", "thermal_transmittance"]].rename( + columns={ + "original_description": self.EPC_API_DATA_NAMES["floor-description"], + "thermal_transmittance": "floor_u_value" + } + ) + + # Merge on + self.standardised_asset_list = self.standardised_asset_list.merge( + floors_uvalue_data, how="left", on=self.EPC_API_DATA_NAMES["floor-description"] + ) + + # We assume that a U-value of 0.5 or below is indicative of an insulated floor self.standardised_asset_list["solar_epc_floor_is_solid_no_recommendation"] = ( ( ( @@ -1072,7 +1091,8 @@ class AssetList: ) ) | ( ( - self.standardised_asset_list[self.EPC_API_DATA_NAMES["floor-description"]].str.contains("solid") + self.standardised_asset_list[ + self.EPC_API_DATA_NAMES["floor-description"]].str.lower().str.contains("solid") ) & ( self.standardised_asset_list[self.EPC_API_DATA_NAMES["floor-description"]].str.lower() .str.contains(", insulated") @@ -1080,6 +1100,33 @@ class AssetList: ) ) + # Check for other floor types, insulated + self.standardised_asset_list["solar_epc_floor_is_other_insulated"] = ( + # The floor is suspended and insulated + ( + ( + self.standardised_asset_list[self.EPC_API_DATA_NAMES["floor-description"]].str + .lower().str.contains("suspended") + ) & ( + ~self.standardised_asset_list["epc_has_floor_recommendation"] + ) + ) | ( + ( + self.standardised_asset_list[ + self.EPC_API_DATA_NAMES["floor-description"] + ].str.lower().str.contains("suspended") + ) & ( + self.standardised_asset_list[ + self.EPC_API_DATA_NAMES["floor-description"] + ].str.lower().str.contains(", insulated") + ) + ) | ( + self.standardised_asset_list["floor_u_value"].apply( + lambda x: x <= 0.5 if not pd.isnull(x) else False + ) + ) + ) + # We now put together the criteria: # Flag properties that look eligible for solar, that have solid floors # TODO: We'll need to revise this @@ -1120,6 +1167,70 @@ class AssetList: self.standardised_asset_list["solar_epc_floor_is_solid_no_recommendation"] ) - # Suspended floor, fully insulated + # Other floor type, fully insulated + self.standardised_asset_list["solar_eligible_other_floor"] = ( + # Landlord data or EPC data indicates the heating system is appropriate + ( + self.standardised_asset_list["solar_landlord_data_indicates_correct_heating_system"] | + self.standardised_asset_list["solar_epc_data_indicates_correct_heating_system"] + ) & + # The property doesn't currently have solar + ~self.standardised_asset_list["property_has_solar"] & + # The walls are insulated + ( + self.standardised_asset_list["solar_landlord_walls_insulated"] | + self.standardised_asset_list["solar_epc_walls_insulated"] + ) & + # Roof is insulated + self.standardised_asset_list["solar_epc_roof_insulated"] & + self.standardised_asset_list["solar_epc_floor_is_other_insulated"] + ) - # ~self.standardised_asset_list["solar_epc_loft_needs_topup"] & + # Other floor type, needs loft top-up + self.standardised_asset_list["solar_eligible_other_floor_needs_loft"] = ( + # Landlord data or EPC data indicates the heating system is appropriate + ( + self.standardised_asset_list["solar_landlord_data_indicates_correct_heating_system"] | + self.standardised_asset_list["solar_epc_data_indicates_correct_heating_system"] + ) & + # The property doesn't currently have solar + ~self.standardised_asset_list["property_has_solar"] & + # The walls are insulated + ( + self.standardised_asset_list["solar_landlord_walls_insulated"] | + self.standardised_asset_list["solar_epc_walls_insulated"] + ) & + # Roof need loft top-up + self.standardised_asset_list["solar_epc_loft_needs_topup"] & + # Floor is not solid, but is insulated + self.standardised_asset_list["solar_epc_floor_is_other_insulated"] + ) + + # Produce some aggregate figures + self.work_type_figures = { + # Empty cavity from non-intrusives + "Empty Cavity (non-intrusives)": ( + self.standardised_asset_list["non_intrusive_indicates_empty_cavity"].sum() + ), + "Empty Cavity (EPC)": ( + ( + self.standardised_asset_list["epc_indicates_empty_cavity"] & + ~self.standardised_asset_list["non_intrusive_indicates_empty_cavity"] + ).sum() + ), + "Cavity Extraction": ( + self.standardised_asset_list["non_intrusive_indicates_cavity_extraction"].sum() + ), + "Solar PV (Solid Floor)": ( + self.standardised_asset_list["solar_eligible_solid_floor"].sum() + ), + "Solar PV (Solid Floor, Needs Loft Top-up)": ( + self.standardised_asset_list["solar_eligible_solid_floor_needs_loft"].sum() + ), + "Solar PV (Other Floor)": ( + self.standardised_asset_list["solar_eligible_other_floor"].sum() + ), + "Solar PV (Other Floor, Needs Loft Top-up)": ( + self.standardised_asset_list["solar_eligible_other_floor_needs_loft"].sum() + ) + } diff --git a/etl/route_march_data_pull/app.py b/etl/route_march_data_pull/app.py index 0de85a27..5960f69b 100644 --- a/etl/route_march_data_pull/app.py +++ b/etl/route_march_data_pull/app.py @@ -440,7 +440,6 @@ def app(): asset_list.extract_attributes() - # TODO - Use this! import msgpack from utils.s3 import read_from_s3 cleaned = read_from_s3(