brunaaaz commited on
Commit
643f40b
·
verified ·
1 Parent(s): 99fb357

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -104
app.py CHANGED
@@ -1,4 +1,4 @@
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,14 +26,6 @@ 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
- # 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,28 +93,6 @@ class HotelBookingDashboard:
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,91 +343,104 @@ def main():
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,7 +462,7 @@ def main():
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,19 +527,23 @@ def main():
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
  })
 
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
  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
  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
  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
  )
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
  # 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
  })