mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
peabody
This commit is contained in:
parent
0254c945e8
commit
1acf4f4d6a
6 changed files with 340 additions and 328 deletions
|
|
@ -19,3 +19,4 @@ 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
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,4 @@ boto3==1.35.44
|
||||||
openpyxl==3.1.2
|
openpyxl==3.1.2
|
||||||
# Basic
|
# Basic
|
||||||
pytz
|
pytz
|
||||||
|
sqlmodel
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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(
|
|
||||||
"/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"
|
|
||||||
)
|
|
||||||
|
|
||||||
sustainability_sample = sustainability_data[
|
# solar_pv_recommendations = recommendations_df[recommendations_df["measure_type"] == "solar_pv"]
|
||||||
sustainability_data["UPRN"].isin(properties_df["uprn"].astype(int).astype(str).values)
|
# average_savings = solar_pv_recommendations.groupby("scenario_id")["energy_cost_savings"].mean().reset_index()
|
||||||
]
|
|
||||||
|
|
||||||
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)
|
|
||||||
block_sizes.to_excel("/Users/khalimconn-kowlessar/Downloads/peabody_block_sizes.xlsx", index=False)
|
|
||||||
|
|
||||||
initial_asset_data.columns
|
# # Check tenures
|
||||||
initial_asset_data["LeaseType"].value_counts()
|
# 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"
|
||||||
|
# )
|
||||||
|
|
||||||
# sustainability_sample["Tenure Group"].value_counts()
|
# sustainability_sample = sustainability_data[
|
||||||
# Tenure Group
|
# sustainability_data["UPRN"].isin(properties_df["uprn"].astype(int).astype(str).values)
|
||||||
# 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()
|
# sustainability_sample = sustainability_sample.merge(
|
||||||
df.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenures.xlsx", index=False)
|
# initial_asset_data, left_on="Org Ref", right_on="UPRN", suffixes=("_sustainability", "_initial_asset")
|
||||||
|
# )
|
||||||
|
|
||||||
tenure_groups = sustainability_sample["Tenure Group"].value_counts().to_frame().reset_index()
|
# block_sizes = initial_asset_data["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False)
|
||||||
tenure_groups.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenure_groups.xlsx", index=False)
|
# block_sizes.to_excel("/Users/khalimconn-kowlessar/Downloads/peabody_block_sizes.xlsx", index=False)
|
||||||
|
|
||||||
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Tenure Group"].value_counts()
|
# initial_asset_data.columns
|
||||||
|
# initial_asset_data["LeaseType"].value_counts()
|
||||||
|
|
||||||
sample_data = initial_asset_data[
|
# # sustainability_sample["Tenure Group"].value_counts()
|
||||||
~initial_asset_data["Ownership Type"].isin(
|
# # Tenure Group
|
||||||
[
|
# # General Needs 57787
|
||||||
# Commercial # Everything is resi - based on the Residential Indicator variable - all are true
|
# # Home Ownership 25471
|
||||||
# Freeholder
|
# # Care & Supported Housing 4239
|
||||||
"FREEHOLDER", # 19517 properties
|
# # Rental 2677
|
||||||
# HOMEBUY / EQUITY LOAN
|
# # Other 188
|
||||||
"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()
|
# df = sustainability_sample["Ownership Type"].value_counts().to_frame().reset_index()
|
||||||
|
# df.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenures.xlsx", index=False)
|
||||||
|
|
||||||
sample_data = initial_asset_data[
|
# tenure_groups = sustainability_sample["Tenure Group"].value_counts().to_frame().reset_index()
|
||||||
initial_asset_data["Ownership Type"].isin(
|
# tenure_groups.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenure_groups.xlsx", index=False)
|
||||||
[
|
|
||||||
"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 [
|
# initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Tenure Group"].value_counts()
|
||||||
# Commercial # Everything is resi, so should be fine. No matches
|
|
||||||
# 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
|
|
||||||
]:
|
|
||||||
print(initial_asset_data[initial_asset_data["Ownership Type"] == value].shape[0])
|
|
||||||
|
|
||||||
house_types = [
|
# sample_data = initial_asset_data[
|
||||||
"HOUSE",
|
# ~initial_asset_data["Ownership Type"].isin(
|
||||||
"BUNGALOW",
|
# [
|
||||||
"MAISONETTE",
|
# # Commercial # Everything is resi - based on the Residential Indicator variable - all are true
|
||||||
"DUPLEX",
|
# # 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"
|
||||||
|
# ]
|
||||||
|
# )
|
||||||
|
# ]
|
||||||
|
|
||||||
guaranteed_control = [
|
# sample_data["Ownership Type"].value_counts()
|
||||||
"Owned and Managed",
|
|
||||||
"Owned and Managed - 999 year lease",
|
|
||||||
"Owned and managed LEASEHOLD",
|
|
||||||
"LEASEHOLD 100%",
|
|
||||||
"DATALOAD DEFAULT",
|
|
||||||
]
|
|
||||||
|
|
||||||
sample_data = initial_asset_data[
|
# sample_data = initial_asset_data[
|
||||||
(
|
# initial_asset_data["Ownership Type"].isin(
|
||||||
initial_asset_data["Ownership Type"].isin(guaranteed_control)
|
# [
|
||||||
)
|
# "Owned and Managed",
|
||||||
|
|
# "Owned and Managed - 999 year lease",
|
||||||
(
|
# "Owned and managed LEASEHOLD",
|
||||||
(initial_asset_data["Ownership Type"] == "FREEHOLDER")
|
# "LEASEHOLD 100%",
|
||||||
&
|
# "DATALOAD DEFAULT"
|
||||||
(initial_asset_data["Property Type"].isin(house_types))
|
# ]
|
||||||
)
|
# )
|
||||||
]
|
# ]
|
||||||
|
# dropped = initial_asset_data[~initial_asset_data["UPRN"].isin(sample_data["UPRN"].values)]
|
||||||
|
# dropped["Ownership Type"].value_counts()
|
||||||
|
|
||||||
fabric_retrofit_sample = initial_asset_data[
|
# for value in [
|
||||||
initial_asset_data["Ownership Type"].isin(
|
# # Commercial # Everything is resi, so should be fine. No matches
|
||||||
[
|
# # Freeholder
|
||||||
"Owned and Managed",
|
# "FREEHOLDER", # 19517 properties
|
||||||
"FREEHOLDER",
|
# # HOMEBUY / EQUITY LOAN
|
||||||
"DATALOAD DEFAULT",
|
# "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
|
||||||
|
# ]:
|
||||||
|
# print(initial_asset_data[initial_asset_data["Ownership Type"] == value].shape[0])
|
||||||
|
|
||||||
initial_asset_data[pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts()
|
# house_types = [
|
||||||
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts()
|
# "HOUSE",
|
||||||
|
# "BUNGALOW",
|
||||||
|
# "MAISONETTE",
|
||||||
|
# "DUPLEX",
|
||||||
|
# ]
|
||||||
|
|
||||||
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Property Type"].value_counts()
|
# guaranteed_control = [
|
||||||
z = initial_asset_data[
|
# "Owned and Managed",
|
||||||
~pd.isnull(initial_asset_data["BlockCode"]) & initial_asset_data["Property Type"].isin(house_types)
|
# "Owned and Managed - 999 year lease",
|
||||||
]
|
# "Owned and managed LEASEHOLD",
|
||||||
|
# "LEASEHOLD 100%",
|
||||||
|
# "DATALOAD DEFAULT",
|
||||||
|
# ]
|
||||||
|
|
||||||
block_code_agg = z["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False)
|
# sample_data = initial_asset_data[
|
||||||
zz = initial_asset_data[initial_asset_data["BlockCode"] == "CHAT3343FM"]
|
# (
|
||||||
|
# initial_asset_data["Ownership Type"].isin(guaranteed_control)
|
||||||
|
# )
|
||||||
|
# |
|
||||||
|
# (
|
||||||
|
# (initial_asset_data["Ownership Type"] == "FREEHOLDER")
|
||||||
|
# &
|
||||||
|
# (initial_asset_data["Property Type"].isin(house_types))
|
||||||
|
# )
|
||||||
|
# ]
|
||||||
|
|
||||||
potential_sample = initial_asset_data[
|
# fabric_retrofit_sample = initial_asset_data[
|
||||||
~pd.isnull(initial_asset_data["BlockCode"])
|
# initial_asset_data["Ownership Type"].isin(
|
||||||
]
|
# [
|
||||||
|
# "Owned and Managed",
|
||||||
|
# "FREEHOLDER",
|
||||||
|
# "DATALOAD DEFAULT",
|
||||||
|
# ]
|
||||||
|
# )
|
||||||
|
# ]
|
||||||
|
|
||||||
compare = potential_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge(
|
# initial_asset_data[pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts()
|
||||||
initial_asset_data["Property Type"].value_counts(normalize=True).to_frame().reset_index(),
|
# initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Ownership Type"].value_counts()
|
||||||
left_on="Property Type",
|
|
||||||
right_on="Property Type",
|
|
||||||
suffixes=("_on_block_codes", "_overall")
|
|
||||||
)
|
|
||||||
|
|
||||||
# Comparison of smaller sample vs overall
|
# initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Property Type"].value_counts()
|
||||||
new_asset_data = pd.read_excel(
|
# z = 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"]) & initial_asset_data["Property Type"].isin(house_types)
|
||||||
"- Peabody "
|
# ]
|
||||||
"- Data Extracts for Domna v2.xlsx",
|
|
||||||
sheet_name="Properties"
|
|
||||||
)
|
|
||||||
|
|
||||||
new_sustainability_data = pd.read_excel(
|
# block_code_agg = z["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False)
|
||||||
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/2025_11_11 "
|
# zz = initial_asset_data[initial_asset_data["BlockCode"] == "CHAT3343FM"]
|
||||||
"- Peabody "
|
|
||||||
"- Data Extracts for Domna v2.xlsx",
|
|
||||||
sheet_name="Sustainability"
|
|
||||||
)
|
|
||||||
|
|
||||||
sap_bands = pd.read_excel(
|
# potential_sample = initial_asset_data[
|
||||||
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/Parity Data "
|
# ~pd.isnull(initial_asset_data["BlockCode"])
|
||||||
"08012026.xlsx",
|
# ]
|
||||||
)
|
|
||||||
|
|
||||||
combined = new_asset_data.merge(
|
# compare = potential_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge(
|
||||||
new_sustainability_data,
|
# initial_asset_data["Property Type"].value_counts(normalize=True).to_frame().reset_index(),
|
||||||
left_on="UPRN",
|
# left_on="Property Type",
|
||||||
right_on="Org Ref",
|
# right_on="Property Type",
|
||||||
suffixes=("_asset", "_sustainability")
|
# suffixes=("_on_block_codes", "_overall")
|
||||||
).merge(
|
# )
|
||||||
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
|
# # Comparison of smaller sample vs overall
|
||||||
property_type_comparison = reduced_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge(
|
# new_asset_data = pd.read_excel(
|
||||||
combined["Property Type"].value_counts(normalize=True).to_frame().reset_index(),
|
# "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/2025_11_11 "
|
||||||
left_on="Property Type",
|
# "- Peabody "
|
||||||
right_on="Property Type",
|
# "- Data Extracts for Domna v2.xlsx",
|
||||||
suffixes=("_reduced_sample", "_overall")
|
# sheet_name="Properties"
|
||||||
)
|
# )
|
||||||
|
|
||||||
# lodged ratings
|
# new_sustainability_data = 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/2025_11_11 "
|
||||||
normalize=True).to_frame().reset_index().merge(
|
# "- Peabody "
|
||||||
combined["Lodged EPC Band"].value_counts(normalize=True).to_frame().reset_index(),
|
# "- Data Extracts for Domna v2.xlsx",
|
||||||
left_on="Lodged EPC Band",
|
# sheet_name="Sustainability"
|
||||||
right_on="Lodged EPC Band",
|
# )
|
||||||
suffixes=("_reduced_sample", "_overall")
|
|
||||||
)
|
|
||||||
|
|
||||||
# modelled ratings
|
# sap_bands = pd.read_excel(
|
||||||
modelled_epc_band_comparison = reduced_sample["SAP 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["SAP Band"].value_counts(normalize=True).to_frame().reset_index(),
|
# )
|
||||||
left_on="SAP Band",
|
|
||||||
right_on="SAP Band",
|
|
||||||
suffixes=("_reduced_sample", "_overall")
|
|
||||||
)
|
|
||||||
|
|
||||||
# Testing measures
|
# combined = new_asset_data.merge(
|
||||||
m1 = pd.read_excel(
|
# new_sustainability_data,
|
||||||
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no "
|
# left_on="UPRN",
|
||||||
"solid floor, ashp 3.0 - 20250113 final.xlsx"
|
# right_on="Org Ref",
|
||||||
)
|
# suffixes=("_asset", "_sustainability")
|
||||||
m2 = pd.read_excel(
|
# ).merge(
|
||||||
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/Final SAL/EPC C - no "
|
# sap_bands[["OrgRef", "SAP Band", "Lodged EPC Band"]], how="left", left_on="Org Ref", right_on="OrgRef"
|
||||||
"solid floor, no EWI or IWI, ashp 3.0 - 20250113 final.xlsx"
|
# )
|
||||||
)
|
# reduced_sample = combined[
|
||||||
|
# ~combined["AH Tenure"].isin(
|
||||||
|
# ["Commercial",
|
||||||
|
# "Freeholder",
|
||||||
|
# "HOMEBUY / EQUITY LOAN",
|
||||||
|
# "Leaseholder",
|
||||||
|
# "Outright Sale",
|
||||||
|
# "SHARED EQUITY",
|
||||||
|
# "Shared Ownership"]
|
||||||
|
# )
|
||||||
|
# ].copy()
|
||||||
|
|
||||||
compare = m1.merge(
|
# # property types
|
||||||
m2,
|
# property_type_comparison = reduced_sample["Property Type"].value_counts(normalize=True).to_frame().reset_index().merge(
|
||||||
left_on="uprn",
|
# combined["Property Type"].value_counts(normalize=True).to_frame().reset_index(),
|
||||||
right_on="uprn",
|
# left_on="Property Type",
|
||||||
suffixes=("_ewi_iwi", "_no_ewi_iwi")
|
# right_on="Property Type",
|
||||||
)
|
# suffixes=("_reduced_sample", "_overall")
|
||||||
|
# )
|
||||||
|
|
||||||
# Which properties get done under the no EWI/IWI scenario that do not under the EWI/IWI scenario
|
# # lodged ratings
|
||||||
only_no_ewi_iwi = compare[
|
# lodged_epc_band_comparison = reduced_sample["Lodged EPC 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["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")
|
||||||
|
# )
|
||||||
|
|
||||||
(m1["total_retrofit_cost"] > 0).sum()
|
# # modelled ratings
|
||||||
(m2["total_retrofit_cost"] > 0).sum()
|
# modelled_epc_band_comparison = reduced_sample["SAP Band"].value_counts(
|
||||||
|
# normalize=True).to_frame().reset_index().merge(
|
||||||
|
# combined["SAP Band"].value_counts(normalize=True).to_frame().reset_index(),
|
||||||
|
# left_on="SAP Band",
|
||||||
|
# right_on="SAP Band",
|
||||||
|
# suffixes=("_reduced_sample", "_overall")
|
||||||
|
# )
|
||||||
|
|
||||||
with_ewi_projects = compare[compare["total_retrofit_cost_no_ewi_iwi"] > 0]
|
# # Testing measures
|
||||||
|
# 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"
|
||||||
|
# )
|
||||||
|
|
||||||
z = with_ewi_projects[pd.isnull(with_ewi_projects["total_retrofit_cost_ewi_iwi"])]
|
# compare = m1.merge(
|
||||||
|
# m2,
|
||||||
|
# left_on="uprn",
|
||||||
|
# right_on="uprn",
|
||||||
|
# suffixes=("_ewi_iwi", "_no_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"])]
|
||||||
|
|
|
||||||
|
|
@ -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"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue