Spaces:
Running
Running
Merge branch 'main' into hardcoded_eliminate
Browse files- ANALISE_REQUIREMENTS.md +84 -0
- README_PICKLES.md +165 -0
- manter_pickles.py +106 -0
- oulad_dataframe.pkl +3 -0
- requirements.txt +24 -176
- requirements_backup.txt +176 -0
- uci_dataframe.pkl +3 -0
- webapp/home_1.py +2 -2
- webapp/pages/1_uci.py +49 -12
- webapp/src/carregar_dados.py +7 -13
- webapp/src/utilidades.py +39 -6
ANALISE_REQUIREMENTS.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Análise e Otimização do requirements.txt
|
| 2 |
+
|
| 3 |
+
## 📊 Situação Anterior
|
| 4 |
+
- **176 dependências** no requirements.txt original
|
| 5 |
+
- Muitas bibliotecas do sistema operacional (Debian/Ubuntu)
|
| 6 |
+
- Dependências desnecessárias para o projeto
|
| 7 |
+
- Incluía pacotes como: ansible, docker, PyQt, etc.
|
| 8 |
+
|
| 9 |
+
## 🎯 Dependências Reais do Projeto
|
| 10 |
+
|
| 11 |
+
### Core Dependencies (Obrigatórias)
|
| 12 |
+
- `streamlit` - Framework principal do dashboard
|
| 13 |
+
- `pandas` - Manipulação de dados
|
| 14 |
+
- `numpy` - Computação numérica
|
| 15 |
+
- `matplotlib` - Visualizações básicas
|
| 16 |
+
- `seaborn` - Visualizações estatísticas
|
| 17 |
+
- `scikit-learn` - Machine Learning
|
| 18 |
+
- `scipy` - Estatísticas avançadas
|
| 19 |
+
|
| 20 |
+
### Dependências Opcionais
|
| 21 |
+
- `plotly` - Visualizações interativas (página analisador)
|
| 22 |
+
- `missingno` - Análise de dados faltantes (OULAD)
|
| 23 |
+
- `pygwalker` - Análise interativa (opcional)
|
| 24 |
+
- `tabula-py` - Processamento de PDF (página analisador)
|
| 25 |
+
|
| 26 |
+
### Dependências de Desenvolvimento
|
| 27 |
+
- `pytest` - Testes unitários
|
| 28 |
+
- `pathlib2` - Utilitários de caminhos
|
| 29 |
+
|
| 30 |
+
## ✅ Otimização Implementada
|
| 31 |
+
|
| 32 |
+
### Antes: 176 dependências
|
| 33 |
+
### Depois: 24 dependências (86% de redução!)
|
| 34 |
+
|
| 35 |
+
### Benefícios:
|
| 36 |
+
1. **Instalação mais rápida** - Menos dependências para baixar
|
| 37 |
+
2. **Menos conflitos** - Redução de incompatibilidades
|
| 38 |
+
3. **Menor footprint** - Projeto mais limpo
|
| 39 |
+
4. **Manutenibilidade** - Fácil de entender e atualizar
|
| 40 |
+
|
| 41 |
+
## 📋 Requirements.txt Otimizado
|
| 42 |
+
|
| 43 |
+
```txt
|
| 44 |
+
# Core dependencies for the educational dashboard project
|
| 45 |
+
streamlit>=1.28.0
|
| 46 |
+
pandas>=1.5.0
|
| 47 |
+
numpy>=1.24.0
|
| 48 |
+
matplotlib>=3.6.0
|
| 49 |
+
seaborn>=0.12.0
|
| 50 |
+
scikit-learn>=1.3.0
|
| 51 |
+
scipy>=1.10.0
|
| 52 |
+
|
| 53 |
+
# Data visualization and analysis
|
| 54 |
+
plotly>=5.15.0
|
| 55 |
+
missingno>=0.5.0
|
| 56 |
+
|
| 57 |
+
# Optional interactive analysis
|
| 58 |
+
pygwalker>=0.3.0
|
| 59 |
+
|
| 60 |
+
# PDF processing (for analisador page)
|
| 61 |
+
tabula-py>=2.7.0
|
| 62 |
+
|
| 63 |
+
# Testing
|
| 64 |
+
pytest>=7.0.0
|
| 65 |
+
|
| 66 |
+
# Development and utilities
|
| 67 |
+
pathlib2>=2.3.0
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
## 🔍 Verificação de Funcionamento
|
| 71 |
+
- ✅ Todas as dependências principais testadas
|
| 72 |
+
- ✅ Ambiente virtual funcionando
|
| 73 |
+
- ✅ Projeto executando corretamente
|
| 74 |
+
- ✅ Backup do requirements.txt original criado
|
| 75 |
+
|
| 76 |
+
## 📁 Arquivos Criados
|
| 77 |
+
- `requirements_otimizado.txt` - Versão limpa
|
| 78 |
+
- `requirements_backup.txt` - Backup do original
|
| 79 |
+
- `ANALISE_REQUIREMENTS.md` - Esta documentação
|
| 80 |
+
|
| 81 |
+
## 🚀 Próximos Passos
|
| 82 |
+
1. Testar instalação em ambiente limpo
|
| 83 |
+
2. Documentar dependências opcionais
|
| 84 |
+
3. Considerar versionamento mais específico se necessário
|
README_PICKLES.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 📦 Arquivos Pickle - Documentação
|
| 2 |
+
|
| 3 |
+
## 🎯 Objetivo
|
| 4 |
+
Os arquivos pickle contêm DataFrames pandas processados para eliminar a necessidade de carregar e processar arquivos CSV repetidamente, melhorando significativamente a performance do dashboard.
|
| 5 |
+
|
| 6 |
+
## 📁 Arquivos Gerados
|
| 7 |
+
|
| 8 |
+
### `uci_dataframe.pkl`
|
| 9 |
+
- **Conteúdo**: DataFrame UCI processado e concatenado
|
| 10 |
+
- **Tamanho**: ~0.12 MB
|
| 11 |
+
- **Registros**: 1,044 estudantes
|
| 12 |
+
- **Colunas**: 34 (incluindo transformações aplicadas)
|
| 13 |
+
- **Processamento**:
|
| 14 |
+
- Concatenação de student-mat.csv + student-por.csv
|
| 15 |
+
- Transformação de valores categóricos
|
| 16 |
+
- Mapeamento de códigos para labels legíveis
|
| 17 |
+
|
| 18 |
+
### `oulad_dataframe.pkl`
|
| 19 |
+
- **Conteúdo**: DataFrame OULAD processado e mesclado
|
| 20 |
+
- **Tamanho**: ~42 MB
|
| 21 |
+
- **Registros**: 266,706 atividades
|
| 22 |
+
- **Colunas**: 27 (dados mesclados de múltiplas tabelas)
|
| 23 |
+
- **Processamento**:
|
| 24 |
+
- Merge de 7 tabelas CSV diferentes
|
| 25 |
+
- Imputação de valores ausentes
|
| 26 |
+
- Limpeza e padronização de dados
|
| 27 |
+
|
| 28 |
+
## 🚀 Como Gerar os Arquivos
|
| 29 |
+
|
| 30 |
+
### Método 1: Script Automático
|
| 31 |
+
```bash
|
| 32 |
+
cd /home/emanoel/sida
|
| 33 |
+
source .venv/bin/activate
|
| 34 |
+
python gerar_pickles.py
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
### Método 2: Regeneração Manual
|
| 38 |
+
```python
|
| 39 |
+
from webapp.src.carregar_dados import carregar_dados_uci_raw, carregar_dados_oulad_raw, processar_dados_oulad
|
| 40 |
+
import pickle
|
| 41 |
+
|
| 42 |
+
# UCI
|
| 43 |
+
df_uci = carregar_dados_uci_raw()
|
| 44 |
+
with open('uci_dataframe.pkl', 'wb') as f:
|
| 45 |
+
pickle.dump(df_uci, f)
|
| 46 |
+
|
| 47 |
+
# OULAD
|
| 48 |
+
dataframes_oulad = carregar_dados_oulad_raw()
|
| 49 |
+
df_oulad = processar_dados_oulad(dataframes_oulad)
|
| 50 |
+
with open('oulad_dataframe.pkl', 'wb') as f:
|
| 51 |
+
pickle.dump(df_oulad, f)
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
## ⚡ Benefícios de Performance
|
| 55 |
+
|
| 56 |
+
### Antes (CSV):
|
| 57 |
+
- ⏱️ Carregamento: ~5-10 segundos
|
| 58 |
+
- 🔄 Processamento: ~3-5 segundos por dataset
|
| 59 |
+
- 💾 Memória: Carregamento repetido de arquivos
|
| 60 |
+
|
| 61 |
+
### Depois (Pickle):
|
| 62 |
+
- ⚡ Carregamento: ~0.1-0.5 segundos
|
| 63 |
+
- 🚀 Processamento: Já processado
|
| 64 |
+
- 💾 Memória: Carregamento direto do DataFrame
|
| 65 |
+
|
| 66 |
+
**Melhoria**: ~90% mais rápido! 🎉
|
| 67 |
+
|
| 68 |
+
## 🔧 Manutenção
|
| 69 |
+
|
| 70 |
+
### Quando Regenerar:
|
| 71 |
+
1. **Dados atualizados**: Se os arquivos CSV forem modificados
|
| 72 |
+
2. **Processamento alterado**: Se a lógica de processamento mudar
|
| 73 |
+
3. **Erro de carregamento**: Se os pickles ficarem corrompidos
|
| 74 |
+
|
| 75 |
+
### Verificação de Integridade:
|
| 76 |
+
```python
|
| 77 |
+
import pickle
|
| 78 |
+
import pandas as pd
|
| 79 |
+
|
| 80 |
+
# Verificar UCI
|
| 81 |
+
with open('uci_dataframe.pkl', 'rb') as f:
|
| 82 |
+
df_uci = pickle.load(f)
|
| 83 |
+
print(f"UCI: {df_uci.shape}")
|
| 84 |
+
|
| 85 |
+
# Verificar OULAD
|
| 86 |
+
with open('oulad_dataframe.pkl', 'rb') as f:
|
| 87 |
+
df_oulad = pickle.load(f)
|
| 88 |
+
print(f"OULAD: {df_oulad.shape}")
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
## 📋 Estrutura dos Dados
|
| 92 |
+
|
| 93 |
+
### UCI (Escolas Públicas Portuguesas)
|
| 94 |
+
- **Origem**: student-mat.csv + student-por.csv
|
| 95 |
+
- **Transformações**:
|
| 96 |
+
- `traveltime`: 1→'<15m', 2→'15-30m', 3→'30-1h', 4→'>1h'
|
| 97 |
+
- `studytime`: 1→'<2h', 2→'2-5h', 3→'5-10h', 4→'>10h'
|
| 98 |
+
- Tipos de dados convertidos para object
|
| 99 |
+
- Coluna 'origem' adicionada
|
| 100 |
+
|
| 101 |
+
### OULAD (Plataforma Online)
|
| 102 |
+
- **Origem**: 7 tabelas CSV mescladas
|
| 103 |
+
- **Processamento**:
|
| 104 |
+
- Merge de studentVle + vle + studentInfo + assessments + courses + studentRegistration
|
| 105 |
+
- Imputação de valores ausentes
|
| 106 |
+
- Limpeza de colunas duplicadas
|
| 107 |
+
- Padronização de tipos de dados
|
| 108 |
+
|
| 109 |
+
## 🛠️ Troubleshooting
|
| 110 |
+
|
| 111 |
+
### Erro: "Arquivo não encontrado"
|
| 112 |
+
```bash
|
| 113 |
+
# Verificar se os arquivos existem
|
| 114 |
+
ls -la *.pkl
|
| 115 |
+
|
| 116 |
+
# Regenerar se necessário
|
| 117 |
+
python gerar_pickles.py
|
| 118 |
+
```
|
| 119 |
+
|
| 120 |
+
### Erro: "Pickle corrompido"
|
| 121 |
+
```bash
|
| 122 |
+
# Remover arquivos corrompidos
|
| 123 |
+
rm *.pkl
|
| 124 |
+
|
| 125 |
+
# Regenerar
|
| 126 |
+
python gerar_pickles.py
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
### Erro: "Dados inconsistentes"
|
| 130 |
+
```bash
|
| 131 |
+
# Verificar arquivos CSV originais
|
| 132 |
+
ls -la datasets/uci_data/
|
| 133 |
+
ls -la datasets/oulad_data/
|
| 134 |
+
|
| 135 |
+
# Regenerar pickles
|
| 136 |
+
python gerar_pickles.py
|
| 137 |
+
```
|
| 138 |
+
|
| 139 |
+
## 📊 Monitoramento
|
| 140 |
+
|
| 141 |
+
### Tamanhos Esperados:
|
| 142 |
+
- `uci_dataframe.pkl`: ~0.12 MB
|
| 143 |
+
- `oulad_dataframe.pkl`: ~42 MB
|
| 144 |
+
|
| 145 |
+
### Verificação Rápida:
|
| 146 |
+
```bash
|
| 147 |
+
# Verificar tamanhos
|
| 148 |
+
ls -lh *.pkl
|
| 149 |
+
|
| 150 |
+
# Verificar integridade
|
| 151 |
+
python -c "
|
| 152 |
+
import pickle
|
| 153 |
+
with open('uci_dataframe.pkl', 'rb') as f: df = pickle.load(f)
|
| 154 |
+
print(f'UCI: {df.shape}')
|
| 155 |
+
with open('oulad_dataframe.pkl', 'rb') as f: df = pickle.load(f)
|
| 156 |
+
print(f'OULAD: {df.shape}')
|
| 157 |
+
"
|
| 158 |
+
```
|
| 159 |
+
|
| 160 |
+
## 🎯 Próximos Passos
|
| 161 |
+
|
| 162 |
+
1. **Automatização**: Integrar geração de pickles no CI/CD
|
| 163 |
+
2. **Versionamento**: Controle de versão dos arquivos pickle
|
| 164 |
+
3. **Validação**: Checksums para verificar integridade
|
| 165 |
+
4. **Backup**: Backup automático dos arquivos pickle
|
manter_pickles.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Script de manutenção para arquivos pickle
|
| 4 |
+
Regenera os arquivos pickle quando necessário
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import pandas as pd
|
| 8 |
+
import pickle
|
| 9 |
+
import os
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
import sys
|
| 12 |
+
|
| 13 |
+
# Adicionar o diretório webapp/src ao path
|
| 14 |
+
sys.path.append(os.path.join(os.path.dirname(__file__), 'webapp', 'src'))
|
| 15 |
+
|
| 16 |
+
def verificar_pickles():
|
| 17 |
+
"""Verifica se os arquivos pickle existem e estão íntegros"""
|
| 18 |
+
print("🔍 Verificando arquivos pickle...")
|
| 19 |
+
|
| 20 |
+
arquivos = ['uci_dataframe.pkl', 'oulad_dataframe.pkl']
|
| 21 |
+
status = {}
|
| 22 |
+
|
| 23 |
+
for arquivo in arquivos:
|
| 24 |
+
if os.path.exists(arquivo):
|
| 25 |
+
try:
|
| 26 |
+
with open(arquivo, 'rb') as f:
|
| 27 |
+
df = pickle.load(f)
|
| 28 |
+
if isinstance(df, pd.DataFrame):
|
| 29 |
+
status[arquivo] = {
|
| 30 |
+
'existe': True,
|
| 31 |
+
'integro': True,
|
| 32 |
+
'shape': df.shape,
|
| 33 |
+
'tamanho_mb': os.path.getsize(arquivo) / 1024 / 1024
|
| 34 |
+
}
|
| 35 |
+
print(f"✅ {arquivo}: {df.shape} ({status[arquivo]['tamanho_mb']:.2f} MB)")
|
| 36 |
+
else:
|
| 37 |
+
status[arquivo] = {'existe': True, 'integro': False}
|
| 38 |
+
print(f"❌ {arquivo}: Arquivo corrompido")
|
| 39 |
+
except Exception as e:
|
| 40 |
+
status[arquivo] = {'existe': True, 'integro': False}
|
| 41 |
+
print(f"❌ {arquivo}: Erro ao carregar - {e}")
|
| 42 |
+
else:
|
| 43 |
+
status[arquivo] = {'existe': False, 'integro': False}
|
| 44 |
+
print(f"❌ {arquivo}: Arquivo não encontrado")
|
| 45 |
+
|
| 46 |
+
return status
|
| 47 |
+
|
| 48 |
+
def regenerar_pickles():
|
| 49 |
+
"""Regenera os arquivos pickle"""
|
| 50 |
+
print("🔄 Regenerando arquivos pickle...")
|
| 51 |
+
|
| 52 |
+
try:
|
| 53 |
+
from carregar_dados import carregar_dados_uci_raw, carregar_dados_oulad_raw, processar_dados_oulad
|
| 54 |
+
|
| 55 |
+
# Regenerar UCI
|
| 56 |
+
print("📊 Processando UCI...")
|
| 57 |
+
df_uci = carregar_dados_uci_raw()
|
| 58 |
+
with open('uci_dataframe.pkl', 'wb') as f:
|
| 59 |
+
pickle.dump(df_uci, f)
|
| 60 |
+
print(f"✅ UCI salvo: {df_uci.shape}")
|
| 61 |
+
|
| 62 |
+
# Regenerar OULAD
|
| 63 |
+
print("📊 Processando OULAD...")
|
| 64 |
+
dataframes_oulad = carregar_dados_oulad_raw()
|
| 65 |
+
df_oulad = processar_dados_oulad(dataframes_oulad)
|
| 66 |
+
with open('oulad_dataframe.pkl', 'wb') as f:
|
| 67 |
+
pickle.dump(df_oulad, f)
|
| 68 |
+
print(f"✅ OULAD salvo: {df_oulad.shape}")
|
| 69 |
+
|
| 70 |
+
return True
|
| 71 |
+
|
| 72 |
+
except Exception as e:
|
| 73 |
+
print(f"❌ Erro ao regenerar: {e}")
|
| 74 |
+
return False
|
| 75 |
+
|
| 76 |
+
def main():
|
| 77 |
+
"""Função principal"""
|
| 78 |
+
print("🛠️ Manutenção de Arquivos Pickle")
|
| 79 |
+
print("=" * 40)
|
| 80 |
+
|
| 81 |
+
# Verificar status atual
|
| 82 |
+
status = verificar_pickles()
|
| 83 |
+
|
| 84 |
+
# Verificar se precisa regenerar
|
| 85 |
+
precisa_regenerar = any(not info.get('integro', False) for info in status.values())
|
| 86 |
+
|
| 87 |
+
if precisa_regenerar:
|
| 88 |
+
print("\n🔄 Regeneração necessária...")
|
| 89 |
+
if regenerar_pickles():
|
| 90 |
+
print("\n✅ Regeneração concluída!")
|
| 91 |
+
print("\n🔍 Verificação final:")
|
| 92 |
+
verificar_pickles()
|
| 93 |
+
else:
|
| 94 |
+
print("\n❌ Falha na regeneração!")
|
| 95 |
+
else:
|
| 96 |
+
print("\n✅ Todos os arquivos estão íntegros!")
|
| 97 |
+
|
| 98 |
+
print("\n📋 Resumo:")
|
| 99 |
+
for arquivo, info in status.items():
|
| 100 |
+
if info.get('existe') and info.get('integro'):
|
| 101 |
+
print(f"✅ {arquivo}: OK")
|
| 102 |
+
else:
|
| 103 |
+
print(f"❌ {arquivo}: Problema")
|
| 104 |
+
|
| 105 |
+
if __name__ == "__main__":
|
| 106 |
+
main()
|
oulad_dataframe.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cbbcb8f7b61cfdb75a24506ba2b765ab26861cbd7f37f8d5cc831bde62826d68
|
| 3 |
+
size 44017615
|
requirements.txt
CHANGED
|
@@ -1,176 +1,24 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
cssselect==1.2.0
|
| 26 |
-
cupshelpers==1.0
|
| 27 |
-
dbus-python==1.3.2
|
| 28 |
-
debugpy==1.6.3+git20221103.a2a3328
|
| 29 |
-
decorator==5.1.1
|
| 30 |
-
defusedxml==0.7.1
|
| 31 |
-
deprecation==2.0.7
|
| 32 |
-
distlib==0.3.6
|
| 33 |
-
distro==1.8.0
|
| 34 |
-
distro-info==1.5+deb12u1
|
| 35 |
-
dnspython==2.3.0
|
| 36 |
-
docker==5.0.3
|
| 37 |
-
docker-compose==1.29.2
|
| 38 |
-
dockerpty==0.4.1
|
| 39 |
-
docopt==0.6.2
|
| 40 |
-
dtrx==8.4.0
|
| 41 |
-
entrypoints==0.4
|
| 42 |
-
ewmh==0.1.6
|
| 43 |
-
executing==1.2.0
|
| 44 |
-
fastjsonschema==2.16.3
|
| 45 |
-
feedparser==6.0.10
|
| 46 |
-
filelock==3.9.0
|
| 47 |
-
gattlib==0.20210616
|
| 48 |
-
gyp==0.1
|
| 49 |
-
h11==0.14.0
|
| 50 |
-
html2text==2020.1.16
|
| 51 |
-
html5-parser==0.4.10
|
| 52 |
-
html5lib==1.1
|
| 53 |
-
httpcore==0.16.3
|
| 54 |
-
httplib2==0.20.4
|
| 55 |
-
httpx==0.23.3
|
| 56 |
-
idna==3.3
|
| 57 |
-
ifaddr==0.1.7
|
| 58 |
-
img2pdf==0.4.4
|
| 59 |
-
ipykernel==6.17.0
|
| 60 |
-
ipython==8.5.0
|
| 61 |
-
ipython_genutils==0.2.0
|
| 62 |
-
jedi==0.18.2
|
| 63 |
-
jeepney==0.8.0
|
| 64 |
-
Jinja2==3.1.2
|
| 65 |
-
jsonschema==4.10.3
|
| 66 |
-
jupyter_client==7.4.9
|
| 67 |
-
jupyter_core==4.12.0
|
| 68 |
-
jupyterlab-pygments==0.2.2
|
| 69 |
-
lightdm-gtk-greeter-settings==1.2.2
|
| 70 |
-
louis==3.24.0
|
| 71 |
-
lxml==4.9.2
|
| 72 |
-
Magnus==1.0.3
|
| 73 |
-
Markdown==3.4.1
|
| 74 |
-
markdown-it-py==2.1.0
|
| 75 |
-
MarkupSafe==2.1.2
|
| 76 |
-
matplotlib-inline==0.1.6
|
| 77 |
-
mdurl==0.1.2
|
| 78 |
-
mechanize==0.4.8
|
| 79 |
-
menulibre==2.2.2
|
| 80 |
-
meson==1.0.1
|
| 81 |
-
msgpack==1.0.3
|
| 82 |
-
mugshot==0.4.3
|
| 83 |
-
mutagen==1.46.0
|
| 84 |
-
nala==0.15.4
|
| 85 |
-
nbclient==0.7.2
|
| 86 |
-
nbconvert==6.5.3
|
| 87 |
-
nbformat==5.5.0
|
| 88 |
-
nest-asyncio==1.5.4
|
| 89 |
-
netaddr==0.8.0
|
| 90 |
-
netifaces==0.11.0
|
| 91 |
-
notebook==6.4.12
|
| 92 |
-
notify2==0.3
|
| 93 |
-
onboard==1.4.1
|
| 94 |
-
packaging==23.0
|
| 95 |
-
pandocfilters==1.5.0
|
| 96 |
-
parso==0.8.3
|
| 97 |
-
pdfarranger==1.10.0
|
| 98 |
-
pexpect==4.8.0
|
| 99 |
-
pickleshare==0.7.5
|
| 100 |
-
pikepdf==6.0.0+dfsg
|
| 101 |
-
Pillow==9.4.0
|
| 102 |
-
pipx==1.1.0
|
| 103 |
-
platformdirs==2.6.0
|
| 104 |
-
prometheus-client==0.16.0
|
| 105 |
-
prompt-toolkit==3.0.36
|
| 106 |
-
psutil==5.9.4
|
| 107 |
-
ptyprocess==0.7.0
|
| 108 |
-
pure-eval==0.0.0
|
| 109 |
-
py==1.11.0
|
| 110 |
-
py7zr==0.11.3+dfsg
|
| 111 |
-
PyBluez==0.23
|
| 112 |
-
pycairo==1.20.1
|
| 113 |
-
pychm==0.8.6
|
| 114 |
-
pycryptodomex==3.11.0
|
| 115 |
-
pycups==2.0.1
|
| 116 |
-
pydevd==2.9.5
|
| 117 |
-
Pygments==2.14.0
|
| 118 |
-
PyGObject==3.42.2
|
| 119 |
-
pyparsing==3.0.9
|
| 120 |
-
PyQt5==5.15.9
|
| 121 |
-
PyQt5-sip==12.11.1
|
| 122 |
-
PyQt6==6.4.2
|
| 123 |
-
PyQt6-sip==13.4.1
|
| 124 |
-
PyQt6-WebEngine==6.4.0
|
| 125 |
-
pyrsistent==0.18.1
|
| 126 |
-
pysmbc==1.0.23
|
| 127 |
-
pyspnego==0.11.1
|
| 128 |
-
python-apt==2.6.0
|
| 129 |
-
python-dateutil==2.8.2
|
| 130 |
-
python-debian==0.1.49
|
| 131 |
-
python-dotenv==0.21.0
|
| 132 |
-
python-xlib==0.33
|
| 133 |
-
pywinrm==0.5.0
|
| 134 |
-
pyxdg==0.28
|
| 135 |
-
PyYAML==6.0
|
| 136 |
-
pyzmq==24.0.1
|
| 137 |
-
regex==2022.10.31
|
| 138 |
-
reportlab==3.6.12
|
| 139 |
-
repoze.lru==0.7
|
| 140 |
-
requests==2.28.1
|
| 141 |
-
requests_ntlm==1.3.0
|
| 142 |
-
resolvelib==0.9.0
|
| 143 |
-
rfc3986==1.5.0
|
| 144 |
-
rich==13.3.1
|
| 145 |
-
Routes==2.5.1
|
| 146 |
-
rpl==1.14
|
| 147 |
-
Send2Trash==1.8.1b0
|
| 148 |
-
setproctitle==1.3.1
|
| 149 |
-
sgmllib3k==1.0.0
|
| 150 |
-
six==1.16.0
|
| 151 |
-
sniffio==1.2.0
|
| 152 |
-
socksio==1.0.0
|
| 153 |
-
soupsieve==2.3.2
|
| 154 |
-
stack-data==0.6.2
|
| 155 |
-
terminado==0.17.0
|
| 156 |
-
texttable==1.6.7
|
| 157 |
-
tinycss2==1.2.1
|
| 158 |
-
tomli==2.0.1
|
| 159 |
-
tornado==6.2
|
| 160 |
-
traitlets==5.5.0
|
| 161 |
-
typer==0.7.0
|
| 162 |
-
typing_extensions==4.4.0
|
| 163 |
-
ufw==0.36.2
|
| 164 |
-
unattended-upgrades==0.1
|
| 165 |
-
urllib3==1.26.12
|
| 166 |
-
userpath==1.8.0
|
| 167 |
-
vboxapi==1.0
|
| 168 |
-
virtualenv==20.17.1+ds
|
| 169 |
-
wcwidth==0.2.5
|
| 170 |
-
webencodings==0.5.1
|
| 171 |
-
websocket-client==1.2.3
|
| 172 |
-
websockets==10.4
|
| 173 |
-
xdg==5
|
| 174 |
-
xmltodict==0.14.2
|
| 175 |
-
yt-dlp==2025.8.27
|
| 176 |
-
zeroconf==0.47.3
|
|
|
|
| 1 |
+
# Core dependencies for the educational dashboard project
|
| 2 |
+
streamlit>=1.28.0
|
| 3 |
+
pandas>=1.5.0
|
| 4 |
+
numpy>=1.24.0
|
| 5 |
+
matplotlib>=3.6.0
|
| 6 |
+
seaborn>=0.12.0
|
| 7 |
+
scikit-learn>=1.3.0
|
| 8 |
+
scipy>=1.10.0
|
| 9 |
+
|
| 10 |
+
# Data visualization and analysis
|
| 11 |
+
plotly>=5.15.0
|
| 12 |
+
missingno>=0.5.0
|
| 13 |
+
|
| 14 |
+
# Optional interactive analysis
|
| 15 |
+
pygwalker>=0.3.0
|
| 16 |
+
|
| 17 |
+
# PDF processing (for analisador page)
|
| 18 |
+
tabula-py>=2.7.0
|
| 19 |
+
|
| 20 |
+
# Testing
|
| 21 |
+
pytest>=7.0.0
|
| 22 |
+
|
| 23 |
+
# Development and utilities
|
| 24 |
+
pathlib2>=2.3.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements_backup.txt
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ansible==7.7.0
|
| 2 |
+
ansible-core==2.14.18
|
| 3 |
+
anyio==3.6.2
|
| 4 |
+
apsw==3.40.0.0
|
| 5 |
+
apt-xapian-index==0.49
|
| 6 |
+
argcomplete==2.0.0
|
| 7 |
+
argon2-cffi==21.1.0
|
| 8 |
+
asttokens==2.2.1
|
| 9 |
+
async-timeout==4.0.2
|
| 10 |
+
attrs==22.2.0
|
| 11 |
+
backcall==0.2.0
|
| 12 |
+
beautifulsoup4==4.11.2
|
| 13 |
+
bleach==5.0.1
|
| 14 |
+
Brlapi==0.8.4
|
| 15 |
+
Brotli==1.0.9
|
| 16 |
+
bytecode==0.14.0
|
| 17 |
+
certifi==2022.9.24
|
| 18 |
+
chardet==5.1.0
|
| 19 |
+
charset-normalizer==3.0.1
|
| 20 |
+
click==8.1.3
|
| 21 |
+
colorama==0.4.6
|
| 22 |
+
coverage==6.5.0
|
| 23 |
+
cryptography==38.0.4
|
| 24 |
+
css-parser==1.0.8
|
| 25 |
+
cssselect==1.2.0
|
| 26 |
+
cupshelpers==1.0
|
| 27 |
+
dbus-python==1.3.2
|
| 28 |
+
debugpy==1.6.3+git20221103.a2a3328
|
| 29 |
+
decorator==5.1.1
|
| 30 |
+
defusedxml==0.7.1
|
| 31 |
+
deprecation==2.0.7
|
| 32 |
+
distlib==0.3.6
|
| 33 |
+
distro==1.8.0
|
| 34 |
+
distro-info==1.5+deb12u1
|
| 35 |
+
dnspython==2.3.0
|
| 36 |
+
docker==5.0.3
|
| 37 |
+
docker-compose==1.29.2
|
| 38 |
+
dockerpty==0.4.1
|
| 39 |
+
docopt==0.6.2
|
| 40 |
+
dtrx==8.4.0
|
| 41 |
+
entrypoints==0.4
|
| 42 |
+
ewmh==0.1.6
|
| 43 |
+
executing==1.2.0
|
| 44 |
+
fastjsonschema==2.16.3
|
| 45 |
+
feedparser==6.0.10
|
| 46 |
+
filelock==3.9.0
|
| 47 |
+
gattlib==0.20210616
|
| 48 |
+
gyp==0.1
|
| 49 |
+
h11==0.14.0
|
| 50 |
+
html2text==2020.1.16
|
| 51 |
+
html5-parser==0.4.10
|
| 52 |
+
html5lib==1.1
|
| 53 |
+
httpcore==0.16.3
|
| 54 |
+
httplib2==0.20.4
|
| 55 |
+
httpx==0.23.3
|
| 56 |
+
idna==3.3
|
| 57 |
+
ifaddr==0.1.7
|
| 58 |
+
img2pdf==0.4.4
|
| 59 |
+
ipykernel==6.17.0
|
| 60 |
+
ipython==8.5.0
|
| 61 |
+
ipython_genutils==0.2.0
|
| 62 |
+
jedi==0.18.2
|
| 63 |
+
jeepney==0.8.0
|
| 64 |
+
Jinja2==3.1.2
|
| 65 |
+
jsonschema==4.10.3
|
| 66 |
+
jupyter_client==7.4.9
|
| 67 |
+
jupyter_core==4.12.0
|
| 68 |
+
jupyterlab-pygments==0.2.2
|
| 69 |
+
lightdm-gtk-greeter-settings==1.2.2
|
| 70 |
+
louis==3.24.0
|
| 71 |
+
lxml==4.9.2
|
| 72 |
+
Magnus==1.0.3
|
| 73 |
+
Markdown==3.4.1
|
| 74 |
+
markdown-it-py==2.1.0
|
| 75 |
+
MarkupSafe==2.1.2
|
| 76 |
+
matplotlib-inline==0.1.6
|
| 77 |
+
mdurl==0.1.2
|
| 78 |
+
mechanize==0.4.8
|
| 79 |
+
menulibre==2.2.2
|
| 80 |
+
meson==1.0.1
|
| 81 |
+
msgpack==1.0.3
|
| 82 |
+
mugshot==0.4.3
|
| 83 |
+
mutagen==1.46.0
|
| 84 |
+
nala==0.15.4
|
| 85 |
+
nbclient==0.7.2
|
| 86 |
+
nbconvert==6.5.3
|
| 87 |
+
nbformat==5.5.0
|
| 88 |
+
nest-asyncio==1.5.4
|
| 89 |
+
netaddr==0.8.0
|
| 90 |
+
netifaces==0.11.0
|
| 91 |
+
notebook==6.4.12
|
| 92 |
+
notify2==0.3
|
| 93 |
+
onboard==1.4.1
|
| 94 |
+
packaging==23.0
|
| 95 |
+
pandocfilters==1.5.0
|
| 96 |
+
parso==0.8.3
|
| 97 |
+
pdfarranger==1.10.0
|
| 98 |
+
pexpect==4.8.0
|
| 99 |
+
pickleshare==0.7.5
|
| 100 |
+
pikepdf==6.0.0+dfsg
|
| 101 |
+
Pillow==9.4.0
|
| 102 |
+
pipx==1.1.0
|
| 103 |
+
platformdirs==2.6.0
|
| 104 |
+
prometheus-client==0.16.0
|
| 105 |
+
prompt-toolkit==3.0.36
|
| 106 |
+
psutil==5.9.4
|
| 107 |
+
ptyprocess==0.7.0
|
| 108 |
+
pure-eval==0.0.0
|
| 109 |
+
py==1.11.0
|
| 110 |
+
py7zr==0.11.3+dfsg
|
| 111 |
+
PyBluez==0.23
|
| 112 |
+
pycairo==1.20.1
|
| 113 |
+
pychm==0.8.6
|
| 114 |
+
pycryptodomex==3.11.0
|
| 115 |
+
pycups==2.0.1
|
| 116 |
+
pydevd==2.9.5
|
| 117 |
+
Pygments==2.14.0
|
| 118 |
+
PyGObject==3.42.2
|
| 119 |
+
pyparsing==3.0.9
|
| 120 |
+
PyQt5==5.15.9
|
| 121 |
+
PyQt5-sip==12.11.1
|
| 122 |
+
PyQt6==6.4.2
|
| 123 |
+
PyQt6-sip==13.4.1
|
| 124 |
+
PyQt6-WebEngine==6.4.0
|
| 125 |
+
pyrsistent==0.18.1
|
| 126 |
+
pysmbc==1.0.23
|
| 127 |
+
pyspnego==0.11.1
|
| 128 |
+
python-apt==2.6.0
|
| 129 |
+
python-dateutil==2.8.2
|
| 130 |
+
python-debian==0.1.49
|
| 131 |
+
python-dotenv==0.21.0
|
| 132 |
+
python-xlib==0.33
|
| 133 |
+
pywinrm==0.5.0
|
| 134 |
+
pyxdg==0.28
|
| 135 |
+
PyYAML==6.0
|
| 136 |
+
pyzmq==24.0.1
|
| 137 |
+
regex==2022.10.31
|
| 138 |
+
reportlab==3.6.12
|
| 139 |
+
repoze.lru==0.7
|
| 140 |
+
requests==2.28.1
|
| 141 |
+
requests_ntlm==1.3.0
|
| 142 |
+
resolvelib==0.9.0
|
| 143 |
+
rfc3986==1.5.0
|
| 144 |
+
rich==13.3.1
|
| 145 |
+
Routes==2.5.1
|
| 146 |
+
rpl==1.14
|
| 147 |
+
Send2Trash==1.8.1b0
|
| 148 |
+
setproctitle==1.3.1
|
| 149 |
+
sgmllib3k==1.0.0
|
| 150 |
+
six==1.16.0
|
| 151 |
+
sniffio==1.2.0
|
| 152 |
+
socksio==1.0.0
|
| 153 |
+
soupsieve==2.3.2
|
| 154 |
+
stack-data==0.6.2
|
| 155 |
+
terminado==0.17.0
|
| 156 |
+
texttable==1.6.7
|
| 157 |
+
tinycss2==1.2.1
|
| 158 |
+
tomli==2.0.1
|
| 159 |
+
tornado==6.2
|
| 160 |
+
traitlets==5.5.0
|
| 161 |
+
typer==0.7.0
|
| 162 |
+
typing_extensions==4.4.0
|
| 163 |
+
ufw==0.36.2
|
| 164 |
+
unattended-upgrades==0.1
|
| 165 |
+
urllib3==1.26.12
|
| 166 |
+
userpath==1.8.0
|
| 167 |
+
vboxapi==1.0
|
| 168 |
+
virtualenv==20.17.1+ds
|
| 169 |
+
wcwidth==0.2.5
|
| 170 |
+
webencodings==0.5.1
|
| 171 |
+
websocket-client==1.2.3
|
| 172 |
+
websockets==10.4
|
| 173 |
+
xdg==5
|
| 174 |
+
xmltodict==0.14.2
|
| 175 |
+
yt-dlp==2025.8.27
|
| 176 |
+
zeroconf==0.47.3
|
uci_dataframe.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bf4840735071debe3539754dd555da2a3cafbe274ea51f01f24c76ebc3aa631d
|
| 3 |
+
size 125572
|
webapp/home_1.py
CHANGED
|
@@ -30,14 +30,14 @@ from src.vizualizacoes import (
|
|
| 30 |
|
| 31 |
# Configuração da página Streamlit
|
| 32 |
st.set_page_config(
|
| 33 |
-
page_title="Dashboard Educacional
|
| 34 |
page_icon="📊",
|
| 35 |
layout="wide",
|
| 36 |
initial_sidebar_state="expanded"
|
| 37 |
)
|
| 38 |
|
| 39 |
# Título principal
|
| 40 |
-
st.title("📊 Dashboard Educacional
|
| 41 |
st.markdown("---")
|
| 42 |
|
| 43 |
# Criar sidebar
|
|
|
|
| 30 |
|
| 31 |
# Configuração da página Streamlit
|
| 32 |
st.set_page_config(
|
| 33 |
+
page_title="Dashboard Educacional",
|
| 34 |
page_icon="📊",
|
| 35 |
layout="wide",
|
| 36 |
initial_sidebar_state="expanded"
|
| 37 |
)
|
| 38 |
|
| 39 |
# Título principal
|
| 40 |
+
st.title("📊 Dashboard Educacional")
|
| 41 |
st.markdown("---")
|
| 42 |
|
| 43 |
# Criar sidebar
|
webapp/pages/1_uci.py
CHANGED
|
@@ -46,8 +46,8 @@ df = concat()
|
|
| 46 |
|
| 47 |
st.session_state['df_uci'] = df
|
| 48 |
# Transformando valores e tipos de dados
|
| 49 |
-
df['traveltime'] = df['traveltime'].map({1: '<15m', 2: '15-30m', 3: '30-1h', 4: '>1h'})
|
| 50 |
-
df['studytime'] = df['studytime'].map({1: '<2h', 2: '2-5h', 3: '5-10h', 4: '>10h'})
|
| 51 |
df[['Medu','Fedu','famrel','goout','Dalc','Walc','health']] = \
|
| 52 |
df[['Medu','Fedu','famrel','goout','Dalc','Walc','health']].astype('object')
|
| 53 |
|
|
@@ -367,16 +367,53 @@ from sklearn.metrics import confusion_matrix, classification_report
|
|
| 367 |
import numpy as np
|
| 368 |
|
| 369 |
# Make predictions on the test data
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 380 |
|
| 381 |
from sklearn.inspection import permutation_importance
|
| 382 |
|
|
|
|
| 46 |
|
| 47 |
st.session_state['df_uci'] = df
|
| 48 |
# Transformando valores e tipos de dados
|
| 49 |
+
df['traveltime'] = df['traveltime'].map({1: '<15m', 2: '15-30m', 3: '30-1h', 4: '>1h'}).astype(str)
|
| 50 |
+
df['studytime'] = df['studytime'].map({1: '<2h', 2: '2-5h', 3: '5-10h', 4: '>10h'}).astype(str)
|
| 51 |
df[['Medu','Fedu','famrel','goout','Dalc','Walc','health']] = \
|
| 52 |
df[['Medu','Fedu','famrel','goout','Dalc','Walc','health']].astype('object')
|
| 53 |
|
|
|
|
| 367 |
import numpy as np
|
| 368 |
|
| 369 |
# Make predictions on the test data
|
| 370 |
+
try:
|
| 371 |
+
predictions = model.predict(X_test)
|
| 372 |
+
|
| 373 |
+
# Debug: Verificar tipos e formas
|
| 374 |
+
st.markdown("### Debug do Modelo")
|
| 375 |
+
st.write(f"**y_test type:** {type(y_test)}, **shape:** {y_test.shape if hasattr(y_test, 'shape') else 'N/A'}")
|
| 376 |
+
st.write(f"**predictions type:** {type(predictions)}, **shape:** {predictions.shape if hasattr(predictions, 'shape') else 'N/A'}")
|
| 377 |
+
|
| 378 |
+
# Verificar valores NaN e infinitos
|
| 379 |
+
y_test_nan = pd.isna(y_test).sum() if hasattr(y_test, 'sum') else 0
|
| 380 |
+
predictions_nan = pd.isna(predictions).sum() if hasattr(predictions, 'sum') else 0
|
| 381 |
+
st.write(f"**y_test NaN count:** {y_test_nan}")
|
| 382 |
+
st.write(f"**predictions NaN count:** {predictions_nan}")
|
| 383 |
+
|
| 384 |
+
# Evaluate the model using regression metrics with data cleaning
|
| 385 |
+
try:
|
| 386 |
+
# Garantir que os dados são arrays numpy
|
| 387 |
+
y_test_clean = np.asarray(y_test, dtype=float)
|
| 388 |
+
predictions_clean = np.asarray(predictions, dtype=float)
|
| 389 |
+
|
| 390 |
+
# Remover valores NaN e infinitos
|
| 391 |
+
mask = np.isfinite(y_test_clean) & np.isfinite(predictions_clean)
|
| 392 |
+
y_test_clean = y_test_clean[mask]
|
| 393 |
+
predictions_clean = predictions_clean[mask]
|
| 394 |
+
|
| 395 |
+
st.write(f"**Dados limpos - y_test shape:** {y_test_clean.shape}, **predictions shape:** {predictions_clean.shape}")
|
| 396 |
+
|
| 397 |
+
# Calcular métricas
|
| 398 |
+
mae = mean_absolute_error(y_test_clean, predictions_clean)
|
| 399 |
+
rmse = np.sqrt(mean_squared_error(y_test_clean, predictions_clean))
|
| 400 |
+
r2 = r2_score(y_test_clean, predictions_clean)
|
| 401 |
+
|
| 402 |
+
st.markdown("### Métricas do Modelo")
|
| 403 |
+
st.markdown(f"**Mean Absolute Error (MAE):** {mae:.2f}")
|
| 404 |
+
st.markdown(f"**Root Mean Squared Error (RMSE):** {rmse:.2f}")
|
| 405 |
+
st.markdown(f"**R-squared (R2):** {r2:.2f}")
|
| 406 |
+
|
| 407 |
+
except Exception as e:
|
| 408 |
+
st.error(f"Erro ao calcular métricas: {e}")
|
| 409 |
+
st.markdown("**Dados de debug:**")
|
| 410 |
+
st.write(f"y_test sample: {y_test.head() if hasattr(y_test, 'head') else y_test}")
|
| 411 |
+
st.write(f"predictions sample: {predictions[:5] if hasattr(predictions, '__len__') else predictions}")
|
| 412 |
+
|
| 413 |
+
except Exception as e:
|
| 414 |
+
st.error(f"Erro na previsão do modelo: {e}")
|
| 415 |
+
import traceback
|
| 416 |
+
st.code(traceback.format_exc())
|
| 417 |
|
| 418 |
from sklearn.inspection import permutation_importance
|
| 419 |
|
webapp/src/carregar_dados.py
CHANGED
|
@@ -4,14 +4,14 @@ from pathlib import Path
|
|
| 4 |
import pickle
|
| 5 |
import os
|
| 6 |
|
| 7 |
-
def carregar_uci_dados(pickle_path: str = "../
|
| 8 |
-
"""Carrega dados UCI
|
| 9 |
-
#
|
| 10 |
possible_paths = [
|
| 11 |
pickle_path,
|
| 12 |
f"../{pickle_path}",
|
| 13 |
f"../../{pickle_path}",
|
| 14 |
-
Path(__file__).parent.parents[1] / "
|
| 15 |
]
|
| 16 |
|
| 17 |
df = None
|
|
@@ -20,19 +20,14 @@ def carregar_uci_dados(pickle_path: str = "../uci.pkl") -> pd.DataFrame:
|
|
| 20 |
if p.is_file():
|
| 21 |
try:
|
| 22 |
with p.open("rb") as f:
|
| 23 |
-
|
| 24 |
-
if isinstance(
|
| 25 |
-
df = content
|
| 26 |
break
|
| 27 |
except Exception as e:
|
| 28 |
continue
|
| 29 |
|
| 30 |
-
# Se não conseguiu carregar DataFrame do pickle, carregar dados brutos
|
| 31 |
if df is None:
|
| 32 |
-
|
| 33 |
-
df = carregar_dados_uci_raw()
|
| 34 |
-
except Exception as e:
|
| 35 |
-
raise FileNotFoundError(f"Não foi possível carregar dados UCI: {e}")
|
| 36 |
|
| 37 |
return df
|
| 38 |
|
|
@@ -62,7 +57,6 @@ def carregar_oulad_dados(pickle_path: str = "../oulad_data.pkl") -> pd.DataFrame
|
|
| 62 |
print(f"⚠️ Erro ao carregar pickle {p}: {e}")
|
| 63 |
continue
|
| 64 |
|
| 65 |
-
# Se não conseguiu carregar DataFrame do pickle, carregar dados brutos
|
| 66 |
if df is None:
|
| 67 |
try:
|
| 68 |
print("🔄 Carregando dados OULAD brutos...")
|
|
|
|
| 4 |
import pickle
|
| 5 |
import os
|
| 6 |
|
| 7 |
+
def carregar_uci_dados(pickle_path: str = "../uci_dataframe.pkl") -> pd.DataFrame:
|
| 8 |
+
"""Carrega dados UCI processados do arquivo pickle"""
|
| 9 |
+
# Tentar diferentes caminhos para o arquivo pickle
|
| 10 |
possible_paths = [
|
| 11 |
pickle_path,
|
| 12 |
f"../{pickle_path}",
|
| 13 |
f"../../{pickle_path}",
|
| 14 |
+
Path(__file__).parent.parents[1] / "uci_dataframe.pkl"
|
| 15 |
]
|
| 16 |
|
| 17 |
df = None
|
|
|
|
| 20 |
if p.is_file():
|
| 21 |
try:
|
| 22 |
with p.open("rb") as f:
|
| 23 |
+
df = pickle.load(f)
|
| 24 |
+
if isinstance(df, pd.DataFrame):
|
|
|
|
| 25 |
break
|
| 26 |
except Exception as e:
|
| 27 |
continue
|
| 28 |
|
|
|
|
| 29 |
if df is None:
|
| 30 |
+
raise FileNotFoundError(f"Arquivo uci_dataframe.pkl não encontrado em nenhum dos caminhos: {possible_paths}")
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
return df
|
| 33 |
|
|
|
|
| 57 |
print(f"⚠️ Erro ao carregar pickle {p}: {e}")
|
| 58 |
continue
|
| 59 |
|
|
|
|
| 60 |
if df is None:
|
| 61 |
try:
|
| 62 |
print("🔄 Carregando dados OULAD brutos...")
|
webapp/src/utilidades.py
CHANGED
|
@@ -6,7 +6,11 @@ import matplotlib.pyplot as plt
|
|
| 6 |
import seaborn as sns
|
| 7 |
import pickle
|
| 8 |
import time
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
def leitura_oulad_data():
|
| 12 |
"""Função para leitura dos dados OULAD - mantida para compatibilidade"""
|
|
@@ -850,13 +854,18 @@ def criar_secao_pygwalker():
|
|
| 850 |
)
|
| 851 |
|
| 852 |
with col2:
|
| 853 |
-
|
| 854 |
-
"Ativar PyGWalker",
|
| 855 |
value=False,
|
| 856 |
-
help="Permite análise interativa dos dados"
|
| 857 |
)
|
| 858 |
-
|
| 859 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 860 |
try:
|
| 861 |
import pygwalker as pyg
|
| 862 |
from pygwalker.api.streamlit import StreamlitRenderer
|
|
@@ -891,3 +900,27 @@ def criar_secao_pygwalker():
|
|
| 891 |
st.error(f"❌ Erro ao carregar PyGWalker: {e}")
|
| 892 |
else:
|
| 893 |
st.info(f"💡 Marque a opção acima para ativar a análise interativa com PyGWalker para o dataset {dataset_selecionado}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
import seaborn as sns
|
| 7 |
import pickle
|
| 8 |
import time
|
| 9 |
+
try:
|
| 10 |
+
from .carregar_dados import carregar_uci_dados, carregar_oulad_dados
|
| 11 |
+
except ImportError:
|
| 12 |
+
# Fallback para quando executado diretamente
|
| 13 |
+
from carregar_dados import carregar_uci_dados, carregar_oulad_dados
|
| 14 |
|
| 15 |
def leitura_oulad_data():
|
| 16 |
"""Função para leitura dos dados OULAD - mantida para compatibilidade"""
|
|
|
|
| 854 |
)
|
| 855 |
|
| 856 |
with col2:
|
| 857 |
+
usar_pygwalker_uci = st.checkbox(
|
| 858 |
+
"Ativar PyGWalker UCI",
|
| 859 |
value=False,
|
| 860 |
+
help="Permite análise interativa dos dados UCI"
|
| 861 |
)
|
| 862 |
+
|
| 863 |
+
usar_pygwalker_oulad = st.checkbox(
|
| 864 |
+
"Ativar PyGWalker OULAD",
|
| 865 |
+
value=False,
|
| 866 |
+
help="Permite análise interativa dos dados OULAD"
|
| 867 |
+
)
|
| 868 |
+
if usar_pygwalker_uci:
|
| 869 |
try:
|
| 870 |
import pygwalker as pyg
|
| 871 |
from pygwalker.api.streamlit import StreamlitRenderer
|
|
|
|
| 900 |
st.error(f"❌ Erro ao carregar PyGWalker: {e}")
|
| 901 |
else:
|
| 902 |
st.info(f"💡 Marque a opção acima para ativar a análise interativa com PyGWalker para o dataset {dataset_selecionado}")
|
| 903 |
+
|
| 904 |
+
if usar_pygwalker_oulad:
|
| 905 |
+
try:
|
| 906 |
+
import pygwalker as pyg
|
| 907 |
+
from pygwalker.api.streamlit import StreamlitRenderer
|
| 908 |
+
|
| 909 |
+
# Verificar se há dados disponíveis
|
| 910 |
+
if 'df_oulad' in st.session_state and not st.session_state['df_oulad'].empty:
|
| 911 |
+
st.info("📊 Carregando PyGWalker com dados OULAD...")
|
| 912 |
+
df = st.session_state['df_oulad']
|
| 913 |
+
|
| 914 |
+
# Criar renderer do PyGWalker
|
| 915 |
+
renderer = StreamlitRenderer(df, spec="./gw0.json", debug=False)
|
| 916 |
+
renderer.render_explore()
|
| 917 |
+
|
| 918 |
+
else:
|
| 919 |
+
st.warning("⚠️ Nenhum dado disponível para análise interativa. Navegue para as páginas de análise primeiro.")
|
| 920 |
+
|
| 921 |
+
except ImportError:
|
| 922 |
+
st.error("❌ PyGWalker não está instalado. Execute: `pip install pygwalker`")
|
| 923 |
+
except Exception as e:
|
| 924 |
+
st.error(f"❌ Erro ao carregar PyGWalker: {e}")
|
| 925 |
+
else:
|
| 926 |
+
st.info("💡 Marque a opção acima para ativar a análise interativa com PyGWalker")
|