brunaaaz commited on
Commit
8c1ee3c
·
verified ·
1 Parent(s): 569d42f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -91
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py - Dashboard Interativo de Cancelamento de Reservas
2
  import streamlit as st
3
  import pandas as pd
4
  import numpy as np
@@ -26,6 +26,14 @@ except ImportError as e:
26
  st.warning(f"⚠️ SMOTE não disponível: {e}. Continuando sem balanceamento automático.")
27
  SMOTE_AVAILABLE = False
28
 
 
 
 
 
 
 
 
 
29
  # Configuração da página
30
  st.set_page_config(
31
  page_title="Dashboard - Cancelamento de Reservas",
@@ -93,6 +101,28 @@ class HotelBookingDashboard:
93
  self.scaler = StandardScaler()
94
  self.is_data_loaded = False
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  def load_and_preprocess_data(self, df):
97
  """Carrega e pré-processa o dataset"""
98
  try:
@@ -343,104 +373,91 @@ def main():
343
  if not dashboard.is_data_loaded:
344
  st.markdown("""
345
  <div class="data-source-section">
346
- <h2>📊 Upload do Dataset</h2>
347
  <p style="font-size: 1.2rem; margin-bottom: 1.5rem;">
348
- <strong>Faça upload do dataset de reservas de hotel para começar a análise</strong>
349
  </p>
350
  </div>
351
  """, unsafe_allow_html=True)
352
 
353
- # Upload centralizado
354
- col1, col2, col3 = st.columns([1, 2, 1])
355
- with col2:
356
- uploaded_file = st.file_uploader(
357
- "**Selecione o arquivo CSV do dataset**",
358
- type=['csv'],
359
- help="Faça upload do dataset de reservas de hotel (ex: hotel_bookings.csv)",
360
- key="main_uploader"
361
- )
362
 
363
- # Instruções
364
- with st.expander("📋 Instruções de Uso", expanded=True):
365
  st.markdown("""
366
- **Como usar este dashboard:**
367
-
368
- 1. **📁 Faça upload** do dataset de reservas de hotel (formato CSV)
369
- 2. **🔄 Aguarde o processamento** automático dos dados
370
- 3. **⚙️ Configure** o algoritmo e parâmetros desejados
371
- 4. **🚀 Treine o modelo** e analise os resultados
372
- 5. **📊 Compare** o desempenho entre diferentes modelos
373
 
374
- **Requisitos do dataset:**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  - Formato CSV
376
- - Deve conter uma coluna target (cancelamento)
377
- - Colunas típicas: `lead_time`, `adr`, `adults`, `is_canceled`, etc.
378
- - Suporta o dataset "Hotel Booking Demand" do Kaggle
379
  """)
380
-
381
- # Processar o arquivo assim que for carregado
382
- if uploaded_file is not None:
383
- try:
384
- with st.spinner("📊 Carregando e analisando o dataset..."):
385
- # Ler o arquivo
386
- df = pd.read_csv(uploaded_file)
387
-
388
- # Mostrar informações básicas
389
- st.success(f" Dataset carregado: {df.shape[0]} linhas × {df.shape[1]} colunas")
390
-
391
- # Preview do dataset
392
- with st.expander("👀 Visualização do Dataset (primeiras 10 linhas)"):
393
- st.dataframe(df.head(10), use_container_width=True)
394
-
395
- # Informações das colunas
396
- with st.expander("📋 Informações das Colunas"):
397
- col1, col2 = st.columns(2)
398
- with col1:
399
- st.write("**Colunas Numéricas:**")
400
- numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
401
- for col in numeric_cols[:10]: # Mostrar apenas as primeiras 10
402
- st.write(f"- {col}")
403
- if len(numeric_cols) > 10:
404
- st.write(f"- ... e mais {len(numeric_cols) - 10} colunas")
405
- with col2:
406
- st.write("**Colunas Categóricas:**")
407
- categorical_cols = df.select_dtypes(include=['object']).columns.tolist()
408
- for col in categorical_cols[:10]: # Mostrar apenas as primeiras 10
409
- st.write(f"- {col}")
410
- if len(categorical_cols) > 10:
411
- st.write(f"- ... e mais {len(categorical_cols) - 10} colunas")
412
-
413
- # Processar automaticamente
414
- if st.button("🔄 Processar Dataset e Continuar", type="primary", use_container_width=True):
415
- with st.spinner("Processando dataset... Isso pode levar alguns segundos"):
416
  success = dashboard.load_and_preprocess_data(df)
417
-
418
  if success:
419
  st.session_state.data_processed = True
420
  st.session_state.dashboard = dashboard
421
  st.rerun()
422
- else:
423
- st.error("Falha no processamento do dataset. Verifique os dados e tente novamente.")
424
-
425
- except Exception as e:
426
- st.error(f"❌ Erro ao carregar arquivo: {str(e)}")
427
- st.info("💡 **Dica:** Verifique se o arquivo é um CSV válido e tente novamente.")
428
 
429
- # Exemplo de estrutura esperada
430
- with st.expander("🎯 Exemplo de Dataset Compatível"):
431
  st.markdown("""
432
- **Estrutura típica do dataset Hotel Booking Demand:**
433
- ```csv
434
- hotel,lead_time,arrival_date_year,arrival_date_month,arrival_date_week_number,
435
- arrival_date_day_of_month,stays_in_weekend_nights,stays_in_week_nights,adults,
436
- children,babies,meal,country,market_segment,distribution_channel,
437
- is_repeated_guest,previous_cancellations,previous_bookings_not_canceled,
438
- reserved_room_type,assigned_room_type,booking_changes,deposit_type,agent,
439
- company,days_in_waiting_list,customer_type,adr,required_car_parking_spaces,
440
- total_of_special_requests,reservation_status,is_canceled
441
- ```
442
-
443
- **Coluna target:** `is_canceled` (1 = cancelado, 0 = não cancelado)
 
 
444
  """)
445
 
446
  return
@@ -462,7 +479,7 @@ def main():
462
  )
463
 
464
  # Parâmetros específicos
465
- st.sidebar.subheader("📊 Parámetros do Modelo")
466
 
467
  if algorithm == "Regressão Logística":
468
  st.sidebar.markdown('<div class="parameter-section">', unsafe_allow_html=True)
@@ -527,23 +544,19 @@ def main():
527
  # Distribuição do target
528
  fig, ax = plt.subplots(figsize=(8, 6))
529
  balance = pd.Series(dashboard.y_train).value_counts()
530
- labels = ['Não Cancelado', 'Cancelado'] if len(balance) == 2 else [f'Classe {i}' for i in balance.index]
531
- ax.pie(balance.values, labels=labels, autopct='%1.1f%%', startangle=90)
532
- ax.set_title('Distribuição do Target')
533
  st.pyplot(fig)
534
 
535
  with col2:
536
  # Estatísticas básicas
537
  st.write("**Estatísticas do Dataset:**")
538
- total_samples = dashboard.X_train.shape[0] + dashboard.X_test.shape[0]
539
- cancel_rate = (dashboard.y_train.sum() + dashboard.y_test.sum()) / total_samples * 100
540
-
541
  stats_df = pd.DataFrame({
542
  'Métrica': ['Total de Amostras', 'Features', 'Taxa de Cancelamento', 'Balanceamento'],
543
  'Valor': [
544
- f"{total_samples:,}",
545
  f"{dashboard.X_train.shape[1]}",
546
- f"{cancel_rate:.1f}%",
547
  f"{balance[0]}:{balance[1]}" if len(balance) == 2 else "Múltiplas classes"
548
  ]
549
  })
 
1
+ # app.py - Dashboard Interativo com Dataset do Hugging Face
2
  import streamlit as st
3
  import pandas as pd
4
  import numpy as np
 
26
  st.warning(f"⚠️ SMOTE não disponível: {e}. Continuando sem balanceamento automático.")
27
  SMOTE_AVAILABLE = False
28
 
29
+ # Tentar importar a biblioteca datasets do Hugging Face
30
+ try:
31
+ from datasets import load_dataset
32
+ DATASETS_AVAILABLE = True
33
+ except ImportError as e:
34
+ st.error(f"❌ Biblioteca 'datasets' não disponível: {e}")
35
+ DATASETS_AVAILABLE = False
36
+
37
  # Configuração da página
38
  st.set_page_config(
39
  page_title="Dashboard - Cancelamento de Reservas",
 
101
  self.scaler = StandardScaler()
102
  self.is_data_loaded = False
103
 
104
+ def load_huggingface_dataset(self):
105
+ """Carrega o dataset do Hugging Face"""
106
+ try:
107
+ with st.spinner("🌐 Carregando dataset do Hugging Face..."):
108
+ # Carregar o dataset
109
+ dataset = load_dataset("SIEP/hotel_bookings")
110
+
111
+ # Converter para pandas DataFrame
112
+ if 'train' in dataset:
113
+ df = dataset['train'].to_pandas()
114
+ else:
115
+ # Se não tiver split 'train', pega o primeiro split disponível
116
+ first_split = list(dataset.keys())[0]
117
+ df = dataset[first_split].to_pandas()
118
+
119
+ st.success(f"✅ Dataset carregado: {df.shape[0]} linhas × {df.shape[1]} colunas")
120
+ return df
121
+
122
+ except Exception as e:
123
+ st.error(f"❌ Erro ao carregar dataset do Hugging Face: {str(e)}")
124
+ return None
125
+
126
  def load_and_preprocess_data(self, df):
127
  """Carrega e pré-processa o dataset"""
128
  try:
 
373
  if not dashboard.is_data_loaded:
374
  st.markdown("""
375
  <div class="data-source-section">
376
+ <h2>📊 Escolha a Fonte dos Dados</h2>
377
  <p style="font-size: 1.2rem; margin-bottom: 1.5rem;">
378
+ <strong>Carregue os dados do Hugging Face ou faça upload do seu próprio dataset</strong>
379
  </p>
380
  </div>
381
  """, unsafe_allow_html=True)
382
 
383
+ # Opções de carregamento
384
+ col1, col2 = st.columns(2)
 
 
 
 
 
 
 
385
 
386
+ with col1:
387
+ st.markdown("### 🌐 Dataset do Hugging Face")
388
  st.markdown("""
389
+ **Vantagens:**
390
+ - Dataset pré-processado
391
+ - Estrutura consistente
392
+ - Sem necessidade de upload
393
+ """)
 
 
394
 
395
+ if DATASETS_AVAILABLE:
396
+ if st.button("🚀 Carregar do Hugging Face", type="primary", use_container_width=True):
397
+ with st.spinner("Carregando dataset SIEP/hotel_bookings..."):
398
+ df = dashboard.load_huggingface_dataset()
399
+ if df is not None:
400
+ success = dashboard.load_and_preprocess_data(df)
401
+ if success:
402
+ st.session_state.data_processed = True
403
+ st.session_state.dashboard = dashboard
404
+ st.rerun()
405
+ else:
406
+ st.error("Biblioteca 'datasets' não disponível")
407
+ st.info("Adicione 'datasets' ao requirements.txt")
408
+
409
+ with col2:
410
+ st.markdown("### 📁 Upload Manual")
411
+ st.markdown("""
412
+ **Use seu próprio dataset:**
413
  - Formato CSV
414
+ - Coluna target: 'is_canceled'
415
+ - Estrutura personalizada
 
416
  """)
417
+
418
+ uploaded_file = st.file_uploader(
419
+ "Selecione o arquivo CSV",
420
+ type=['csv'],
421
+ help="Faça upload do dataset de reservas de hotel"
422
+ )
423
+
424
+ if uploaded_file is not None:
425
+ try:
426
+ with st.spinner("Carregando arquivo..."):
427
+ df = pd.read_csv(uploaded_file)
428
+ st.success(f"✅ Dataset carregado: {df.shape[0]} linhas × {df.shape[1]} colunas")
429
+
430
+ # Preview
431
+ with st.expander("👀 Visualizar Dataset"):
432
+ st.dataframe(df.head(10))
433
+
434
+ if st.button("🔄 Processar Dataset", type="primary", use_container_width=True):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  success = dashboard.load_and_preprocess_data(df)
 
436
  if success:
437
  st.session_state.data_processed = True
438
  st.session_state.dashboard = dashboard
439
  st.rerun()
440
+
441
+ except Exception as e:
442
+ st.error(f"❌ Erro ao carregar arquivo: {str(e)}")
 
 
 
443
 
444
+ # Informações sobre o dataset
445
+ with st.expander("📋 Sobre o Dataset", expanded=True):
446
  st.markdown("""
447
+ **Dataset: Hotel Bookings (SIEP/hotel_bookings)**
448
+
449
+ Este dataset contém informações de reservas de hotel incluindo:
450
+
451
+ **Variáveis Principais:**
452
+ - `is_canceled`: Indicador de cancelamento (target)
453
+ - `lead_time`: Tempo entre reserva e chegada
454
+ - `adr`: Taxa diária média
455
+ - `adults`, `children`, `babies`: Número de hóspedes
456
+ - `country`, `market_segment`: Informações demográficas
457
+ - `previous_cancellations`: Histórico de cancelamentos
458
+ - `booking_changes`: Número de mudanças na reserva
459
+
460
+ **Objetivo:** Prever se uma reserva será cancelada com base nas características da reserva.
461
  """)
462
 
463
  return
 
479
  )
480
 
481
  # Parâmetros específicos
482
+ st.sidebar.subheader("📊 Parâmetros do Modelo")
483
 
484
  if algorithm == "Regressão Logística":
485
  st.sidebar.markdown('<div class="parameter-section">', unsafe_allow_html=True)
 
544
  # Distribuição do target
545
  fig, ax = plt.subplots(figsize=(8, 6))
546
  balance = pd.Series(dashboard.y_train).value_counts()
547
+ ax.pie(balance.values, labels=['Não Cancelado', 'Cancelado'], autopct='%1.1f%%', startangle=90)
548
+ ax.set_title('Distribuição de Cancelamentos')
 
549
  st.pyplot(fig)
550
 
551
  with col2:
552
  # Estatísticas básicas
553
  st.write("**Estatísticas do Dataset:**")
 
 
 
554
  stats_df = pd.DataFrame({
555
  'Métrica': ['Total de Amostras', 'Features', 'Taxa de Cancelamento', 'Balanceamento'],
556
  'Valor': [
557
+ f"{dashboard.X_train.shape[0] + dashboard.X_test.shape[0]:,}",
558
  f"{dashboard.X_train.shape[1]}",
559
+ f"{(dashboard.y_train.sum() + dashboard.y_test.sum()) / (len(dashboard.y_train) + len(dashboard.y_test)) * 100:.1f}%",
560
  f"{balance[0]}:{balance[1]}" if len(balance) == 2 else "Múltiplas classes"
561
  ]
562
  })