nbacchi commited on
Commit
b36eee9
·
verified ·
1 Parent(s): 4c92717

Upload 3 files

Browse files
Files changed (3) hide show
  1. apartment_price_model.pkl +3 -0
  2. app.py +114 -0
  3. requirements.txt +1 -0
apartment_price_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f4ad8f12166bee59259972339e137a6ede2a2922cf4c39f210e164e2ea950b49
3
+ size 11976223
app.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import pickle
3
+
4
+ import gradio as gr
5
+ import pandas as pd
6
+
7
+
8
+ BASE_DIR = Path(__file__).resolve().parent
9
+ MODEL_PATH = BASE_DIR / "apartment_price_model.pkl"
10
+ DATA_PATH = BASE_DIR / "data" / "raw" / "original_apartment_data_analytics_hs24.csv"
11
+
12
+
13
+ with MODEL_PATH.open("rb") as f:
14
+ model = pickle.load(f)
15
+
16
+
17
+ df = pd.read_csv(DATA_PATH)
18
+ municipality_columns = ["town", "postalcode", "pop", "pop_dens", "frg_pct", "emp", "tax_income"]
19
+ municipality_df = df[municipality_columns].dropna().copy()
20
+ municipality_df["town"] = municipality_df["town"].astype(str).str.strip()
21
+ municipality_df = municipality_df.drop_duplicates(subset=["town"]).sort_values("town")
22
+ MUNICIPALITY_DATA = municipality_df.set_index("town").to_dict("index")
23
+
24
+
25
+ def _build_features(rooms: float, area: float, town: str) -> tuple[pd.DataFrame, dict]:
26
+ municipality = MUNICIPALITY_DATA[town]
27
+
28
+ pop = float(municipality["pop"])
29
+ pop_dens = float(municipality["pop_dens"])
30
+ frg_pct = float(municipality["frg_pct"])
31
+ emp = float(municipality["emp"])
32
+ tax_income = float(municipality["tax_income"])
33
+
34
+ municipality_area_proxy = pop / pop_dens
35
+ emp_per_resident = emp / pop
36
+ foreigner_count_est = pop * (frg_pct / 100)
37
+
38
+ features = pd.DataFrame(
39
+ [
40
+ {
41
+ "rooms": rooms,
42
+ "area": area,
43
+ "pop": pop,
44
+ "pop_dens": pop_dens,
45
+ "frg_pct": frg_pct,
46
+ "emp": emp,
47
+ "tax_income": tax_income,
48
+ "municipality_area_proxy": municipality_area_proxy,
49
+ "emp_per_resident": emp_per_resident,
50
+ "foreigner_count_est": foreigner_count_est,
51
+ }
52
+ ]
53
+ )
54
+
55
+ return features, municipality
56
+
57
+
58
+ def predict_price(rooms: float, area: float, town: str) -> tuple[str, str]:
59
+ features, municipality = _build_features(rooms=rooms, area=area, town=town)
60
+ prediction = float(model.predict(features)[0])
61
+
62
+ pop = float(municipality["pop"])
63
+ pop_dens = float(municipality["pop_dens"])
64
+ frg_pct = float(municipality["frg_pct"])
65
+ emp = float(municipality["emp"])
66
+
67
+ municipality_area_proxy = pop / pop_dens
68
+ emp_per_resident = emp / pop
69
+ foreigner_count_est = pop * (frg_pct / 100)
70
+
71
+ details = (
72
+ f"Ort: {town} (PLZ {int(municipality['postalcode'])})\n\n"
73
+ f"Gemeindedaten:\n"
74
+ f" Bevölkerung: {int(pop):,}\n"
75
+ f" Bevölkerungsdichte: {pop_dens:.1f}/km²\n"
76
+ f" Ausländeranteil: {frg_pct:.1f}%\n"
77
+ f" Beschäftigte: {int(emp):,}\n"
78
+ f" Steuerbares Einkommen: CHF {municipality['tax_income']:,.0f}\n\n"
79
+ f"Zusätzliche berechnete Features:\n"
80
+ f" Gemeindegröße: {municipality_area_proxy:.2f} km²\n"
81
+ f" Arbeitsplatzquote: {emp_per_resident:.3f}\n"
82
+ f" Ausländerpopulation: {int(foreigner_count_est):,}"
83
+ )
84
+
85
+ return f"CHF {prediction:,.2f} pro Monat", details
86
+
87
+
88
+ demo = gr.Interface(
89
+ fn=predict_price,
90
+ inputs=[
91
+ gr.Slider(1, 8, value=3, step=0.5, label="Zimmer"),
92
+ gr.Slider(20, 250, value=80, step=1, label="Wohnfläche (m²)"),
93
+ gr.Dropdown(choices=list(MUNICIPALITY_DATA.keys()), value="Zürich", label="Gemeinde"),
94
+ ],
95
+ outputs=[
96
+ gr.Textbox(label="Geschätzte Miete"),
97
+ gr.Textbox(label="Verwendete Gemeindedaten"),
98
+ ],
99
+ examples=[
100
+ [2.5, 60, "Zürich"],
101
+ [3.5, 90, "Winterthur"],
102
+ [4.5, 120, "Uster"],
103
+ ],
104
+ title="Apartment Price Prediction – Kanton Zürich",
105
+ description=(
106
+ "Vorhersage der monatlichen Wohnungsmiete mit einem Random-Forest-Regressionsmodell. "
107
+ "Die App nutzt Basismerkmale und zusätzliche Feature-Engineering-Variablen "
108
+ "(municipality_area_proxy, emp_per_resident, foreigner_count_est)."
109
+ ),
110
+ )
111
+
112
+
113
+ if __name__ == "__main__":
114
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ scikit-learn