|
|
import os |
|
|
os.environ["PGEOCODE_CACHE_DIR"] = "/tmp/pgeocode" |
|
|
|
|
|
import streamlit as st |
|
|
import pandas as pd |
|
|
import joblib |
|
|
|
|
|
def create_dataframe_from_user_input(): |
|
|
""" |
|
|
Collects user input for house features using Streamlit and |
|
|
returns a Pandas DataFrame. The input fields are organized |
|
|
into categorized sections for better usability. |
|
|
""" |
|
|
|
|
|
|
|
|
type_list = ['HOUSE', 'APARTMENT'] |
|
|
subtype_list = ['HOUSE', 'APARTMENT', 'VILLA', 'APARTMENT_BLOCK', 'APARTMENT_GROUP', |
|
|
'MIXED_USE_BUILDING', 'GROUND_FLOOR', 'DUPLEX', 'HOUSE_GROUP', |
|
|
'FLAT_STUDIO', 'PENTHOUSE', 'EXCEPTIONAL_PROPERTY', 'MANSION', |
|
|
'TOWN_HOUSE', 'SERVICE_FLAT', 'BUNGALOW', 'KOT', 'COUNTRY_COTTAGE', |
|
|
'FARMHOUSE', 'LOFT', 'CHALET', 'TRIPLEX', 'CASTLE', 'OTHER_PROPERTY', |
|
|
'MANOR_HOUSE', 'PAVILION'] |
|
|
province_list = ['West Flanders', 'Antwerp', 'East Flanders', 'Brussels', 'Hainaut', |
|
|
'Liège', 'Flemish Brabant', 'Limburg', 'Walloon Brabant', 'Namur', |
|
|
'Luxembourg'] |
|
|
building_condition_list = ['GOOD', 'AS_NEW', 'TO_RENOVATE', 'TO_BE_DONE_UP', |
|
|
'JUST_RENOVATED', 'TO_RESTORE'] |
|
|
flood_zone_type_list = ['NON_FLOOD_ZONE', 'POSSIBLE_FLOOD_ZONE', 'RECOGNIZED_FLOOD_ZONE', |
|
|
'RECOGNIZED_N_CIRCUMSCRIBED_FLOOD_ZONE', 'CIRCUMSCRIBED_WATERSIDE_ZONE', |
|
|
'CIRCUMSCRIBED_FLOOD_ZONE', 'POSSIBLE_N_CIRCUMSCRIBED_FLOOD_ZONE', |
|
|
'POSSIBLE_N_CIRCUMSCRIBED_WATERSIDE_ZONE', 'RECOGNIZED_N_CIRCUMSCRIBED_WATERSIDE_ZONE'] |
|
|
heating_type_list = ['GAS', 'FUELOIL', 'ELECTRIC', 'PELLET', 'WOOD', 'SOLAR', 'CARBON'] |
|
|
kitchen_type_list = ['INSTALLED', 'HYPER_EQUIPPED', 'SEMI_EQUIPPED', 'NOT_INSTALLED', |
|
|
'USA_HYPER_EQUIPPED', 'USA_INSTALLED', 'USA_SEMI_EQUIPPED', |
|
|
'USA_UNINSTALLED'] |
|
|
garden_orientation_list = ['SOUTH', 'SOUTH_WEST', 'SOUTH_EAST', 'WEST', 'EAST', |
|
|
'NORTH_WEST', 'NORTH_EAST', 'NORTH'] |
|
|
terrace_orientation_list = ['SOUTH', 'SOUTH_WEST', 'SOUTH_EAST', 'WEST', 'EAST', |
|
|
'NORTH_WEST', 'NORTH_EAST', 'NORTH'] |
|
|
epc_score_list = ['B', 'C', 'D', 'A', 'F', 'E', 'G', 'A+', 'A++'] |
|
|
|
|
|
|
|
|
st.header("Enter House Information") |
|
|
|
|
|
|
|
|
st.subheader("Property Details") |
|
|
col1, col2 = st.columns(2) |
|
|
with col1: |
|
|
property_type = st.selectbox("Property Type", type_list, key='type') |
|
|
property_subtype = st.selectbox("Subtype", subtype_list, key='subtype') |
|
|
province = st.selectbox("Province", province_list, key='province') |
|
|
locality = st.text_input("Locality", key='locality') |
|
|
post_code = st.number_input("Post Code", min_value=1000, max_value=9999, step=1, key='postCode') |
|
|
with col2: |
|
|
building_condition = st.selectbox("Building Condition", building_condition_list, key='buildingCondition') |
|
|
building_construction_year = st.number_input("Building Construction Year", min_value=1000, max_value=2024, step=1, key='buildingConstructionYear') |
|
|
facade_count = st.number_input("Facade Count", min_value=0, step=1, key='facadeCount') |
|
|
floor_count = st.number_input("Floor Count", min_value=0, step=1, key='floorCount') |
|
|
flood_zone_type = st.selectbox("Flood Zone Type", flood_zone_type_list, key='floodZoneType') |
|
|
epc_score = st.selectbox("EPC Score", epc_score_list, key='epcScore') |
|
|
|
|
|
|
|
|
st.subheader("Room Information") |
|
|
col3, col4 = st.columns(2) |
|
|
with col3: |
|
|
bedroom_count = st.number_input("Bedroom Count", min_value=0, step=1, key='bedroomCount') |
|
|
bathroom_count = st.number_input("Bathroom Count", min_value=0, step=1, key='bathroomCount') |
|
|
room_count = st.number_input("Room Count", min_value=0, step=1, key='roomCount') |
|
|
has_attic = st.selectbox("Has Attic", ['Yes', 'No'], key='hasAttic') |
|
|
has_basement = st.selectbox("Has Basement", ['Yes', 'No'], key='hasBasement') |
|
|
has_dressing_room = st.selectbox("Has Dressing Room", ['Yes', 'No'], key='hasDressingRoom') |
|
|
has_dining_room = st.selectbox("Has Dining Room", ['Yes', 'No'], key='hasDiningRoom') |
|
|
dining_room_surface = st.number_input("Dining Room Surface (sqm)", min_value=0.0, key='diningRoomSurface') |
|
|
with col4: |
|
|
has_living_room = st.selectbox("Has Living Room", ['Yes', 'No'], key='hasLivingRoom') |
|
|
living_room_surface = st.number_input("Living Room Surface (sqm)", min_value=0.0, key='livingRoomSurface') |
|
|
kitchen_surface = st.number_input("Kitchen Surface (sqm)", min_value=0.0, key='kitchenSurface') |
|
|
kitchen_type = st.selectbox("Kitchen Type", kitchen_type_list, key='kitchenType') |
|
|
toilet_count = st.number_input("Toilet Count", min_value=0, step=1, key='toiletCount') |
|
|
has_office = st.selectbox("Has Office", ['Yes', 'No'], key='hasOffice') |
|
|
has_lift = st.selectbox("Has Lift", ['Yes', 'No'], key='hasLift') |
|
|
|
|
|
|
|
|
st.subheader("Surface Areas") |
|
|
col5, col6 = st.columns(2) |
|
|
with col5: |
|
|
habitable_surface = st.number_input("Habitable Surface (sqm)", min_value=0.0, key='habitableSurface') |
|
|
land_surface = st.number_input("Land Surface (sqm)", min_value=0.0, key='landSurface') |
|
|
garden_surface = st.number_input("Garden Surface (sqm)", min_value=0.0, key='gardenSurface') |
|
|
with col6: |
|
|
terrace_surface = st.number_input("Terrace Surface (sqm)", min_value=0.0, key='terraceSurface') |
|
|
street_facade_width = st.number_input("Street Facade Width (m)", min_value=0.0, key='streetFacadeWidth') |
|
|
monthly_cost = st.number_input("Monthly Cost (€)", min_value=0.0, key='monthlyCost') |
|
|
|
|
|
|
|
|
st.subheader("Outdoor Features") |
|
|
col7, col8 = st.columns(2) |
|
|
with col7: |
|
|
has_garden = st.selectbox("Has Garden", ['Yes', 'No'], key='hasGarden') |
|
|
garden_orientation = st.selectbox("Garden Orientation", garden_orientation_list, key='gardenOrientation') |
|
|
has_balcony = st.selectbox("Has Balcony", ['Yes', 'No'], key='hasBalcony') |
|
|
has_terrace = st.selectbox("Has Terrace", ['Yes', 'No'], key='hasTerrace') |
|
|
terrace_orientation = st.selectbox("Terrace Orientation", terrace_orientation_list, key='terraceOrientation') |
|
|
with col8: |
|
|
parking_count_indoor = st.number_input("Indoor Parking Count", min_value=0, step=1, key='parkingCountIndoor') |
|
|
parking_count_outdoor = st.number_input("Outdoor Parking Count", min_value=0, step=1, key='parkingCountOutdoor') |
|
|
has_swimming_pool = st.selectbox("Has Swimming Pool", ['Yes', 'No'], key='hasSwimmingPool') |
|
|
|
|
|
|
|
|
st.subheader("Additional Features") |
|
|
col9, col10 = st.columns(2) |
|
|
with col9: |
|
|
heating_type = st.selectbox("Heating Type", heating_type_list, key='heatingType') |
|
|
has_heat_pump = st.selectbox("Has Heat Pump", ['Yes', 'No'], key='hasHeatPump') |
|
|
has_photovoltaic_panels = st.selectbox("Has Photovoltaic Panels", ['Yes', 'No'], key='hasPhotovoltaicPanels') |
|
|
has_thermic_panels = st.selectbox("Has Thermic Panels", ['Yes', 'No'], key='hasThermicPanels') |
|
|
with col10: |
|
|
has_air_conditioning = st.selectbox("Has Air Conditioning", ['Yes', 'No'], key='hasAirConditioning') |
|
|
has_armored_door = st.selectbox("Has Armored Door", ['Yes', 'No'], key='hasArmoredDoor') |
|
|
has_visiophone = st.selectbox("Has Visiophone", ['Yes', 'No'], key='hasVisiophone') |
|
|
has_fireplace = st.selectbox("Has Fireplace", ['Yes', 'No'], key='hasFireplace') |
|
|
accessible_disabled_people = st.selectbox("Accessible Disabled People", ['True', 'False'], key='accessibleDisabledPeople') |
|
|
|
|
|
|
|
|
if st.button("Predict"): |
|
|
|
|
|
data = { |
|
|
'type': property_type, |
|
|
'subtype': property_subtype, |
|
|
'bedroomCount': bedroom_count, |
|
|
'bathroomCount': bathroom_count, |
|
|
'province': province, |
|
|
'locality': locality, |
|
|
'postCode': post_code, |
|
|
'habitableSurface': habitable_surface, |
|
|
'roomCount': room_count, |
|
|
'monthlyCost': monthly_cost, |
|
|
'hasAttic': has_attic == 'Yes', |
|
|
'hasBasement': has_basement == 'Yes', |
|
|
'hasDressingRoom': has_dressing_room == 'Yes', |
|
|
'diningRoomSurface': dining_room_surface, |
|
|
'hasDiningRoom': has_dining_room == 'Yes', |
|
|
'buildingCondition': building_condition, |
|
|
'buildingConstructionYear': building_construction_year, |
|
|
'facadeCount': facade_count, |
|
|
'floorCount': floor_count, |
|
|
'streetFacadeWidth': street_facade_width, |
|
|
'hasLift': has_lift == 'Yes', |
|
|
'floodZoneType': flood_zone_type, |
|
|
'heatingType': heating_type, |
|
|
'hasHeatPump': has_heat_pump == 'Yes', |
|
|
'hasPhotovoltaicPanels': has_photovoltaic_panels == 'Yes', |
|
|
'hasThermicPanels': has_thermic_panels == 'Yes', |
|
|
'kitchenSurface': kitchen_surface, |
|
|
'kitchenType': kitchen_type, |
|
|
'landSurface': land_surface, |
|
|
'hasLivingRoom': has_living_room == 'Yes', |
|
|
'livingRoomSurface': living_room_surface, |
|
|
'hasBalcony': has_balcony == 'Yes', |
|
|
'hasGarden': has_garden == 'Yes', |
|
|
'gardenSurface': garden_surface, |
|
|
'gardenOrientation': garden_orientation, |
|
|
'parkingCountIndoor': parking_count_indoor, |
|
|
'parkingCountOutdoor': parking_count_outdoor, |
|
|
'hasAirConditioning': has_air_conditioning == 'Yes', |
|
|
'hasArmoredDoor': has_armored_door == 'Yes', |
|
|
'hasVisiophone': has_visiophone == 'Yes', |
|
|
'hasOffice': has_office == 'Yes', |
|
|
'toiletCount': toilet_count, |
|
|
'hasSwimmingPool': has_swimming_pool == 'Yes', |
|
|
'hasFireplace': has_fireplace == 'Yes', |
|
|
'hasTerrace': has_terrace == 'Yes', |
|
|
'terraceSurface': terrace_surface, |
|
|
'terraceOrientation': terrace_orientation, |
|
|
'accessibleDisabledPeople': accessible_disabled_people == 'True', |
|
|
'epcScore': epc_score |
|
|
} |
|
|
df = pd.DataFrame(data, index=[0]) |
|
|
pipeline = joblib.load('saved/pipeline.pkl') |
|
|
model = joblib.load('saved/model.pkl') |
|
|
expected_columns = joblib.load('saved/columns.pkl') |
|
|
df_test = pipeline.transform(df) |
|
|
for col in expected_columns: |
|
|
if col not in df_test.columns: |
|
|
df_test[col] = 0 |
|
|
|
|
|
df_test = df_test[expected_columns] |
|
|
preds = model.predict(df_test) |
|
|
st.subheader("Price prediction") |
|
|
st.markdown(f"<h1 style='text-align: center; color: red;'>{preds[0]:.2f} €</h1>", unsafe_allow_html=True) |
|
|
return df |
|
|
|
|
|
if __name__ == "__main__": |
|
|
create_dataframe_from_user_input() |
|
|
|