import gradio as gr from sklearn.ensemble import RandomForestRegressor import numpy as np import pandas as pd import pickle from geopy.geocoders import Nominatim from geopy.exc import GeocoderTimedOut from math import radians, cos, sin, asin, sqrt # Lade das Modell # TODO change the file to your own model. model_filename = "final_apartment_model.pkl" random_forest_model = RandomForestRegressor() with open(model_filename, 'rb') as f: random_forest_model = pickle.load(f) # Funktion zur Berechnung der Entfernung zwischen zwei Koordinatenpunkten def haversine(lon1, lat1, lon2, lat2): """ Berechnet die Entfernung in Kilometern zwischen zwei Punkten auf der Erde (anhand von Längen-/Breitengraden) """ lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 c = 2 * asin(sqrt(a)) return 6371 * c transport_hubs = [ ["Zürich HB", 47.3778, 8.5403], ["Zürich Stadelhofen", 47.3665, 8.5486], ["Zürich Oerlikon", 47.4111, 8.5438], ["Zürich Altstetten", 47.3911, 8.4889], ["Winterthur", 47.4996, 8.7241], ["Uster", 47.3474, 8.7201], ["Wetzikon", 47.3281, 8.7974], ["Dübendorf", 47.3973, 8.6186], ["Dietikon", 47.4051, 8.4012], ["Thalwil", 47.2916, 8.5641] ] def get_coordinates(address): """Holt die Koordinaten für eine gegebene Adresse""" try: geolocator = Nominatim(user_agent="my_apartment_predictor") if 'zürich' not in address.lower() and 'switzerland' not in address.lower(): address += ', Zürich, Switzerland' location = geolocator.geocode(address) if location: return location.latitude, location.longitude, location.address return None, None, None except GeocoderTimedOut: return None, None, None def get_nearest_transport_distance(lat, lon): """Berechnet die Distanz zum nächsten Verkehrsknotenpunkt""" distances = [] for hub in transport_hubs: hub_name, hub_lat, hub_lon = hub distance = haversine(lon, lat, hub_lon, hub_lat) distances.append(distance) return min(distances) # Lade die BFS-Daten df_bfs_data = pd.read_csv('bfs_municipality_and_tax_data.csv') # Bereinige die tax_income Spalte von Tausendertrennzeichen und konvertiere zu float df_bfs_data['tax_income'] = df_bfs_data['tax_income'].str.replace("'", "").astype(float) # Berechne Durchschnittswerte für die Features mean_values = { 'pop': df_bfs_data['pop'].mean(), 'pop_dens': df_bfs_data['pop_dens'].mean(), 'frg_pct': df_bfs_data['frg_pct'].mean(), 'emp': df_bfs_data['emp'].mean(), 'tax_income': df_bfs_data['tax_income'].mean() } def predict_apartment_price(rooms, area, address): """Vorhersage des Mietpreises basierend auf Zimmer, Fläche und Adresse""" # Hole Koordinaten für die Adresse lat, lon, full_address = get_coordinates(address) if lat is None or lon is None: return "Adresse konnte nicht gefunden werden. Bitte überprüfen Sie die Eingabe." # Berechne die Distanz zum nächsten Verkehrsknotenpunkt distance_to_transport = get_nearest_transport_distance(lat, lon) # Erstelle DataFrame für die Vorhersage mit den vorberechneten Durchschnittswerten prediction_data = pd.DataFrame({ 'rooms': [rooms], 'area': [area], 'pop': [mean_values['pop']], 'pop_dens': [mean_values['pop_dens']], 'frg_pct': [mean_values['frg_pct']], 'emp': [mean_values['emp']], 'tax_income': [mean_values['tax_income']], 'distance_to_transport': [distance_to_transport] }) # Mache die Vorhersage prediction = random_forest_model.predict(prediction_data) predicted_price = np.round(prediction[0], 0) return f"Geschätzter Mietpreis für {full_address}: CHF {predicted_price:.0f}\nEntfernung zum nächsten Verkehrsknotenpunkt: {distance_to_transport:.1f} km" iface = gr.Interface( fn=predict_apartment_price, inputs=[ gr.Number(label="Anzahl Zimmer"), gr.Number(label="Wohnfläche (m²)"), gr.Textbox(label="Adresse (z.B. Bahnhofstrasse 1, Zürich)") ], outputs=gr.Textbox(label="Vorhersage"), title="Mietpreis-Vorhersage", description="Geben Sie die Details der Wohnung ein, um den geschätzten Mietpreis zu erhalten.", examples=[ [4.5, 120, "Bahnhofstrasse 1, Zürich"], [3.5, 80, "Universitätstrasse 84, Zürich"], [2.5, 60, "Technikumstrasse 9, Winterthur"] ] ) iface.launch()