File size: 4,629 Bytes
71f1a78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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()