fixed bug in create_base_difference_epc_record

This commit is contained in:
Khalim Conn-Kowlessar 2026-03-12 14:17:57 +00:00
parent 12d1223f17
commit 5e3d522378
3 changed files with 106 additions and 167 deletions

View file

@ -3,6 +3,7 @@ import ast
from itertools import groupby
import pandas as pd
import numpy as np
from typing import Set
from datetime import datetime, timedelta
from etl.epc.Dataset import TrainingDataset
@ -55,12 +56,11 @@ class Property:
walls = None
windows = None
lighting = None
energy_source = None
spatial = None
base_difference_record = None
DATA_ANOMALY_MATCHES = DATA_ANOMALY_MATCHES
DATA_ANOMALY_MATCHES: Set = DATA_ANOMALY_MATCHES
# Surplus information, that can be provided as optional inputs, by a customer
n_bathrooms = None
@ -101,8 +101,7 @@ class Property:
self.address = address
self.postcode = postcode
self.old_data = self.epc_record.get("old_data")
self.property_dimensions = None
self.old_data = self.epc_record.old_data
# This is a list of measures that have already been installed in the property, typically found as a result
# of the non-invasive surveys. We reflect that this has been installed in the recommendations, but remove the
# cost and instead, provide a message that the measure has already been installed
@ -121,17 +120,17 @@ class Property:
self.valuation = property_valuation
self.uprn = uprn if uprn is not None else epc_record.get("uprn")
self.uprn_source = self.epc_record.get("uprn-source")
self.uprn = uprn if uprn is not None else epc_record.uprn
self.uprn_source = self.epc_record.uprn_source
self.full_sap_epc = self.epc_record.get("full_sap_epc")
self.full_sap_epc = self.epc_record.full_sap_epc
self.in_conservation_area, self.is_listed, self.is_heritage = None, None, None
self.restricted_measures = False
self.year_built = epc_record.get("year_built")
self.number_of_rooms = epc_record.get("number_habitable_rooms")
self.age_band = epc_record.get("age_band")
self.construction_age_band = epc_record.get("construction_age_band")
self.number_of_floors = epc_record.get("number_of_floors")
self.year_built = self.epc_record.year_built
self.number_of_rooms = epc_record.number_habitable_rooms
self.age_band = epc_record.age_band
self.construction_age_band = epc_record.construction_age_band
self.number_of_floors = epc_record.number_of_floors
self.perimeter = None
self.wall_type = None
self.floor_type = None
@ -141,61 +140,27 @@ class Property:
# when storing the energy, we'll also
self.energy = {
"primary_energy_consumption": epc_record.get("energy_consumption_current"),
"epc_co2_emissions": epc_record.get("co2_emissions_current"),
"primary_energy_consumption": epc_record.energy_consumption_current,
"epc_co2_emissions": epc_record.co2_emissions_current,
# These will be added in once we estimate the amount of emissions from appliances - using the carbon
# intensity of electricity
"appliances_co2_emissions": None,
"co2_emissions": None
}
self.ventilation = {
"ventilation": epc_record.get("mechanical_ventilation"),
}
self.solar_pv = {
"solar_pv": epc_record.get("photo_supply"),
}
self.solar_hot_water = {
"solar_hot_water": self.epc_record.get("solar_water_heating_flag"),
"solar_hot_water_boolean": self.epc_record.get("solar_water_heating_flag_bool"),
}
self.wind_turbine = {
"wind_turbine": self.epc_record.get("wind_turbine_count"),
}
self.number_of_open_fireplaces = {
"number_of_open_fireplaces": self.epc_record.get(
"number_open_fireplaces"
),
}
self.number_of_extensions = {
"number_of_extensions": self.epc_record.get("extension_count"),
}
self.number_of_storeys = {
"number_of_storeys": self.epc_record.get("flat_storey_count"),
}
self.heat_loss_corridor = {
"heat_loss_corridor": self.epc_record.get("heat_loss_corridor"),
"length": self.epc_record.get("unheated_corridor_length"),
"heat_loss_corridor_boolean": self.epc_record.get("heat_loss_corridor_bool"),
}
self.mains_gas = self.epc_record.get("mains_gas_flag")
self.floor_height = self.epc_record.get("floor_height")
self.mains_gas = self.epc_record.mains_gas_flag
self.floor_height = self.epc_record.floor_height
self.insulation_wall_area = None
self.floor_area = self.epc_record.get("total_floor_area")
self.floor_area = self.epc_record.total_floor_area
self.roof_area = None
self.insulation_floor_area = None
self.number_lighting_outlets = self.epc_record.get("fixed_lighting_outlets_count")
self.number_lighting_outlets = self.epc_record.fixed_lighting_outlets_count
self.floor_level = None
self.number_of_windows = None
self.windows_area = None
self.solar_pv_percentage = None
self.current_energy_consumption = None
self.current_energy_consumption_heating_hotwater = None
self.current_energy_bill = None
self.expected_energy_bill = None
self.heating_energy_source = None
self.hot_water_energy_source = None
self.recommendations_scoring_data = []
self.simulation_epcs = {}
@ -225,6 +190,12 @@ class Property:
# Ventilation
self.has_ventilation = self.identify_ventilation()
@staticmethod
def _safe_int(value: str | int | float | None) -> int | None:
if value in [None, ""]:
return None
return int(round(float(value) + 1e-5))
@classmethod
def extract_kwargs(cls, kwargs):
"""
@ -237,24 +208,24 @@ class Property:
# Note - none of this data is contained in an energy asssessment, but we should consider how this is done
# as we collect more data from the energy assessment
n_bathrooms = kwargs.get("n_bathrooms", None)
n_bathrooms = kwargs.get("n_bathrooms")
# We add on a small value to ensure that the number of bathrooms is rounded up, in case the value is 0.5
n_bathrooms = int(round(float(n_bathrooms) + 1e-5)) if n_bathrooms not in [None, ""] else None
n_bathrooms = cls._safe_int(n_bathrooms) if n_bathrooms not in [None, ""] else None
n_bedrooms = kwargs.get("n_bedrooms", None)
n_bedrooms = int(round(float(n_bedrooms) + 1e-5)) if n_bedrooms not in [None, ""] else None
n_bedrooms = kwargs.get("n_bedrooms")
n_bedrooms = cls._safe_int(n_bedrooms) if n_bedrooms not in [None, ""] else None
number_of_floors = kwargs.get("number_of_floors", None)
number_of_floors = int(round(float(number_of_floors) + 1e-5)) if number_of_floors not in [None, ""] else None
number_of_floors = kwargs.get("number_of_floors")
number_of_floors = cls._safe_int(number_of_floors) if number_of_floors not in [None, ""] else None
insulation_floor_area = kwargs.get("insulation_floor_area", None)
insulation_floor_area = kwargs.get("insulation_floor_area")
insulation_floor_area = float(insulation_floor_area) if insulation_floor_area not in [None, ""] else None
insulation_wall_area = kwargs.get("insulation_wall_area", None)
insulation_wall_area = kwargs.get("insulation_wall_area")
insulation_wall_area = float(insulation_wall_area) if insulation_wall_area not in [None, ""] else None
# We allow for the asset owner to provide us with total floor area, in the event of it being incorrect
floor_area = kwargs.get("floor_area", None)
floor_area = kwargs.get("floor_area")
floor_area = float(floor_area) if floor_area not in [None, ""] else None
return {
@ -283,14 +254,11 @@ class Property:
It will be the same starting and ending EPC, as we don't have the expected EPC yet
"""
fixed_data_col_names = MANDATORY_FIXED_FEATURES + LATEST_FIELD
fixed_data_col_names = [
x.lower().replace("_", "-") for x in fixed_data_col_names
]
fixed_data_col_names = [x.lower() for x in MANDATORY_FIXED_FEATURES + LATEST_FIELD]
fixed_data = {
k.replace("-", "_"): v
for k, v in self.data.items()
for k, v in vars(self.epc_record).items()
if k in fixed_data_col_names
}
@ -311,7 +279,7 @@ class Property:
# If we have variables that have been given to us by the landlord that we know are correct, whereas the EPC
# may not be, we use them
if self.owner_floor_area is not None:
if self.owner_floor_area:
self.base_difference_record.df["total_floor_area_ending"] = self.floor_area
self.base_difference_record.df["estimated_perimeter_ending"] = self.perimeter
@ -410,7 +378,7 @@ class Property:
self.recommendations_scoring_data.append(scoring_dict)
simulation_epc = self.epc_record.__dict__.copy()
simulation_epc = vars(self.epc_record).copy()
# Insert static values
simulation_epc["lodgement_date"] = simulation_lodgment_date
simulation_epc = {k.replace("_", "-"): v for k, v in simulation_epc.items()}
@ -487,7 +455,7 @@ class Property:
# CO₂ emissions per square metre floor area per year in kg/m². Since CO₂ emissions are in tonnes
# per year, we multiply by 1000 to get kg/m²
"co2-emiss-curr-per-floor-area": round(
1000 * (rec_impact["carbon"] / self.epc_record.get("total_floor_area"))
1000 * (rec_impact["carbon"] / self.epc_record.total_floor_area)
),
"co2-emissions-current": rec_impact["carbon"],
"current-energy-rating": sap_to_epc(rec_impact["sap"]),
@ -600,15 +568,16 @@ class Property:
for description, attribute in cleaned.items():
cleaner_cls = all_cleaner_map[description]
description_underscore = description.replace("-", "_")
if self.epc_record.get(description) in self.DATA_ANOMALY_MATCHES:
if getattr(self.epc_record, description_underscore) in self.DATA_ANOMALY_MATCHES:
if description == "lighting-description":
cleaner_cls = cleaner_cls("", averages=None)
else:
cleaner_cls = cleaner_cls("")
fill_dict = {
"original_description": self.epc_record.get(description),
"clean_description": self.epc_record.get(description),
"original_description": getattr(self.epc_record, description_underscore),
"clean_description": getattr(self.epc_record, description_underscore),
**cleaner_cls.process()
}
setattr(self, self.ATTRIBUTE_MAP[description], fill_dict)
@ -617,7 +586,7 @@ class Property:
attributes = [
x
for x in cleaned[description]
if x["original_description"] == self.epc_record.get(description)
if x["original_description"] == getattr(self.epc_record, description_underscore)
]
if len(attributes) > 1:
@ -628,11 +597,11 @@ class Property:
if len(attributes) == 0:
# We attempt to perform the clean on the fly
if description == "lighting-description":
cleaner_cls = cleaner_cls(self.epc_record.get(description), averages=None)
cleaner_cls = cleaner_cls(getattr(self.epc_record, description_underscore), averages=None)
else:
cleaner_cls = cleaner_cls(self.epc_record.get(description))
cleaner_cls = cleaner_cls(getattr(self.epc_record, description_underscore))
processed = {
"original_description": self.epc_record.get(description),
"original_description": getattr(self.epc_record, description_underscore),
"clean_description": cleaner_cls.description.replace(
"(assumed)", ""
)
@ -671,12 +640,12 @@ class Property:
# Today's costs
todays_lighting_cost = kwh_client.convert_cost_to_today(
original_cost=float(self.data["lighting-cost-current"]),
lodgement_date=pd.Timestamp(self.epc_record.get("lodgement_date")).tz_localize(None)
original_cost=float(self.epc_record.lighting_cost_current),
lodgement_date=pd.Timestamp(self.epc_record.lodgement_date).tz_localize(None)
)
# If we have the kwh figures, we don't need to predict them
condition_data = self.energy_assessment_condition_data.copy()
condition_data = self.energy_assessment_condition_data
heating_kwh_predictions = kwh_predictions["heating_kwh_predictions"]
hotwater_kwh_predictions = kwh_predictions["hotwater_kwh_predictions"]
@ -715,19 +684,13 @@ class Property:
}
# Sum up the adjusted kwh figures
self.current_energy_consumption = sum(list(unadjusted_kwh_estimates.values()))
self.current_energy_consumption = sum(unadjusted_kwh_estimates.values())
self.current_energy_consumption_heating_hotwater = (
unadjusted_kwh_estimates["heating"] + unadjusted_kwh_estimates["hot_water"]
)
self.energy_cost_estimates = {
"unadjusted": unadjusted_heating_costs,
# Don't think we need the EPC
# "epc": {
# "heating": float(self.data["heating-cost-current"]),
# "hot_water": float(self.data["hot-water-cost-current"]),
# "lighting": float(self.data["lighting-cost-current"]),
# }
}
self.energy_consumption_estimates = {
@ -787,7 +750,7 @@ class Property:
:return:
"""
current_sap_rating = float(self.data["current-energy-efficiency"])
current_sap_rating = float(self.epc_record.current_energy_efficiency)
if needs_rebaselining:
current_sap_rating += rebaselining_sap
@ -795,24 +758,24 @@ class Property:
property_data = {
"creation_status": "READY",
"uprn": int(self.data["uprn"]),
"uprn": int(self.epc_record.uprn),
"building_reference_number": (
int(self.data["building-reference-number"]) if
self.data["building-reference-number"] is not None else None
int(self.epc_record.building_reference_number) if
self.epc_record.building_reference_number is not None else None
),
"has_pre_condition_report": True,
"has_recommendations": True,
"property_type": self.data["property-type"],
"built_form": self.data["built-form"],
"local_authority": self.data["local-authority-label"],
"constituency": self.data["constituency-label"],
"property_type": self.epc_record.property_type,
"built_form": self.epc_record.built_form,
"local_authority": self.epc_record.local_authority_label,
"constituency": self.epc_record.constituency_label,
"number_of_rooms": self.number_of_rooms,
"year_built": self.year_built,
"tenure": self.data["tenure"],
"tenure": self.epc_record.tenure,
"current_epc_rating": current_epc_rating,
"current_sap_points": current_sap_rating,
"current_valuation": current_valuation,
"original_sap_points": self.data["current-energy-efficiency"],
"original_sap_points": self.epc_record.current_energy_efficiency,
"is_sap_points_adjusted_for_installed_measures": needs_rebaselining,
"installed_measures_sap_point_adjustment": rebaselining_sap,
}
@ -841,7 +804,7 @@ class Property:
raise ValueError("Current energy bill has not been set")
# IF we have a SAP05 overwrite, we pull out the relevant information
sap_05_overwritten = self.data.get("sap-05-overwritten", False)
sap_05_overwritten = self.epc_record.sap_05_overwritten
sap_05_score, sap_05_epc_rating = None, None
if sap_05_overwritten:
@ -854,7 +817,7 @@ class Property:
sap_05_score = int(newest_old_epc["current-energy-efficiency"])
sap_05_epc_rating = newest_old_epc["current-energy-rating"]
lodgement_date = self.data["lodgement-date"]
lodgement_date = self.epc_record.lodgement_date
# We check if the lodgement date is more than 10 years old
is_expired = self.epc_is_expired
@ -876,42 +839,42 @@ class Property:
"portfolio_id": portfolio_id,
"lodgement_date": datetime.fromisoformat(lodgement_date),
"is_expired": is_expired,
"full_address": self.data["address"],
"total_floor_area": float(self.data["total-floor-area"]),
"full_address": self.epc_record.address,
"total_floor_area": float(self.epc_record.total_floor_area),
"walls": self.walls["clean_description"],
"walls_rating": self._prepare_rating_field(self.data["walls-energy-eff"]),
"walls_rating": self._prepare_rating_field(self.epc_record.walls_energy_eff),
"roof": self.roof["clean_description"],
"roof_rating": self._prepare_rating_field(self.data["roof-energy-eff"]),
"roof_rating": self._prepare_rating_field(self.epc_record.roof_energy_eff),
"floor": self.floor["clean_description"],
"floor_rating": self._prepare_rating_field(self.data["floor-energy-eff"]),
"floor_rating": self._prepare_rating_field(self.epc_record.floor_energy_eff),
"windows": self.windows["clean_description"],
"windows_rating": self._prepare_rating_field(self.data["windows-energy-eff"]),
"windows_rating": self._prepare_rating_field(self.epc_record.windows_energy_eff),
"heating": self.main_heating["clean_description"],
"heating_rating": self._prepare_rating_field(self.data["mainheat-energy-eff"]),
"heating_rating": self._prepare_rating_field(self.epc_record.mainheat_energy_eff),
"heating_controls": self.main_heating_controls["clean_description"],
"heating_controls_rating": self._prepare_rating_field(self.data["mainheatc-energy-eff"]),
"heating_controls_rating": self._prepare_rating_field(self.epc_record.mainheatc_energy_eff),
"hot_water": self.hotwater["clean_description"],
"hot_water_rating": self._prepare_rating_field(self.data["hot-water-energy-eff"]),
"hot_water_rating": self._prepare_rating_field(self.epc_record.hot_water_energy_eff),
"lighting": self.lighting["clean_description"],
"lighting_rating": self._prepare_rating_field(self.data["lighting-energy-eff"]),
"lighting_rating": self._prepare_rating_field(self.epc_record.lighting_energy_eff),
"mainfuel": self.main_fuel["clean_description"],
"ventilation": self.ventilation["ventilation"],
"solar_pv": self.solar_pv["solar_pv"],
"solar_hot_water": self.solar_hot_water["solar_hot_water_boolean"],
"wind_turbine": self.wind_turbine["wind_turbine"],
"ventilation": self.epc_record.mechanical_ventilation,
"solar_pv": self.epc_record.photo_supply,
"solar_hot_water": self.epc_record.solar_water_heating_flag_bool,
"wind_turbine": self.epc_record.wind_turbine_count,
"floor_height": self.floor_height,
"heat_loss_corridor": self.heat_loss_corridor["heat_loss_corridor_boolean"],
"unheated_corridor_length": self.heat_loss_corridor["length"],
"number_of_open_fireplaces": self.number_of_open_fireplaces["number_of_open_fireplaces"],
"number_of_extensions": self.number_of_extensions["number_of_extensions"],
"number_of_storeys": self.number_of_storeys["number_of_storeys"],
"heat_loss_corridor": self.epc_record.heat_loss_corridor_bool,
"unheated_corridor_length": self.epc_record.unheated_corridor_length,
"number_of_open_fireplaces": self.epc_record.number_open_fireplaces,
"number_of_extensions": self.epc_record.extension_count,
"number_of_storeys": self.epc_record.flat_storey_count,
"mains_gas": self.mains_gas,
"energy_tariff": self.data["energy-tariff"],
"energy_tariff": self.epc_record.energy_tariff,
"primary_energy_consumption": primary_energy_consumption,
"co2_emissions": co2_emissions,
"current_energy_demand": current_kwh_demand, # This is kwh - naming is confusing
"current_energy_demand_heating_hotwater": current_kwh_heating_hotwater, # This is kwh
"estimated": self.data.get("estimated", False),
"estimated": self.epc_record.estimated,
# We indicate if we've overwritten a SAP 05 EPC
"sap_05_overwritten": sap_05_overwritten,
"sap_05_score": sap_05_score,
@ -974,7 +937,7 @@ class Property:
"""
result = property_dimensions[
(property_dimensions["PROPERTY_TYPE"] == self.data["property-type"])
(property_dimensions["PROPERTY_TYPE"] == self.epc_record.property_type)
]
if (
@ -986,10 +949,10 @@ class Property:
]
if (
self.data["built-form"] not in self.DATA_ANOMALY_MATCHES
and self.data["built-form"] in result["BUILT_FORM"]
self.epc_record.built_form not in self.DATA_ANOMALY_MATCHES
and self.epc_record.built_form in result["BUILT_FORM"]
):
result = result[(result["BUILT_FORM"] == self.data["built-form"])]
result = result[(result["BUILT_FORM"] == self.epc_record.built_form)]
return result[
["NUMBER_HABITABLE_ROOMS", "TOTAL_FLOOR_AREA", "FLOOR_HEIGHT"]
@ -1032,7 +995,7 @@ class Property:
num_floors=self.number_of_floors,
floor_height=self.floor_height,
perimeter=self.perimeter,
built_form=self.data["built-form"],
built_form=self.epc_record.built_form,
)
if self.insulation_floor_area is None:
@ -1051,15 +1014,15 @@ class Property:
def set_floor_level(self):
self.floor_level = (
FLOOR_LEVEL_MAP[self.data["floor-level"]]
if self.data["floor-level"] not in self.DATA_ANOMALY_MATCHES
and self.data["floor-level"] is not None
FLOOR_LEVEL_MAP[self.epc_record.floor_level]
if self.epc_record.floor_level not in self.DATA_ANOMALY_MATCHES
and self.epc_record.floor_level is not None
else None
)
if self.floor_level is None:
if self.data["property-type"] != "Flat":
if self.epc_record.property_type != "Flat":
return
if self.floor["another_property_below"]:
@ -1119,21 +1082,6 @@ class Property:
)
self.floor_type = "suspended"
@staticmethod
def _extract_component(
component_data, component_rename_cols, component_drop_cols, rename_prefix=None
):
for k in component_rename_cols:
component_data[f"{rename_prefix}_{k}"] = component_data.get(k)
component_data = {
k: v
for k, v in component_data.items()
if k not in component_drop_cols + component_rename_cols
}
return component_data
def set_windows_count(self):
"""
Using the estimate_windows function, this method will set the number of windows in the property
@ -1145,8 +1093,8 @@ class Property:
self.number_of_windows = int(condition_data["number_of_windows"]) \
if condition_data.get("number_of_windows") is not None \
else estimate_windows(
property_type=self.data["property-type"],
built_form=self.data["built-form"],
property_type=self.epc_record.property_type,
built_form=self.epc_record.built_form,
construction_age_band=self.construction_age_band,
floor_area=self.floor_area,
number_habitable_rooms=self.number_of_rooms,
@ -1166,14 +1114,14 @@ class Property:
# If we have a house over a floor area threshold, we recommend an ASHP
if (
self.data["property-type"] in ["House", "Bungalow"] and
self.epc_record.property_type in ["House", "Bungalow"] and
self.floor_area > assumptions.ASHP_FLOOR_AREA_THRESHOLD
):
return True
suitable_property_type = (
self.data["property-type"] in ["House", "Bungalow"] and
self.data["built-form"] not in ["Enclosed Mid-Terrace", "Enclosed End-Terrace"]
self.epc_record.property_type in ["House", "Bungalow"] and
self.epc_record.built_form not in ["Enclosed Mid-Terrace", "Enclosed End-Terrace"]
)
has_air_source_heat_pump = self.main_heating["has_air_source_heat_pump"]
@ -1195,12 +1143,12 @@ class Property:
# may be installed such that they are not visible from the street
return False
if (self.data["property-type"] in ["House", "Bungalow"]) and (
if (self.epc_record.property_type in ["House", "Bungalow"]) and (
not pd.isnull(self.roof["thermal_transmittance"])
):
return True
is_valid_property_type = self.data["property-type"] in ["House", "Bungalow", "Maisonette"]
is_valid_property_type = self.epc_record.property_type in ["House", "Bungalow", "Maisonette"]
is_valid_roof_type = (
self.roof["is_flat"] or self.roof["is_pitched"] or self.roof["is_roof_room"]
)
@ -1213,7 +1161,7 @@ class Property:
"already has solar pv", "roof too small", "no roof"
]
else:
has_no_existing_solar_pv = self.data["photo-supply"] in [
has_no_existing_solar_pv = self.epc_record.photo_supply in [
None, 0, self.DATA_ANOMALY_MATCHES
]
@ -1285,12 +1233,10 @@ class Property:
def identify_ventilation(self):
ventilation_descriptions = [
return self.epc_record.mechanical_ventilation in {
'mechanical, extract only',
'mechanical, supply and extract'
]
return self.epc_record.get("mechanical-ventilation") in ventilation_descriptions
}
@property
def epc_is_expired(self) -> bool:
@ -1299,7 +1245,7 @@ class Property:
valid for 10 years.
:return: boolean indicating whether the EPC is expired
"""
lodgement_date = self.epc_record.get("lodgement-date")
lodgement_date = self.epc_record.lodgement_date
return (datetime.now() - pd.to_datetime(lodgement_date)) > timedelta(days=3650)
@property
@ -1308,4 +1254,4 @@ class Property:
This property indicates that the EPC is estimated, based on the presence of the "estimated" flag in the data
:return: boolean indicating whether the EPC is estimated
"""
return self.epc_record.get("estimated")
return self.epc_record.estimated

View file

@ -813,19 +813,11 @@ async def model_engine(body: PlanTriggerRequest):
# 1) EPC expired
# 2) Missing EPC
# 3) Materially different information from landlord vs EPC
# make the landlord remapping dictionary
needs_rebaselining = p.epc_is_expired | p.epc_is_estimated | (len(differences) > 0)
p.epc_record.update(differences)
# make the landlord remapping dictionar
needs_rebaselining = p.epc_is_expired | p.epc_is_estimated | (len(p.epc_record.landlord_differences) > 0)
# Need to adjust p.data and p.epc_record.df?
if needs_rebaselining:
if len(differences):
# Insert into prepared_epc
for k, v in differences.items():
p.epc_record.prepared_epc[k] = v
p.create_base_difference_epc_record(cleaned_lookup=cleaned)
scoring_data = p.base_difference_record.df.copy()
rebaselining_scoring_data.append(scoring_data)

View file

@ -308,6 +308,7 @@ class EPCRecord:
# ------------------------------------------------------------------
# Indicates if the EPC record has been predicted. By default, false
estimated: Optional[bool] = False
sap_05_overwritten: Optional[bool] = False
# ------------------------------------------------------------------
# MODEL FLAGS