Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- app.py +126 -0
- final_apartment_model.pkl +3 -0
- requirements.txt +6 -0
app.py
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from sklearn.ensemble import RandomForestRegressor
|
3 |
+
import numpy as np
|
4 |
+
import pandas as pd
|
5 |
+
import pickle
|
6 |
+
from geopy.geocoders import Nominatim
|
7 |
+
from geopy.exc import GeocoderTimedOut
|
8 |
+
from math import radians, cos, sin, asin, sqrt
|
9 |
+
|
10 |
+
# Lade das Modell
|
11 |
+
# TODO change the file to your own model.
|
12 |
+
model_filename = "final_apartment_model.pkl"
|
13 |
+
|
14 |
+
random_forest_model = RandomForestRegressor()
|
15 |
+
with open(model_filename, 'rb') as f:
|
16 |
+
random_forest_model = pickle.load(f)
|
17 |
+
|
18 |
+
# Funktion zur Berechnung der Entfernung zwischen zwei Koordinatenpunkten
|
19 |
+
def haversine(lon1, lat1, lon2, lat2):
|
20 |
+
"""
|
21 |
+
Berechnet die Entfernung in Kilometern zwischen zwei Punkten
|
22 |
+
auf der Erde (anhand von Längen-/Breitengraden)
|
23 |
+
"""
|
24 |
+
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
|
25 |
+
dlon = lon2 - lon1
|
26 |
+
dlat = lat2 - lat1
|
27 |
+
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
|
28 |
+
c = 2 * asin(sqrt(a))
|
29 |
+
return 6371 * c
|
30 |
+
|
31 |
+
transport_hubs = [
|
32 |
+
["Zürich HB", 47.3778, 8.5403],
|
33 |
+
["Zürich Stadelhofen", 47.3665, 8.5486],
|
34 |
+
["Zürich Oerlikon", 47.4111, 8.5438],
|
35 |
+
["Zürich Altstetten", 47.3911, 8.4889],
|
36 |
+
["Winterthur", 47.4996, 8.7241],
|
37 |
+
["Uster", 47.3474, 8.7201],
|
38 |
+
["Wetzikon", 47.3281, 8.7974],
|
39 |
+
["Dübendorf", 47.3973, 8.6186],
|
40 |
+
["Dietikon", 47.4051, 8.4012],
|
41 |
+
["Thalwil", 47.2916, 8.5641]
|
42 |
+
]
|
43 |
+
|
44 |
+
def get_coordinates(address):
|
45 |
+
"""Holt die Koordinaten für eine gegebene Adresse"""
|
46 |
+
try:
|
47 |
+
geolocator = Nominatim(user_agent="my_apartment_predictor")
|
48 |
+
if 'zürich' not in address.lower() and 'switzerland' not in address.lower():
|
49 |
+
address += ', Zürich, Switzerland'
|
50 |
+
location = geolocator.geocode(address)
|
51 |
+
if location:
|
52 |
+
return location.latitude, location.longitude, location.address
|
53 |
+
return None, None, None
|
54 |
+
except GeocoderTimedOut:
|
55 |
+
return None, None, None
|
56 |
+
|
57 |
+
def get_nearest_transport_distance(lat, lon):
|
58 |
+
"""Berechnet die Distanz zum nächsten Verkehrsknotenpunkt"""
|
59 |
+
distances = []
|
60 |
+
for hub in transport_hubs:
|
61 |
+
hub_name, hub_lat, hub_lon = hub
|
62 |
+
distance = haversine(lon, lat, hub_lon, hub_lat)
|
63 |
+
distances.append(distance)
|
64 |
+
return min(distances)
|
65 |
+
|
66 |
+
# Lade die BFS-Daten
|
67 |
+
df_bfs_data = pd.read_csv('bfs_municipality_and_tax_data.csv')
|
68 |
+
|
69 |
+
# Bereinige die tax_income Spalte von Tausendertrennzeichen und konvertiere zu float
|
70 |
+
df_bfs_data['tax_income'] = df_bfs_data['tax_income'].str.replace("'", "").astype(float)
|
71 |
+
|
72 |
+
# Berechne Durchschnittswerte für die Features
|
73 |
+
mean_values = {
|
74 |
+
'pop': df_bfs_data['pop'].mean(),
|
75 |
+
'pop_dens': df_bfs_data['pop_dens'].mean(),
|
76 |
+
'frg_pct': df_bfs_data['frg_pct'].mean(),
|
77 |
+
'emp': df_bfs_data['emp'].mean(),
|
78 |
+
'tax_income': df_bfs_data['tax_income'].mean()
|
79 |
+
}
|
80 |
+
|
81 |
+
def predict_apartment_price(rooms, area, address):
|
82 |
+
"""Vorhersage des Mietpreises basierend auf Zimmer, Fläche und Adresse"""
|
83 |
+
# Hole Koordinaten für die Adresse
|
84 |
+
lat, lon, full_address = get_coordinates(address)
|
85 |
+
if lat is None or lon is None:
|
86 |
+
return "Adresse konnte nicht gefunden werden. Bitte überprüfen Sie die Eingabe."
|
87 |
+
|
88 |
+
# Berechne die Distanz zum nächsten Verkehrsknotenpunkt
|
89 |
+
distance_to_transport = get_nearest_transport_distance(lat, lon)
|
90 |
+
|
91 |
+
# Erstelle DataFrame für die Vorhersage mit den vorberechneten Durchschnittswerten
|
92 |
+
prediction_data = pd.DataFrame({
|
93 |
+
'rooms': [rooms],
|
94 |
+
'area': [area],
|
95 |
+
'pop': [mean_values['pop']],
|
96 |
+
'pop_dens': [mean_values['pop_dens']],
|
97 |
+
'frg_pct': [mean_values['frg_pct']],
|
98 |
+
'emp': [mean_values['emp']],
|
99 |
+
'tax_income': [mean_values['tax_income']],
|
100 |
+
'distance_to_transport': [distance_to_transport]
|
101 |
+
})
|
102 |
+
|
103 |
+
# Mache die Vorhersage
|
104 |
+
prediction = random_forest_model.predict(prediction_data)
|
105 |
+
predicted_price = np.round(prediction[0], 0)
|
106 |
+
|
107 |
+
return f"Geschätzter Mietpreis für {full_address}: CHF {predicted_price:.0f}\nEntfernung zum nächsten Verkehrsknotenpunkt: {distance_to_transport:.1f} km"
|
108 |
+
|
109 |
+
iface = gr.Interface(
|
110 |
+
fn=predict_apartment_price,
|
111 |
+
inputs=[
|
112 |
+
gr.Number(label="Anzahl Zimmer"),
|
113 |
+
gr.Number(label="Wohnfläche (m²)"),
|
114 |
+
gr.Textbox(label="Adresse (z.B. Bahnhofstrasse 1, Zürich)")
|
115 |
+
],
|
116 |
+
outputs=gr.Textbox(label="Vorhersage"),
|
117 |
+
title="Mietpreis-Vorhersage",
|
118 |
+
description="Geben Sie die Details der Wohnung ein, um den geschätzten Mietpreis zu erhalten.",
|
119 |
+
examples=[
|
120 |
+
[4.5, 120, "Bahnhofstrasse 1, Zürich"],
|
121 |
+
[3.5, 80, "Universitätstrasse 84, Zürich"],
|
122 |
+
[2.5, 60, "Technikumstrasse 9, Winterthur"]
|
123 |
+
]
|
124 |
+
)
|
125 |
+
|
126 |
+
iface.launch()
|
final_apartment_model.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:736e75e17260610c98730fd94baf62c1d94d2a26147a5f173106662f692e967f
|
3 |
+
size 20191162
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
pandas
|
3 |
+
numpy
|
4 |
+
scikit-learn
|
5 |
+
matplotlib
|
6 |
+
geopy
|