This commit is contained in:
Jun-te Kim 2026-01-27 18:52:51 +00:00
parent 0254c945e8
commit 1acf4f4d6a
6 changed files with 340 additions and 328 deletions

View file

@ -18,4 +18,5 @@ pytest-cov==7.0.0
ipykernel>=6.25,<7 ipykernel>=6.25,<7
pydantic-settings<2 pydantic-settings<2
pyyaml>=6.0.1 pyyaml>=6.0.1
pydantic>=1.10.7,<2 pydantic>=1.10.7,<2
sqlmodel

View file

@ -1,7 +1,7 @@
from sqlalchemy import create_engine from sqlalchemy import create_engine
from contextlib import contextmanager from contextlib import contextmanager
from backend.app.config import get_settings from backend.app.config import get_settings
from sqlmodel import Session # from sqlmodel import Session
connection_string = "postgresql+{drivername}://{username}:{password}@{server}:{port}/{dbname}" connection_string = "postgresql+{drivername}://{username}:{password}@{server}:{port}/{dbname}"
db_string = connection_string.format( db_string = connection_string.format(

View file

@ -10,4 +10,5 @@ boto3==1.35.44
# Data # Data
openpyxl==3.1.2 openpyxl==3.1.2
# Basic # Basic
pytz pytz
sqlmodel

View file

@ -98,8 +98,17 @@ def main():
results.append(tmp) results.append(tmp)
final_df = pd.concat(results, ignore_index=True) final_df = pd.concat(results, ignore_index=True)
a = final_df[["best_match_lexiscore","Address 1", "best_match_address", "Postcode", "UPRN", "best_match_uprn"]] # add levi score to viewing a = final_df[[
"best_match_lexiscore","Address 1",
"best_match_address", "Postcode",
"UPRN", "best_match_uprn"
]] # add levi score to viewing
b = final_df[final_df["best_match_lexiscore"]>0] # add levi score to viewing b = final_df[final_df["best_match_lexiscore"]>0] # add levi score to viewing
b = b[[
"best_match_lexiscore","Address 1",
"best_match_address", "Postcode",
"UPRN", "best_match_uprn"
]]
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -1,111 +1,111 @@
import pandas as pd import pandas as pd
epc_c_recommendations = pd.read_excel( # epc_c_recommendations = pd.read_excel(
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no " # "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no "
"solid floor, ashp 3.0 - corrected.xlsx" # "solid floor, ashp 3.0 - corrected.xlsx"
) # )
epc_b_recommendations = pd.read_excel( # epc_b_recommendations = pd.read_excel(
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC B - no " # "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC B - no "
"solid floor, ashp 3.0 - corrected.xlsx" # "solid floor, ashp 3.0 - corrected.xlsx"
) # )
epc_c_movers = epc_b_recommendations[ # epc_c_movers = epc_b_recommendations[
epc_b_recommendations["current_epc_rating"] == "Epc.C" # epc_b_recommendations["current_epc_rating"] == "Epc.C"
] # ]
epc_c_movers["property_type"].value_counts() # epc_c_movers["property_type"].value_counts()
house_epc_c_movers = epc_c_movers[ # house_epc_c_movers = epc_c_movers[
epc_c_movers["property_type"] == "House" # epc_c_movers["property_type"] == "House"
] # ]
house_epc_c_movers_with_solar = house_epc_c_movers[ # house_epc_c_movers_with_solar = house_epc_c_movers[
~pd.isnull(house_epc_c_movers["solar_pv"]) | ~pd.isnull(house_epc_c_movers["solar_pv_with_battery"]) # ~pd.isnull(house_epc_c_movers["solar_pv"]) | ~pd.isnull(house_epc_c_movers["solar_pv_with_battery"])
] # ]
house_epc_c_movers_with_a_heatpump = house_epc_c_movers[ # house_epc_c_movers_with_a_heatpump = house_epc_c_movers[
~pd.isnull(house_epc_c_movers["air_source_heat_pump"]) # ~pd.isnull(house_epc_c_movers["air_source_heat_pump"])
] # ]
flat_epc_c_movers = epc_c_movers[ # flat_epc_c_movers = epc_c_movers[
epc_c_movers["property_type"] == "Flat" # epc_c_movers["property_type"] == "Flat"
] # ]
epc_c_recommendations["sap_points"].mean() # epc_c_recommendations["sap_points"].mean()
epc_c_recommendations["sap_points"].mean() # epc_c_recommendations["sap_points"].mean()
measure_cols = [ # measure_cols = [
"air_source_heat_pump", # "air_source_heat_pump",
"boiler_upgrade", # "boiler_upgrade",
"cavity_wall_insulation", # "cavity_wall_insulation",
"double_glazing", # "double_glazing",
"external_wall_insulation", # "external_wall_insulation",
"flat_roof_insulation", # "flat_roof_insulation",
"high_heat_retention_storage_heaters", # "high_heat_retention_storage_heaters",
"internal_wall_insulation", # "internal_wall_insulation",
"loft_insulation", # "loft_insulation",
"low_energy_lighting", # "low_energy_lighting",
"mechanical_ventilation", # "mechanical_ventilation",
"room_roof_insulation", # "room_roof_insulation",
"roomstat_programmer_trvs", # "roomstat_programmer_trvs",
"sealing_open_fireplace", # "sealing_open_fireplace",
"secondary_glazing", # "secondary_glazing",
"secondary_heating", # "secondary_heating",
"solar_pv", # "solar_pv",
"solar_pv_with_battery", # "solar_pv_with_battery",
"suspended_floor_insulation", # "suspended_floor_insulation",
"time_temperature_zone_control", # "time_temperature_zone_control",
] # ]
epc_c_melted = ( # epc_c_melted = (
epc_c_recommendations # epc_c_recommendations
.melt( # .melt(
id_vars=[c for c in epc_c_recommendations.columns if c not in measure_cols], # id_vars=[c for c in epc_c_recommendations.columns if c not in measure_cols],
value_vars=measure_cols, # value_vars=measure_cols,
var_name="measure_type", # var_name="measure_type",
value_name="value", # value_name="value",
) # )
.dropna(subset=["value"]) # .dropna(subset=["value"])
) # )
epc_c_melted = epc_c_melted[epc_c_melted["value"] > 0] # epc_c_melted = epc_c_melted[epc_c_melted["value"] > 0]
epc_c_measures = epc_c_melted["measure_type"].value_counts(normalize=True).to_frame().reset_index() # epc_c_measures = epc_c_melted["measure_type"].value_counts(normalize=True).to_frame().reset_index()
epc_b_melted = ( # epc_b_melted = (
epc_b_recommendations # epc_b_recommendations
.melt( # .melt(
id_vars=[c for c in epc_b_recommendations.columns if c not in measure_cols], # id_vars=[c for c in epc_b_recommendations.columns if c not in measure_cols],
value_vars=measure_cols, # value_vars=measure_cols,
var_name="measure_type", # var_name="measure_type",
value_name="value", # value_name="value",
) # )
.dropna(subset=["value"]) # .dropna(subset=["value"])
) # )
epc_b_melted = epc_b_melted[epc_b_melted["value"] > 0] # epc_b_melted = epc_b_melted[epc_b_melted["value"] > 0]
epc_b_measures = epc_b_melted["measure_type"].value_counts(normalize=True).to_frame().reset_index() # epc_b_measures = epc_b_melted["measure_type"].value_counts(normalize=True).to_frame().reset_index()
measures_compared = epc_c_measures.merge( # measures_compared = epc_c_measures.merge(
epc_b_measures, # epc_b_measures,
left_on="measure_type", # left_on="measure_type",
right_on="measure_type", # right_on="measure_type",
suffixes=("_epc_c", "_epc_b"), # suffixes=("_epc_c", "_epc_b"),
) # )
epc_c_retrofits = epc_c_recommendations[ # epc_c_retrofits = epc_c_recommendations[
epc_c_recommendations["total_retrofit_cost"] > 0 # epc_c_recommendations["total_retrofit_cost"] > 0
] # ]
epc_b_retrofits = epc_b_recommendations[ # epc_b_retrofits = epc_b_recommendations[
epc_b_recommendations["total_retrofit_cost"] > 0 # epc_b_recommendations["total_retrofit_cost"] > 0
] # ]
epc_c_retrofits["sap_points"].mean() # epc_c_retrofits["sap_points"].mean()
epc_b_retrofits["sap_points"].mean() # epc_b_retrofits["sap_points"].mean()
properties_in_both = epc_c_retrofits.merge(epc_b_retrofits, on="uprn", suffixes=("_epc_c", "_epc_b")) # properties_in_both = epc_c_retrofits.merge(epc_b_retrofits, on="uprn", suffixes=("_epc_c", "_epc_b"))
properties_in_both["total_retrofit_cost_epc_c"].mean() # properties_in_both["total_retrofit_cost_epc_c"].mean()
properties_in_both["sap_points_epc_c"].mean() # properties_in_both["sap_points_epc_c"].mean()
properties_in_both["total_retrofit_cost_epc_b"].mean() # properties_in_both["total_retrofit_cost_epc_b"].mean()
properties_in_both["sap_points_epc_b"].mean() # properties_in_both["sap_points_epc_b"].mean()
# Solar PV savings - we need the amount of solar PV bill savings # Solar PV savings - we need the amount of solar PV bill savings
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
@ -114,14 +114,12 @@ from backend.app.db.models.recommendations import Recommendation, Plan, PlanReco
from backend.app.db.models.portfolio import PropertyModel, PropertyDetailsEpcModel from backend.app.db.models.portfolio import PropertyModel, PropertyDetailsEpcModel
from collections import defaultdict from collections import defaultdict
PORTFOLIO_ID = 434 # Peabody PORTFOLIO_ID = 485 # Peabody
SCENARIOS = [ SCENARIOS = [
904, 970
905
] ]
scenario_names = { scenario_names = {
904: "EPC C - no solid floor, ashp 3.0", 970: "EPC C - no solid floor, ashp 3.0",
905: "EPC B - no solid floor, ashp 3.0",
} }
@ -233,259 +231,266 @@ properties_data, plans_data, recommendations_data = get_data(
recommendations_df = pd.DataFrame(recommendations_data) recommendations_df = pd.DataFrame(recommendations_data)
properties_df = pd.DataFrame(properties_data) properties_df = pd.DataFrame(properties_data)
solar_pv_recommendations = recommendations_df[recommendations_df["measure_type"] == "solar_pv"] with pd.ExcelWriter("hackney.xlsx", engine="openpyxl") as writer:
average_savings = solar_pv_recommendations.groupby("scenario_id")["energy_cost_savings"].mean().reset_index() recommendations_df.to_excel(writer, sheet_name="recommendations", index=False)
properties_df.to_excel(writer, sheet_name="properties", index=False)
# Check tenures
initial_asset_data = pd.read_excel( # solar_pv_recommendations = recommendations_df[recommendations_df["measure_type"] == "solar_pv"]
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody " # average_savings = solar_pv_recommendations.groupby("scenario_id")["energy_cost_savings"].mean().reset_index()
"- Data Extracts for Domna.xlsx",
sheet_name="Properties"
)
sustainability_data = pd.read_excel(
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody "
"- Data Extracts for Domna.xlsx",
sheet_name="Sustainability"
)
sustainability_sample = sustainability_data[
sustainability_data["UPRN"].isin(properties_df["uprn"].astype(int).astype(str).values)
]
sustainability_sample = sustainability_sample.merge(
initial_asset_data, left_on="Org Ref", right_on="UPRN", suffixes=("_sustainability", "_initial_asset")
)
block_sizes = initial_asset_data["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False) # # Check tenures
block_sizes.to_excel("/Users/khalimconn-kowlessar/Downloads/peabody_block_sizes.xlsx", index=False) # initial_asset_data = pd.read_excel(
# "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody "
# "- Data Extracts for Domna.xlsx",
# sheet_name="Properties"
# )
# sustainability_data = pd.read_excel(
# "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody "
# "- Data Extracts for Domna.xlsx",
# sheet_name="Sustainability"
# )
initial_asset_data.columns # sustainability_sample = sustainability_data[
initial_asset_data["LeaseType"].value_counts() # sustainability_data["UPRN"].isin(properties_df["uprn"].astype(int).astype(str).values)
# ]
# sustainability_sample["Tenure Group"].value_counts() # sustainability_sample = sustainability_sample.merge(
# Tenure Group # initial_asset_data, left_on="Org Ref", right_on="UPRN", suffixes=("_sustainability", "_initial_asset")
# General Needs 57787 # )
# Home Ownership 25471
# Care & Supported Housing 4239
# Rental 2677
# Other 188
df = sustainability_sample["Ownership Type"].value_counts().to_frame().reset_index() # block_sizes = initial_asset_data["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False)
df.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenures.xlsx", index=False) # block_sizes.to_excel("/Users/khalimconn-kowlessar/Downloads/peabody_block_sizes.xlsx", index=False)
tenure_groups = sustainability_sample["Tenure Group"].value_counts().to_frame().reset_index() # initial_asset_data.columns
tenure_groups.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenure_groups.xlsx", index=False) # initial_asset_data["LeaseType"].value_counts()
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Tenure Group"].value_counts() # # sustainability_sample["Tenure Group"].value_counts()
# # Tenure Group
# # General Needs 57787
# # Home Ownership 25471
# # Care & Supported Housing 4239
# # Rental 2677
# # Other 188
sample_data = initial_asset_data[ # df = sustainability_sample["Ownership Type"].value_counts().to_frame().reset_index()
~initial_asset_data["Ownership Type"].isin( # df.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenures.xlsx", index=False)
[
# Commercial # Everything is resi - based on the Residential Indicator variable - all are true
# Freeholder
"FREEHOLDER", # 19517 properties
# HOMEBUY / EQUITY LOAN
"Rent to Homebuy", # 1 property
# Leaseholder
"LEASEHOLD 100%", # 8455 properties
"Owned and Managed - 999 year lease", # 2076 properties
"Managed but not Owned-Private Lease", # 159 properties
"Owned and managed LEASEHOLD", # 26 properties
# Outright Sale - can't find anything matching
# SHARED EQUITY
"Shared Ownership", # 4065 properties
"Shared Ownership Owned Not Managed", # 23 properties
# Extra categories which seem sensible to exclude
"NOT MANAGED AND NOT OWNED"
]
)
]
sample_data["Ownership Type"].value_counts() # tenure_groups = sustainability_sample["Tenure Group"].value_counts().to_frame().reset_index()
# tenure_groups.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenure_groups.xlsx", index=False)
sample_data = initial_asset_data[ # initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Tenure Group"].value_counts()
initial_asset_data["Ownership Type"].isin(
[
"Owned and Managed",
"Owned and Managed - 999 year lease",
"Owned and managed LEASEHOLD",
"LEASEHOLD 100%",
"DATALOAD DEFAULT"
]
)
]
dropped = initial_asset_data[~initial_asset_data["UPRN"].isin(sample_data["UPRN"].values)]
dropped["Ownership Type"].value_counts()
for value in [ # sample_data = initial_asset_data[
# Commercial # Everything is resi, so should be fine. No matches # ~initial_asset_data["Ownership Type"].isin(
# Freeholder # [
"FREEHOLDER", # 19517 properties # # Commercial # Everything is resi - based on the Residential Indicator variable - all are true
# HOMEBUY / EQUITY LOAN # # Freeholder
"Rent to Homebuy", # 1 property # "FREEHOLDER", # 19517 properties
# Leaseholder # # HOMEBUY / EQUITY LOAN
"LEASEHOLD 100%", # 8455 properties # "Rent to Homebuy", # 1 property
"Owned and Managed - 999 year lease", # 2076 properties # # Leaseholder
"Managed but not Owned-Private Lease", # 159 properties # "LEASEHOLD 100%", # 8455 properties
"Owned and managed LEASEHOLD", # 26 properties # "Owned and Managed - 999 year lease", # 2076 properties
# Outright Sale - can't find anything matching # "Managed but not Owned-Private Lease", # 159 properties
# SHARED EQUITY # "Owned and managed LEASEHOLD", # 26 properties
"Shared Ownership", # 4065 properties # # Outright Sale - can't find anything matching
"Shared Ownership Owned Not Managed", # 23 properties # # SHARED EQUITY
]: # "Shared Ownership", # 4065 properties
print(initial_asset_data[initial_asset_data["Ownership Type"] == value].shape[0]) # "Shared Ownership Owned Not Managed", # 23 properties
# # Extra categories which seem sensible to exclude
# "NOT MANAGED AND NOT OWNED"
# ]
# )
# ]
house_types = [ # sample_data["Ownership Type"].value_counts()
"HOUSE",
"BUNGALOW",
"MAISONETTE",
"DUPLEX",
]
guaranteed_control = [ # sample_data = initial_asset_data[
"Owned and Managed", # initial_asset_data["Ownership Type"].isin(
"Owned and Managed - 999 year lease", # [
"Owned and managed LEASEHOLD", # "Owned and Managed",
"LEASEHOLD 100%", # "Owned and Managed - 999 year lease",
"DATALOAD DEFAULT", # "Owned and managed LEASEHOLD",
] # "LEASEHOLD 100%",
# "DATALOAD DEFAULT"
# ]
# )
# ]
# dropped = initial_asset_data[~initial_asset_data["UPRN"].isin(sample_data["UPRN"].values)]
# dropped["Ownership Type"].value_counts()
sample_data = initial_asset_data[ # for value in [
( # # Commercial # Everything is resi, so should be fine. No matches
initial_asset_data["Ownership Type"].isin(guaranteed_control) # # Freeholder
) # "FREEHOLDER", # 19517 properties
| # # HOMEBUY / EQUITY LOAN
( # "Rent to Homebuy", # 1 property
(initial_asset_data["Ownership Type"] == "FREEHOLDER") # # Leaseholder
& # "LEASEHOLD 100%", # 8455 properties
(initial_asset_data["Property Type"].isin(house_types)) # "Owned and Managed - 999 year lease", # 2076 properties
) # "Managed but not Owned-Private Lease", # 159 properties
] # "Owned and managed LEASEHOLD", # 26 properties
# # Outright Sale - can't find anything matching
# # SHARED EQUITY
# "Shared Ownership", # 4065 properties
# "Shared Ownership Owned Not Managed", # 23 properties
# ]:
# print(initial_asset_data[initial_asset_data["Ownership Type"] == value].shape[0])
fabric_retrofit_sample = initial_asset_data[ # house_types = [
initial_asset_data["Ownership Type"].isin( # "HOUSE",
[ # "BUNGALOW",
"Owned and Managed", # "MAISONETTE",
"FREEHOLDER", # "DUPLEX",
"DATALOAD DEFAULT", # ]
]
)
]
initial_asset_data[pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts() # guaranteed_control = [
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts() # "Owned and Managed",
# "Owned and Managed - 999 year lease",
# "Owned and managed LEASEHOLD",
# "LEASEHOLD 100%",
# "DATALOAD DEFAULT",
# ]
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Property Type"].value_counts() # sample_data = initial_asset_data[
z = initial_asset_data[ # (
~pd.isnull(initial_asset_data["BlockCode"]) & initial_asset_data["Property Type"].isin(house_types) # initial_asset_data["Ownership Type"].isin(guaranteed_control)
] # )
# |
# (
# (initial_asset_data["Ownership Type"] == "FREEHOLDER")
# &
# (initial_asset_data["Property Type"].isin(house_types))
# )
# ]
block_code_agg = z["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False) # fabric_retrofit_sample = initial_asset_data[
zz = initial_asset_data[initial_asset_data["BlockCode"] == "CHAT3343FM"] # initial_asset_data["Ownership Type"].isin(
# [
# "Owned and Managed",
# "FREEHOLDER",
# "DATALOAD DEFAULT",
# ]
# )
# ]
potential_sample = initial_asset_data[ # initial_asset_data[pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts()
~pd.isnull(initial_asset_data["BlockCode"]) # initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts()
]
compare = potential_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge( # initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Property Type"].value_counts()
initial_asset_data["Property Type"].value_counts(normalize=True).to_frame().reset_index(), # z = initial_asset_data[
left_on="Property Type", # ~pd.isnull(initial_asset_data["BlockCode"]) & initial_asset_data["Property Type"].isin(house_types)
right_on="Property Type", # ]
suffixes=("_on_block_codes", "_overall")
)
# Comparison of smaller sample vs overall # block_code_agg = z["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False)
new_asset_data = pd.read_excel( # zz = initial_asset_data[initial_asset_data["BlockCode"] == "CHAT3343FM"]
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/2025_11_11 "
"- Peabody "
"- Data Extracts for Domna v2.xlsx",
sheet_name="Properties"
)
new_sustainability_data = pd.read_excel( # potential_sample = initial_asset_data[
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/2025_11_11 " # ~pd.isnull(initial_asset_data["BlockCode"])
"- Peabody " # ]
"- Data Extracts for Domna v2.xlsx",
sheet_name="Sustainability"
)
sap_bands = pd.read_excel( # compare = potential_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge(
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/Parity Data " # initial_asset_data["Property Type"].value_counts(normalize=True).to_frame().reset_index(),
"08012026.xlsx", # left_on="Property Type",
) # right_on="Property Type",
# suffixes=("_on_block_codes", "_overall")
# )
combined = new_asset_data.merge( # # Comparison of smaller sample vs overall
new_sustainability_data, # new_asset_data = pd.read_excel(
left_on="UPRN", # "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/2025_11_11 "
right_on="Org Ref", # "- Peabody "
suffixes=("_asset", "_sustainability") # "- Data Extracts for Domna v2.xlsx",
).merge( # sheet_name="Properties"
sap_bands[["OrgRef", "SAP Band", "Lodged EPC Band"]], how="left", left_on="Org Ref", right_on="OrgRef" # )
)
reduced_sample = combined[
~combined["AH Tenure"].isin(
["Commercial",
"Freeholder",
"HOMEBUY / EQUITY LOAN",
"Leaseholder",
"Outright Sale",
"SHARED EQUITY",
"Shared Ownership"]
)
].copy()
# property types # new_sustainability_data = pd.read_excel(
property_type_comparison = reduced_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge( # "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/2025_11_11 "
combined["Property Type"].value_counts(normalize=True).to_frame().reset_index(), # "- Peabody "
left_on="Property Type", # "- Data Extracts for Domna v2.xlsx",
right_on="Property Type", # sheet_name="Sustainability"
suffixes=("_reduced_sample", "_overall") # )
)
# lodged ratings # sap_bands = pd.read_excel(
lodged_epc_band_comparison = reduced_sample["Lodged EPC Band"].value_counts( # "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/Parity Data "
normalize=True).to_frame().reset_index().merge( # "08012026.xlsx",
combined["Lodged EPC Band"].value_counts(normalize=True).to_frame().reset_index(), # )
left_on="Lodged EPC Band",
right_on="Lodged EPC Band",
suffixes=("_reduced_sample", "_overall")
)
# modelled ratings # combined = new_asset_data.merge(
modelled_epc_band_comparison = reduced_sample["SAP Band"].value_counts( # new_sustainability_data,
normalize=True).to_frame().reset_index().merge( # left_on="UPRN",
combined["SAP Band"].value_counts(normalize=True).to_frame().reset_index(), # right_on="Org Ref",
left_on="SAP Band", # suffixes=("_asset", "_sustainability")
right_on="SAP Band", # ).merge(
suffixes=("_reduced_sample", "_overall") # sap_bands[["OrgRef", "SAP Band", "Lodged EPC Band"]], how="left", left_on="Org Ref", right_on="OrgRef"
) # )
# reduced_sample = combined[
# ~combined["AH Tenure"].isin(
# ["Commercial",
# "Freeholder",
# "HOMEBUY / EQUITY LOAN",
# "Leaseholder",
# "Outright Sale",
# "SHARED EQUITY",
# "Shared Ownership"]
# )
# ].copy()
# Testing measures # # property types
m1 = pd.read_excel( # property_type_comparison = reduced_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge(
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no " # combined["Property Type"].value_counts(normalize=True).to_frame().reset_index(),
"solid floor, ashp 3.0 - 20250113 final.xlsx" # left_on="Property Type",
) # right_on="Property Type",
m2 = pd.read_excel( # suffixes=("_reduced_sample", "_overall")
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no " # )
"solid floor, no EWI or IWI, ashp 3.0 - 20250113 final.xlsx"
)
compare = m1.merge( # # lodged ratings
m2, # lodged_epc_band_comparison = reduced_sample["Lodged EPC Band"].value_counts(
left_on="uprn", # normalize=True).to_frame().reset_index().merge(
right_on="uprn", # combined["Lodged EPC Band"].value_counts(normalize=True).to_frame().reset_index(),
suffixes=("_ewi_iwi", "_no_ewi_iwi") # left_on="Lodged EPC Band",
) # right_on="Lodged EPC Band",
# suffixes=("_reduced_sample", "_overall")
# )
# Which properties get done under the no EWI/IWI scenario that do not under the EWI/IWI scenario # # modelled ratings
only_no_ewi_iwi = compare[ # modelled_epc_band_comparison = reduced_sample["SAP Band"].value_counts(
(compare["total_retrofit_cost_ewi_iwi"] == 0) & # normalize=True).to_frame().reset_index().merge(
(compare["total_retrofit_cost_no_ewi_iwi"] != 0) # combined["SAP Band"].value_counts(normalize=True).to_frame().reset_index(),
] # left_on="SAP Band",
# right_on="SAP Band",
# suffixes=("_reduced_sample", "_overall")
# )
(m1["total_retrofit_cost"] > 0).sum() # # Testing measures
(m2["total_retrofit_cost"] > 0).sum() # m1 = pd.read_excel(
# "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no "
# "solid floor, ashp 3.0 - 20250113 final.xlsx"
# )
# m2 = pd.read_excel(
# "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no "
# "solid floor, no EWI or IWI, ashp 3.0 - 20250113 final.xlsx"
# )
with_ewi_projects = compare[compare["total_retrofit_cost_no_ewi_iwi"] > 0] # compare = m1.merge(
# m2,
# left_on="uprn",
# right_on="uprn",
# suffixes=("_ewi_iwi", "_no_ewi_iwi")
# )
z = with_ewi_projects[pd.isnull(with_ewi_projects["total_retrofit_cost_ewi_iwi"])] # # Which properties get done under the no EWI/IWI scenario that do not under the EWI/IWI scenario
# only_no_ewi_iwi = compare[
# (compare["total_retrofit_cost_ewi_iwi"] == 0) &
# (compare["total_retrofit_cost_no_ewi_iwi"] != 0)
# ]
# (m1["total_retrofit_cost"] > 0).sum()
# (m2["total_retrofit_cost"] > 0).sum()
# with_ewi_projects = compare[compare["total_retrofit_cost_no_ewi_iwi"] > 0]
# z = with_ewi_projects[pd.isnull(with_ewi_projects["total_retrofit_cost_ewi_iwi"])]

View file

@ -14,16 +14,12 @@ from collections import defaultdict
# PORTFOLIO_ID = 206 # PORTFOLIO_ID = 206
# SCENARIOS = [389] # SCENARIOS = [389]
PORTFOLIO_ID = 435 # Peabody PORTFOLIO_ID = 485 # Peabody
SCENARIOS = [ SCENARIOS = [
908, 970,
909,
910,
] ]
scenario_names = { scenario_names = {
908: "EPC C - no solid floor, ashp 3.0", 970: "EPC C - Nosolid floor, EQI, IWI",
909: "EPC C - no solid floor, no EWI or IWI, ashp 3.0",
910: "EPC B - no solid floor, no EWI, ashp 3.0"
} }