Update app.py
Browse files
app.py
CHANGED
@@ -33,7 +33,8 @@ st.markdown("""
|
|
33 |
<style>
|
34 |
.main-header {
|
35 |
font-size: 2.5rem;
|
36 |
-
color:
|
|
|
37 |
text-align: center;
|
38 |
margin-bottom: 1rem;
|
39 |
}
|
@@ -62,7 +63,7 @@ st.markdown("""
|
|
62 |
""", unsafe_allow_html=True)
|
63 |
|
64 |
st.sidebar.title("Navigasyon")
|
65 |
-
pages = ["Ana Sayfa", "Veri İnceleme", "Ön İşleme Sonuçları", "Model Sonuçları", "Harita Görselleştirme"]
|
66 |
selected_page = st.sidebar.radio("", pages)
|
67 |
|
68 |
@st.cache_data
|
@@ -120,21 +121,20 @@ if df is not None:
|
|
120 |
if selected_page == "Ana Sayfa":
|
121 |
st.markdown("<h1 class='main-header'>New York Airbnb Fiyat Tahmini</h1>", unsafe_allow_html=True)
|
122 |
|
123 |
-
|
124 |
-
with col2:
|
125 |
-
st.image("https://a0.muscache.com/im/pictures/fe7217ff-0b24-438d-8833-1dd45a298a6b.jpg", use_column_width=True)
|
126 |
-
|
127 |
-
st.markdown("<div class='info-box'>", unsafe_allow_html=True)
|
128 |
st.markdown("""
|
129 |
-
Bu
|
130 |
-
Amacımız, bir evi kiralamak isteyen birinin
|
131 |
-
|
132 |
""")
|
133 |
st.markdown("</div>", unsafe_allow_html=True)
|
134 |
|
135 |
st.markdown("<h2 class='section-header'>Veri Seti Genel Bakış</h2>", unsafe_allow_html=True)
|
136 |
st.dataframe(df.head())
|
137 |
-
|
|
|
|
|
|
|
138 |
st.markdown("<h2 class='section-header'>Veri Seti Sütunları</h2>", unsafe_allow_html=True)
|
139 |
st.markdown("""
|
140 |
- **id**: Airbnb ilanının benzersiz kimlik numarası
|
@@ -158,7 +158,16 @@ if df is not None:
|
|
158 |
|
159 |
elif selected_page == "Veri İnceleme":
|
160 |
st.markdown("<h1 class='main-header'>Veri İnceleme</h1>", unsafe_allow_html=True)
|
161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
st.markdown("<h2 class='section-header'>Aylık Yorum Sayısı Analizi</h2>", unsafe_allow_html=True)
|
163 |
|
164 |
col1, col2 = st.columns(2)
|
@@ -167,10 +176,10 @@ if df is not None:
|
|
167 |
with col2:
|
168 |
st.metric("Medyan", f"{df['reviews_per_month'].median():.2f}")
|
169 |
|
170 |
-
st.markdown("<div
|
171 |
st.markdown("""
|
172 |
-
Çarpık bir dağılım var. Çünkü ortalama > medyan olduğundan
|
173 |
-
|
174 |
""")
|
175 |
st.markdown("</div>", unsafe_allow_html=True)
|
176 |
|
@@ -185,19 +194,10 @@ if df is not None:
|
|
185 |
|
186 |
st.markdown("""
|
187 |
Daha fazla yorum sayısına sahip ilanlar ortalamayı yukarı çekiyor.
|
188 |
-
Burada çarpıklığı azaltmam gerekiyor. Dağılımı dengeli hale
|
189 |
""")
|
190 |
|
191 |
-
st.markdown("<h2 class='section-header'>Eksik Değer Analizi</h2>", unsafe_allow_html=True)
|
192 |
-
|
193 |
-
missing_vals = df.isnull().sum()
|
194 |
-
missing_cols = missing_vals[missing_vals > 0]
|
195 |
|
196 |
-
if len(missing_cols) > 0:
|
197 |
-
st.write("Eksik değer içeren sütunlar:")
|
198 |
-
st.write(missing_cols)
|
199 |
-
else:
|
200 |
-
st.success("Veri setinde eksik değer bulunmuyor.")
|
201 |
|
202 |
|
203 |
elif selected_page == "Ön İşleme Sonuçları":
|
@@ -247,11 +247,14 @@ if df is not None:
|
|
247 |
|
248 |
st.pyplot(fig)
|
249 |
|
250 |
-
st.markdown("<div
|
251 |
st.markdown("""
|
252 |
-
|
253 |
-
|
254 |
-
|
|
|
|
|
|
|
255 |
""")
|
256 |
st.markdown("</div>", unsafe_allow_html=True)
|
257 |
except Exception as e:
|
@@ -263,10 +266,10 @@ if df is not None:
|
|
263 |
st.markdown("""
|
264 |
Eksik değerleri şu stratejiye göre doldurdum:
|
265 |
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
""")
|
271 |
|
272 |
|
@@ -274,11 +277,40 @@ if df is not None:
|
|
274 |
|
275 |
st.markdown("""
|
276 |
1. neighbourhood_group ve room_type kategorik değişkenlerini one-hot encoding ile sayısal değerlere dönüştürdüm.
|
277 |
-
2. neighbourhood
|
|
|
|
|
278 |
3. Sıfır fiyatlı ilanları veri setinden çıkardım.
|
279 |
-
4.
|
280 |
-
|
|
|
|
|
|
|
|
|
281 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
|
283 |
|
284 |
elif selected_page == "Model Sonuçları":
|
@@ -301,11 +333,13 @@ if df is not None:
|
|
301 |
lr_mae = mean_absolute_error(y_test, lr_pred)
|
302 |
lr_mse = mean_squared_error(y_test, lr_pred)
|
303 |
lr_rmse = np.sqrt(lr_mse)
|
|
|
304 |
|
305 |
-
col1, col2, col3 = st.columns(
|
306 |
-
col1.metric("MAE", f"
|
307 |
-
col2.metric("RMSE", f"
|
308 |
-
col3.metric("MSE", f"
|
|
|
309 |
|
310 |
fig, ax = plt.subplots(figsize=(8, 6))
|
311 |
sns.scatterplot(x=y_test, y=lr_pred, alpha=0.5, ax=ax)
|
@@ -330,8 +364,8 @@ if df is not None:
|
|
330 |
dt_r2 = r2_score(y_test, dt_pred)
|
331 |
|
332 |
col1, col2, col3 = st.columns(3)
|
333 |
-
col1.metric("MAE", f"
|
334 |
-
col2.metric("MSE", f"
|
335 |
col3.metric("R²", f"{dt_r2:.4f}")
|
336 |
|
337 |
fig, ax = plt.subplots(figsize=(8, 6))
|
@@ -363,8 +397,8 @@ if df is not None:
|
|
363 |
rf_r2 = r2_score(y_test, rf_pred)
|
364 |
|
365 |
col1, col2, col3 = st.columns(3)
|
366 |
-
col1.metric("MAE", f"
|
367 |
-
col2.metric("MSE", f"
|
368 |
col3.metric("R²", f"{rf_r2:.4f}")
|
369 |
|
370 |
fig, ax = plt.subplots(figsize=(8, 6))
|
@@ -390,14 +424,59 @@ if df is not None:
|
|
390 |
comparison_df = comparison_df.set_index('Model')
|
391 |
st.dataframe(comparison_df.style.highlight_min(subset=['MAE', 'MSE']).highlight_max(subset=['R²']))
|
392 |
|
393 |
-
st.markdown("<div
|
394 |
st.markdown("""
|
395 |
Random Forest modeli en iyi performansı göstermiştir.
|
396 |
R² değeri 1'e yakın olduğu için modelin açıklama gücü yüksektir.
|
397 |
""")
|
398 |
-
st.markdown("</div>", unsafe_allow_html=True)
|
399 |
-
|
400 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
401 |
elif selected_page == "Harita Görselleştirme":
|
402 |
st.markdown("<h1 class='main-header'>Harita Görselleştirme</h1>", unsafe_allow_html=True)
|
403 |
|
@@ -462,6 +541,80 @@ if df is not None:
|
|
462 |
except Exception as e:
|
463 |
st.error(f"Harita oluşturulurken bir hata oluştu: {e}")
|
464 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
465 |
if __name__ == "__main__":
|
466 |
|
467 |
pass
|
|
|
33 |
<style>
|
34 |
.main-header {
|
35 |
font-size: 2.5rem;
|
36 |
+
color: black;
|
37 |
+
/* Airbnb color */
|
38 |
text-align: center;
|
39 |
margin-bottom: 1rem;
|
40 |
}
|
|
|
63 |
""", unsafe_allow_html=True)
|
64 |
|
65 |
st.sidebar.title("Navigasyon")
|
66 |
+
pages = ["Ana Sayfa", "Veri İnceleme", "Ön İşleme Sonuçları", "Model Sonuçları", "Harita Görselleştirme","Raporlama","Fiyat Tahmin"]
|
67 |
selected_page = st.sidebar.radio("", pages)
|
68 |
|
69 |
@st.cache_data
|
|
|
121 |
if selected_page == "Ana Sayfa":
|
122 |
st.markdown("<h1 class='main-header'>New York Airbnb Fiyat Tahmini</h1>", unsafe_allow_html=True)
|
123 |
|
124 |
+
st.markdown("<div>", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
125 |
st.markdown("""
|
126 |
+
Bu projede, New York City'deki Airbnb kiralık dairelerin fiyatlarını tahmin etmek amacıyla regresyon modelleri geliştirilmiştir.
|
127 |
+
Amacımız, bir evi kiralamak isteyen birinin ödeyeceği fiyatı öngörebilmektir.
|
128 |
+
Bu doğrultuda, Doğrusal Regresyon, Karar Ağacı ve Random Forest modelleri uygulanmıştır.
|
129 |
""")
|
130 |
st.markdown("</div>", unsafe_allow_html=True)
|
131 |
|
132 |
st.markdown("<h2 class='section-header'>Veri Seti Genel Bakış</h2>", unsafe_allow_html=True)
|
133 |
st.dataframe(df.head())
|
134 |
+
rows, cols = df.shape
|
135 |
+
st.markdown(f"""
|
136 |
+
Veri seti toplam **{rows} gözlem (satır)** ve **{cols} özellik (sütun)** içermektedir.
|
137 |
+
""")
|
138 |
st.markdown("<h2 class='section-header'>Veri Seti Sütunları</h2>", unsafe_allow_html=True)
|
139 |
st.markdown("""
|
140 |
- **id**: Airbnb ilanının benzersiz kimlik numarası
|
|
|
158 |
|
159 |
elif selected_page == "Veri İnceleme":
|
160 |
st.markdown("<h1 class='main-header'>Veri İnceleme</h1>", unsafe_allow_html=True)
|
161 |
+
st.markdown("<h2 class='section-header'>Eksik Değer Analizi</h2>", unsafe_allow_html=True)
|
162 |
+
|
163 |
+
missing_vals = df.isnull().sum()
|
164 |
+
missing_cols = missing_vals[missing_vals > 0]
|
165 |
+
|
166 |
+
if len(missing_cols) > 0:
|
167 |
+
st.write("Eksik değer içeren sütunlar:")
|
168 |
+
st.write(missing_cols)
|
169 |
+
else:
|
170 |
+
st.success("Veri setinde eksik değer bulunmuyor.")
|
171 |
st.markdown("<h2 class='section-header'>Aylık Yorum Sayısı Analizi</h2>", unsafe_allow_html=True)
|
172 |
|
173 |
col1, col2 = st.columns(2)
|
|
|
176 |
with col2:
|
177 |
st.metric("Medyan", f"{df['reviews_per_month'].median():.2f}")
|
178 |
|
179 |
+
st.markdown("<div>", unsafe_allow_html=True)
|
180 |
st.markdown("""
|
181 |
+
Çarpık bir dağılım var. Çünkü ortalama > medyan olduğundan aylık yorum sayısı verisi sağa çarpık bir dağılıma sahiptir.
|
182 |
+
Çünkü verilerin çoğu düşük yorum sayısına sahipken, birkaç popüler ilanın çok yüksek yorum alması ortalamayı yukarı çekmektedir.
|
183 |
""")
|
184 |
st.markdown("</div>", unsafe_allow_html=True)
|
185 |
|
|
|
194 |
|
195 |
st.markdown("""
|
196 |
Daha fazla yorum sayısına sahip ilanlar ortalamayı yukarı çekiyor.
|
197 |
+
Burada çarpıklığı azaltmam gerekiyor. Dağılımı dengeli hale getirmek gerekiyor.
|
198 |
""")
|
199 |
|
|
|
|
|
|
|
|
|
200 |
|
|
|
|
|
|
|
|
|
|
|
201 |
|
202 |
|
203 |
elif selected_page == "Ön İşleme Sonuçları":
|
|
|
247 |
|
248 |
st.pyplot(fig)
|
249 |
|
250 |
+
st.markdown("<div>", unsafe_allow_html=True)
|
251 |
st.markdown("""
|
252 |
+
Aylık yorum sayısı değişkeni başlangıçta oldukça sağa çarpıktı.
|
253 |
+
Bu durum, az sayıda ilanın aşırı fazla yorum alması nedeniyle, ortalamanın yukarı çekilmesinden kaynaklanıyordu.
|
254 |
+
Yeo-Johnson dönüşümü ile bu dağılım daha simetrik ve normal benzeri bir yapıya dönüştürüldü.
|
255 |
+
Böylece hem uç değerlerin etkisi azaldı, hem de regresyon modellerinin doğruluğu artırılmış oldu.
|
256 |
+
|
257 |
+
|
258 |
""")
|
259 |
st.markdown("</div>", unsafe_allow_html=True)
|
260 |
except Exception as e:
|
|
|
266 |
st.markdown("""
|
267 |
Eksik değerleri şu stratejiye göre doldurdum:
|
268 |
|
269 |
+
--Bu sütunlar ("id", "name", "host_id", "host_name", "last_review") analiz için gereksiz sutünlarımı verimden attım.
|
270 |
+
1. Aynı mahalle ve oda tipindeki medyan değerleri kullanarak eksik değerleri doldurdum.Çünkü benzer özellikteki evlerin benzer yorum alma ihtimali yüksek
|
271 |
+
2. Hala eksik değer varsa, mahalle bazında medyan değerleri kullandım.
|
272 |
+
3. Son olarak, kalan eksik değerleri 0 ile doldurdum.
|
273 |
""")
|
274 |
|
275 |
|
|
|
277 |
|
278 |
st.markdown("""
|
279 |
1. neighbourhood_group ve room_type kategorik değişkenlerini one-hot encoding ile sayısal değerlere dönüştürdüm.
|
280 |
+
2. neighbourhood sütunu, 200'den fazla farklı mahalle ismi içeriyordu.
|
281 |
+
Bu değişkeni doğrudan modele vermek hem anlamlı olmaz hem de yüksek boyutluluğa sebep olurdu.
|
282 |
+
Bunun yerine, her mahallenin ortalama fiyatını hesaplayarak neighbourhood_encoded adlı yeni bir sayısal değişken oluşturdum.BU sayede artık mahalle ismi degil o mahallenin ortalam fiyat bilgisini çektik.
|
283 |
3. Sıfır fiyatlı ilanları veri setinden çıkardım.
|
284 |
+
4. Fiyat değişkenine log(1 + price) dönüşümü uyguladım.
|
285 |
+
Bu sayede fiyatlardaki çarpıklığı azalttım ve veriyi modellere daha uygun hale getirdim.
|
286 |
+
5. Minimum konaklama süresi ve yorum sayısı gibi değişkenlerde yüksek uç değerler bulunuyordu.
|
287 |
+
minimum_nights değişkenine log dönüşümü uygulayarak bu uç değerlerin etkisini azalttım.
|
288 |
+
6. reviews_per_month ile number_of_reviews’u çarparak yeni bir review_score değişkeni oluşturdum.
|
289 |
+
Bu yeni özellik, hem evin ne kadar aktif olduğunu hem de ne kadar uzun süredir platformda olduğunu yansıtarak model için daha bilgilendirici hale geldi.
|
290 |
""")
|
291 |
+
# minimum_nights_log sütunu yoksa oluştur
|
292 |
+
if "minimum_nights_log" not in df.columns:
|
293 |
+
df["minimum_nights_log"] = np.log1p(df["minimum_nights"])
|
294 |
+
|
295 |
+
# Görselleştirme
|
296 |
+
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
|
297 |
+
|
298 |
+
# Orijinal minimum_nights dağılımı
|
299 |
+
sns.histplot(df["minimum_nights"], bins=50, kde=True, ax=axes[0], color="skyblue")
|
300 |
+
axes[0].set_title("Minimum Nights (Orijinal)")
|
301 |
+
axes[0].set_xlabel("minimum_nights")
|
302 |
+
|
303 |
+
# Log dönüşümlü minimum_nights dağılımı
|
304 |
+
sns.histplot(df["minimum_nights_log"], bins=50, kde=True, ax=axes[1], color="lightgreen")
|
305 |
+
axes[1].set_title("Minimum Nights (Log Dönüşümlü)")
|
306 |
+
axes[1].set_xlabel("minimum_nights_log")
|
307 |
+
|
308 |
+
plt.tight_layout()
|
309 |
+
st.pyplot(fig)
|
310 |
+
|
311 |
+
|
312 |
+
|
313 |
+
|
314 |
|
315 |
|
316 |
elif selected_page == "Model Sonuçları":
|
|
|
333 |
lr_mae = mean_absolute_error(y_test, lr_pred)
|
334 |
lr_mse = mean_squared_error(y_test, lr_pred)
|
335 |
lr_rmse = np.sqrt(lr_mse)
|
336 |
+
lr_r2 = r2_score(y_test, lr_pred)
|
337 |
|
338 |
+
col1, col2, col3,col4 = st.columns(4)
|
339 |
+
col1.metric("MAE", f"{lr_mae:.2f}")
|
340 |
+
col2.metric("RMSE", f"{lr_rmse:.2f}")
|
341 |
+
col3.metric("MSE", f"{lr_mse:.2f}")
|
342 |
+
col4.metric("R²", f"{lr_r2:.4f}")
|
343 |
|
344 |
fig, ax = plt.subplots(figsize=(8, 6))
|
345 |
sns.scatterplot(x=y_test, y=lr_pred, alpha=0.5, ax=ax)
|
|
|
364 |
dt_r2 = r2_score(y_test, dt_pred)
|
365 |
|
366 |
col1, col2, col3 = st.columns(3)
|
367 |
+
col1.metric("MAE", f"{dt_mae:.2f}")
|
368 |
+
col2.metric("MSE", f"{dt_mse:.2f}")
|
369 |
col3.metric("R²", f"{dt_r2:.4f}")
|
370 |
|
371 |
fig, ax = plt.subplots(figsize=(8, 6))
|
|
|
397 |
rf_r2 = r2_score(y_test, rf_pred)
|
398 |
|
399 |
col1, col2, col3 = st.columns(3)
|
400 |
+
col1.metric("MAE", f"{rf_mae:.2f}")
|
401 |
+
col2.metric("MSE", f"{rf_mse:.2f}")
|
402 |
col3.metric("R²", f"{rf_r2:.4f}")
|
403 |
|
404 |
fig, ax = plt.subplots(figsize=(8, 6))
|
|
|
424 |
comparison_df = comparison_df.set_index('Model')
|
425 |
st.dataframe(comparison_df.style.highlight_min(subset=['MAE', 'MSE']).highlight_max(subset=['R²']))
|
426 |
|
427 |
+
st.markdown("<div>", unsafe_allow_html=True)
|
428 |
st.markdown("""
|
429 |
Random Forest modeli en iyi performansı göstermiştir.
|
430 |
R² değeri 1'e yakın olduğu için modelin açıklama gücü yüksektir.
|
431 |
""")
|
|
|
|
|
432 |
|
433 |
+
# Korelasyon matrisi
|
434 |
+
st.markdown("<h2 class='section-header'>Korelasyon Matrisi</h2>", unsafe_allow_html=True)
|
435 |
+
|
436 |
+
# İşlenmiş veri ile korelasyon hesapla
|
437 |
+
_, _, processed_df = preprocess_data(df)
|
438 |
+
|
439 |
+
# Sadece sayısal sütunları alalım
|
440 |
+
corr = processed_df.select_dtypes(include=["float64", "int64"]).corr()
|
441 |
+
|
442 |
+
# Grafik
|
443 |
+
fig, ax = plt.subplots(figsize=(12, 10))
|
444 |
+
sns.heatmap(corr, annot=True, fmt=".2f", cmap="coolwarm", square=True, ax=ax)
|
445 |
+
ax.set_title("Değişkenler Arası Korelasyon Matrisi")
|
446 |
+
st.pyplot(fig)
|
447 |
+
|
448 |
+
# Yorum
|
449 |
+
st.markdown("""
|
450 |
+
Korelasyon matrisi, değişkenler arasındaki ilişkileri göstermektedir. Fiyatla en güçlü pozitif korelasyon neighbourhood_encoded (mahalle ortalama fiyatı) ve reviews_per_month_original (yorum yoğunluğu) değişkenlerindedir. Ayrıca review_score ile number_of_reviews arasında beklenen şekilde yüksek bir ilişki vardır. Bu analiz, modele en çok katkı sağlayan değişkenleri belirlemek için önemlidir.
|
451 |
+
""")
|
452 |
+
|
453 |
+
st.markdown("<h3 class='subsection-header'>Kategorik Değişkenler ve Ortalama Fiyat</h3>", unsafe_allow_html=True)
|
454 |
+
|
455 |
+
categorical_cols = ["room_type", "neighbourhood_group"]
|
456 |
+
selected_cat = st.selectbox("İncelemek istediğiniz kategorik değişkeni seçin:", categorical_cols)
|
457 |
+
|
458 |
+
# Seçilen kategoriye göre ortalama fiyat
|
459 |
+
avg_price_by_cat = df.groupby(selected_cat)["price"].mean().sort_values(ascending=False).reset_index()
|
460 |
+
|
461 |
+
fig, ax = plt.subplots(figsize=(8, 5))
|
462 |
+
sns.barplot(x="price", y=selected_cat, data=avg_price_by_cat, palette="magma", ax=ax)
|
463 |
+
ax.set_title(f"{selected_cat} kategorisine göre ortalama fiyat")
|
464 |
+
ax.set_xlabel("Ortalama Fiyat ($)")
|
465 |
+
ax.set_ylabel(selected_cat)
|
466 |
+
st.pyplot(fig)
|
467 |
+
|
468 |
+
# Açıklama
|
469 |
+
st.markdown(f"""
|
470 |
+
**{selected_cat}** değişkenine göre Airbnb fiyatlarının nasıl değiştiği yukarıdaki grafikte görülmektedir.
|
471 |
+
|
472 |
+
Bu grafik:
|
473 |
+
- Her bir kategori için **ortalama fiyat** değerini gösterir.
|
474 |
+
- Modelin `room_type` ve `neighbourhood_group` gibi değişkenlere neden önem verdiğini açıklar.
|
475 |
+
""")
|
476 |
+
|
477 |
+
|
478 |
+
|
479 |
+
|
480 |
elif selected_page == "Harita Görselleştirme":
|
481 |
st.markdown("<h1 class='main-header'>Harita Görselleştirme</h1>", unsafe_allow_html=True)
|
482 |
|
|
|
541 |
except Exception as e:
|
542 |
st.error(f"Harita oluşturulurken bir hata oluştu: {e}")
|
543 |
|
544 |
+
elif selected_page == "Raporlama":
|
545 |
+
st.markdown("<h1 class='main-header'>📊Proje Raporlaması</h1>", unsafe_allow_html=True)
|
546 |
+
|
547 |
+
|
548 |
+
|
549 |
+
|
550 |
+
|
551 |
+
|
552 |
+
st.markdown("<h2 class='section-header'> Sonuçlar ve Yorumlar</h2>", unsafe_allow_html=True)
|
553 |
+
st.markdown("""
|
554 |
+
- En başarılı model: **Random Forest**,
|
555 |
+
- Overfitting gözlemlenmemiştir (train ve test R² yakın)
|
556 |
+
- Modelin en önemli değişkenleri:
|
557 |
+
- `neighbourhood_encoded`: mahalle ortalama fiyatı
|
558 |
+
- `latitude`, `longitude`: konum bilgisi
|
559 |
+
- `room_type_Entire home/apt`:
|
560 |
+
""")
|
561 |
+
|
562 |
+
st.markdown("<h2 class='section-header'> Çıkarımlar</h2>", unsafe_allow_html=True)
|
563 |
+
st.markdown("""
|
564 |
+
- Lokasyon ve mahalle ortalamaları fiyat üzerinde en baskın faktörlerdir.
|
565 |
+
- Ev fiyatları üzerinde 'oda tipi', 'yorum_sayısı' da etkilemektedir.
|
566 |
+
- Model, düşük fiyatlı evlerde daha başarılı tahmin yaparken, uç değerlerde sapmalar yaşanmıştır.
|
567 |
+
""")
|
568 |
+
elif selected_page == "Fiyat Tahmin":
|
569 |
+
st.markdown("<h1 class='main-header'> Airbnb Fiyat Tahmin Aracı</h1>", unsafe_allow_html=True)
|
570 |
+
|
571 |
+
X, y, processed_df = preprocess_data(df)
|
572 |
+
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
|
573 |
+
rf_model.fit(X, y)
|
574 |
+
|
575 |
+
st.markdown("<h2 class='section-header'>Bilgilerinizi Girin</h2>", unsafe_allow_html=True)
|
576 |
+
|
577 |
+
# Girişler
|
578 |
+
latitude = st.number_input("Latitude (Enlem)", value=40.75)
|
579 |
+
longitude = st.number_input("Longitude (Boylam)", value=-73.98)
|
580 |
+
minimum_nights = st.number_input("Minimum Konaklama Gecesi", min_value=1, value=3)
|
581 |
+
number_of_reviews = st.number_input("Yorum Sayısı", min_value=0, value=10)
|
582 |
+
reviews_per_month = st.number_input("Aylık Ortalama Yorum", min_value=0.0, value=0.5)
|
583 |
+
availability_365 = st.slider("Yıllık Müsaitlik (gün)", 0, 365, 180)
|
584 |
+
|
585 |
+
neighbourhood_encoded = st.slider("Mahalle Ortalama Fiyatı", min_value=20, max_value=500, value=150)
|
586 |
+
|
587 |
+
neighbourhood_group = st.selectbox("Bölge", ["Brooklyn", "Manhattan", "Queens", "Staten Island", "Bronx"])
|
588 |
+
room_type = st.selectbox("Oda Tipi", ["Private room", "Entire home/apt", "Shared room"])
|
589 |
+
|
590 |
+
# Özellik vektörü oluştur
|
591 |
+
input_data = {
|
592 |
+
"latitude": latitude,
|
593 |
+
"longitude": longitude,
|
594 |
+
"minimum_nights": minimum_nights,
|
595 |
+
"number_of_reviews": number_of_reviews,
|
596 |
+
"reviews_per_month": reviews_per_month,
|
597 |
+
"calculated_host_listings_count": 1,
|
598 |
+
"availability_365": availability_365,
|
599 |
+
"neighbourhood_encoded": neighbourhood_encoded,
|
600 |
+
"review_score": reviews_per_month * number_of_reviews,
|
601 |
+
"minimum_nights_log": np.log1p(minimum_nights),
|
602 |
+
"neighbourhood_group_Manhattan": 1 if neighbourhood_group == "Manhattan" else 0,
|
603 |
+
"neighbourhood_group_Queens": 1 if neighbourhood_group == "Queens" else 0,
|
604 |
+
"neighbourhood_group_Staten Island": 1 if neighbourhood_group == "Staten Island" else 0,
|
605 |
+
"neighbourhood_group_Bronx": 1 if neighbourhood_group == "Bronx" else 0,
|
606 |
+
"room_type_Private room": 1 if room_type == "Private room" else 0,
|
607 |
+
"room_type_Shared room": 1 if room_type == "Shared room" else 0
|
608 |
+
}
|
609 |
+
|
610 |
+
# Modelin beklediği sırayla dataframe'e dönüştür
|
611 |
+
input_df = pd.DataFrame([input_data], columns=X.columns)
|
612 |
+
|
613 |
+
# Tahmin
|
614 |
+
if st.button("Tahmini Fiyatı Göster"):
|
615 |
+
prediction = rf_model.predict(input_df)[0]
|
616 |
+
st.success(f"Tahmini Gecelik Fiyat: **${prediction:.2f}**")
|
617 |
+
|
618 |
if __name__ == "__main__":
|
619 |
|
620 |
pass
|