brunaaaz commited on
Commit
33f133d
·
verified ·
1 Parent(s): cef1fbd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -20
app.py CHANGED
@@ -155,7 +155,6 @@ model, model_cols, df_training = train_model(df)
155
  st.sidebar.image("https://upload.wikimedia.org/wikipedia/commons/6/69/Airbnb_Logo_Bélo.svg", width=140)
156
  st.sidebar.header("Navegação")
157
 
158
- # Label visibility adicionado para evitar warning
159
  page = st.sidebar.radio(
160
  "Menu Principal",
161
  ["📊 Dashboard de Mercado", "📈 Análise Exploratória", "🤖 Simulador IA"],
@@ -187,6 +186,11 @@ if page == "📊 Dashboard de Mercado":
187
  st.markdown("---")
188
 
189
  st.subheader("Mapa de Oportunidades")
 
 
 
 
 
190
  if not df_filtered.empty:
191
  center_lat = df_filtered['latitude'].mean()
192
  center_lon = df_filtered['longitude'].mean()
@@ -206,14 +210,52 @@ if page == "📊 Dashboard de Mercado":
206
  map_data = st_folium(m, height=450, width="100%")
207
  else:
208
  st.warning("Sem dados.")
209
- map_data = None
210
 
 
211
  if map_data and map_data.get('last_object_clicked_popup'):
212
- name = map_data['last_object_clicked_popup']
213
- match = df_filtered[df_filtered['listing_name'] == name]
214
  if not match.empty:
215
- sel = match.iloc[0]
216
- st.info(f"🏡 **{sel['listing_name']}** | Faturamento: R$ {sel['ttm_revenue_native']:,.0f} | Nota: {sel['rating_overall']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
 
218
  st.markdown("---")
219
 
@@ -237,7 +279,6 @@ if page == "📊 Dashboard de Mercado":
237
  st.subheader("💰 Preço Médio por Mês (R$)")
238
  price_table = past_filt.groupby(['month_str', 'city'])['native_rate_avg'].mean().unstack().fillna(0)
239
 
240
- # --- CORREÇÃO: use_container_width é válido no streamlit recente, mas se der aviso, é visual ---
241
  st.dataframe(price_table.style.format("R$ {:.2f}"), use_container_width=True)
242
  else:
243
  st.warning("Sem dados históricos.")
@@ -260,7 +301,7 @@ if page == "📊 Dashboard de Mercado":
260
  ax.imshow(wc, interpolation='bilinear')
261
  ax.axis("off")
262
  st.pyplot(fig)
263
- plt.close(fig) # Limpeza de memória
264
 
265
  # --- PÁGINA 2: EXPLORATÓRIA ---
266
  elif page == "📈 Análise Exploratória":
@@ -296,8 +337,6 @@ elif page == "📈 Análise Exploratória":
296
  with col4:
297
  st.subheader("Tipos de Imóveis")
298
 
299
- # --- CORREÇÃO DEFINITIVA DO ERRO 'VALUE OF X' ---
300
- # Reseta o index e renomeia EXPLICITAMENTE para garantir que o Plotly ache as colunas
301
  df_counts = df_filtered['room_type'].value_counts().reset_index()
302
  df_counts.columns = ['Tipo_Imovel', 'Contagem']
303
 
@@ -308,10 +347,18 @@ elif page == "📈 Análise Exploratória":
308
  template="plotly_white")
309
  st.plotly_chart(fig_bar, use_container_width=True)
310
 
311
- # --- PÁGINA 3: SIMULADOR ---
312
  elif page == "🤖 Simulador IA":
313
  st.title("🤖 Simulador Inteligente")
314
 
 
 
 
 
 
 
 
 
315
  c1, c2 = st.columns([1, 1.5])
316
 
317
  with c1:
@@ -334,10 +381,8 @@ elif page == "🤖 Simulador IA":
334
  sim_pool = st.checkbox("Tem Piscina?", value=False)
335
  sim_super = st.checkbox("Será Superhost?", value=True)
336
 
337
- btn_calc = st.button("🔮 Calcular Previsão")
338
-
339
- with c2:
340
- if btn_calc:
341
  input_df = pd.DataFrame({
342
  'bedrooms': [sim_bed], 'guests': [sim_guest],
343
  'num_reviews': [30], 'latitude': [sim_lat], 'longitude': [sim_lon],
@@ -354,26 +399,37 @@ elif page == "🤖 Simulador IA":
354
  input_df = input_df[model_cols]
355
  pred = model.predict(input_df)[0]
356
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  st.success(f"### 💰 Faturamento Estimado: R$ {pred:,.2f} / ano")
358
 
359
  st.markdown("#### 📍 Localização Simulada")
360
- m_sim = folium.Map(location=[sim_lat, sim_lon], zoom_start=14, tiles='CartoDB positron')
361
  folium.Marker(
362
- [sim_lat, sim_lon],
363
  popup="Seu Imóvel Simulado",
364
  icon=folium.Icon(color="red", icon="home")
365
  ).add_to(m_sim)
366
  st_folium(m_sim, height=300, width="100%")
367
 
368
  st.markdown("#### 🏠 Imóveis Reais Semelhantes (Vizinhança)")
369
- df_city_neighbors = df_training[df_training['city'] == sim_city].copy()
370
 
371
  if not df_city_neighbors.empty:
372
  nn = NearestNeighbors(n_neighbors=5, algorithm='ball_tree')
373
  nn.fit(df_city_neighbors[['latitude', 'longitude']])
374
 
375
- # CORREÇÃO: Passando DataFrame com colunas nomeadas para evitar Warning
376
- X_query = pd.DataFrame([[sim_lat, sim_lon]], columns=['latitude', 'longitude'])
377
  distances, indices = nn.kneighbors(X_query)
378
 
379
  neighbors = df_city_neighbors.iloc[indices[0]]
 
155
  st.sidebar.image("https://upload.wikimedia.org/wikipedia/commons/6/69/Airbnb_Logo_Bélo.svg", width=140)
156
  st.sidebar.header("Navegação")
157
 
 
158
  page = st.sidebar.radio(
159
  "Menu Principal",
160
  ["📊 Dashboard de Mercado", "📈 Análise Exploratória", "🤖 Simulador IA"],
 
186
  st.markdown("---")
187
 
188
  st.subheader("Mapa de Oportunidades")
189
+ st.caption("Clique nos círculos coloridos para ver a Ficha Técnica completa abaixo.")
190
+
191
+ map_data = None
192
+ selected_listing = None
193
+
194
  if not df_filtered.empty:
195
  center_lat = df_filtered['latitude'].mean()
196
  center_lon = df_filtered['longitude'].mean()
 
210
  map_data = st_folium(m, height=450, width="100%")
211
  else:
212
  st.warning("Sem dados.")
 
213
 
214
+ # --- RESTAURAÇÃO DA FICHA TÉCNICA DETALHADA ---
215
  if map_data and map_data.get('last_object_clicked_popup'):
216
+ name_clicked = map_data['last_object_clicked_popup']
217
+ match = df_filtered[df_filtered['listing_name'] == name_clicked]
218
  if not match.empty:
219
+ selected_listing = match.iloc[0]
220
+
221
+ if selected_listing is not None:
222
+ st.markdown("### 📋 Ficha Técnica do Imóvel")
223
+ with st.container():
224
+ # Cabeçalho estilizado
225
+ st.markdown(f"""
226
+ <div style="background-color: #f0f2f6; padding: 20px; border-radius: 10px; border: 1px solid #ccc; margin-bottom: 20px;">
227
+ <h3 style="margin:0; color:#31333F;">🏡 {selected_listing['listing_name']}</h3>
228
+ </div>
229
+ """, unsafe_allow_html=True)
230
+
231
+ c_img, c_info, c_kpi = st.columns([1, 1, 1])
232
+
233
+ with c_img:
234
+ if pd.notna(selected_listing['cover_photo_url']):
235
+ st.image(selected_listing['cover_photo_url'], use_container_width=True)
236
+ else:
237
+ st.info("Sem foto disponível")
238
+
239
+ with c_info:
240
+ st.markdown(f"**📍 Cidade:** {selected_listing['city']}")
241
+ st.markdown(f"**🏠 Tipo:** {selected_listing['room_type']}")
242
+ st.markdown(f"**👥 Acomoda:** {int(selected_listing['guests'])} pessoas")
243
+ st.markdown(f"**🛏️ Quartos:** {int(selected_listing['bedrooms'])}")
244
+ st.metric("Nota Geral", f"⭐ {selected_listing['rating_overall']}")
245
+
246
+ with c_kpi:
247
+ st.metric("Faturamento Anual", f"R$ {selected_listing['ttm_revenue_native']:,.2f}")
248
+ st.metric("ROI Estimado", f"{selected_listing['ROI_anual']:.2f}%")
249
+
250
+ status = selected_listing['Recomendacao']
251
+ if "COMPRA" in status:
252
+ st.success(f"## {status}")
253
+ elif "NÃO" in status:
254
+ st.error(f"## {status}")
255
+ else:
256
+ st.warning(f"## {status}")
257
+ else:
258
+ st.info("👆 Clique em uma bolinha colorida no mapa acima para ver a análise completa do imóvel aqui.")
259
 
260
  st.markdown("---")
261
 
 
279
  st.subheader("💰 Preço Médio por Mês (R$)")
280
  price_table = past_filt.groupby(['month_str', 'city'])['native_rate_avg'].mean().unstack().fillna(0)
281
 
 
282
  st.dataframe(price_table.style.format("R$ {:.2f}"), use_container_width=True)
283
  else:
284
  st.warning("Sem dados históricos.")
 
301
  ax.imshow(wc, interpolation='bilinear')
302
  ax.axis("off")
303
  st.pyplot(fig)
304
+ plt.close(fig)
305
 
306
  # --- PÁGINA 2: EXPLORATÓRIA ---
307
  elif page == "📈 Análise Exploratória":
 
337
  with col4:
338
  st.subheader("Tipos de Imóveis")
339
 
 
 
340
  df_counts = df_filtered['room_type'].value_counts().reset_index()
341
  df_counts.columns = ['Tipo_Imovel', 'Contagem']
342
 
 
347
  template="plotly_white")
348
  st.plotly_chart(fig_bar, use_container_width=True)
349
 
350
+ # --- PÁGINA 3: SIMULADOR (COM SESSION STATE PARA NÃO SUMIR) ---
351
  elif page == "🤖 Simulador IA":
352
  st.title("🤖 Simulador Inteligente")
353
 
354
+ # Inicializa variáveis de estado se não existirem
355
+ if 'sim_result' not in st.session_state:
356
+ st.session_state['sim_result'] = None
357
+ if 'sim_coords' not in st.session_state:
358
+ st.session_state['sim_coords'] = None
359
+ if 'sim_params' not in st.session_state:
360
+ st.session_state['sim_params'] = None
361
+
362
  c1, c2 = st.columns([1, 1.5])
363
 
364
  with c1:
 
381
  sim_pool = st.checkbox("Tem Piscina?", value=False)
382
  sim_super = st.checkbox("Será Superhost?", value=True)
383
 
384
+ if st.button("🔮 Calcular Previsão"):
385
+ # Salva parâmetros na sessão
 
 
386
  input_df = pd.DataFrame({
387
  'bedrooms': [sim_bed], 'guests': [sim_guest],
388
  'num_reviews': [30], 'latitude': [sim_lat], 'longitude': [sim_lon],
 
399
  input_df = input_df[model_cols]
400
  pred = model.predict(input_df)[0]
401
 
402
+ # ATUALIZA O ESTADO
403
+ st.session_state['sim_result'] = pred
404
+ st.session_state['sim_coords'] = [sim_lat, sim_lon]
405
+ st.session_state['sim_params'] = {'city': sim_city}
406
+
407
+ with c2:
408
+ # VERIFICA SE HÁ RESULTADO GRAVADO NA SESSÃO
409
+ if st.session_state['sim_result'] is not None:
410
+ pred = st.session_state['sim_result']
411
+ lat, lon = st.session_state['sim_coords']
412
+ city = st.session_state['sim_params']['city']
413
+
414
  st.success(f"### 💰 Faturamento Estimado: R$ {pred:,.2f} / ano")
415
 
416
  st.markdown("#### 📍 Localização Simulada")
417
+ m_sim = folium.Map(location=[lat, lon], zoom_start=14, tiles='CartoDB positron')
418
  folium.Marker(
419
+ [lat, lon],
420
  popup="Seu Imóvel Simulado",
421
  icon=folium.Icon(color="red", icon="home")
422
  ).add_to(m_sim)
423
  st_folium(m_sim, height=300, width="100%")
424
 
425
  st.markdown("#### 🏠 Imóveis Reais Semelhantes (Vizinhança)")
426
+ df_city_neighbors = df_training[df_training['city'] == city].copy()
427
 
428
  if not df_city_neighbors.empty:
429
  nn = NearestNeighbors(n_neighbors=5, algorithm='ball_tree')
430
  nn.fit(df_city_neighbors[['latitude', 'longitude']])
431
 
432
+ X_query = pd.DataFrame([[lat, lon]], columns=['latitude', 'longitude'])
 
433
  distances, indices = nn.kneighbors(X_query)
434
 
435
  neighbors = df_city_neighbors.iloc[indices[0]]