Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import seaborn as sns | |
| from sklearn.linear_model import LinearRegression | |
| from sklearn.model_selection import train_test_split | |
| from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error | |
| from scipy.stats import kruskal, shapiro | |
| import io | |
| import base64 | |
| # Configuracoes | |
| plt.style.use('default') | |
| sns.set_style("whitegrid") | |
| def criar_dashboard(): | |
| with gr.Blocks(theme=gr.themes.Soft()) as dashboard: | |
| # HEADER | |
| gr.Markdown( | |
| """ | |
| <div style="text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; border-radius: 15px; color: white;"> | |
| <h1 style="margin: 0;">🏠 ANALYTICS IMOBILIÁRIO</h1> | |
| <p style="margin: 0; opacity: 0.9;">Dashboard de Modelagem Estatística - UnB</p> | |
| </div> | |
| """ | |
| ) | |
| # MENU | |
| with gr.Row(): | |
| aba = gr.Radio( | |
| choices=["📊 Análise Exploratória", "📈 ANOVA", "🤖 Regressão Linear"], | |
| value="📊 Análise Exploratória", | |
| label="Navegação" | |
| ) | |
| gr.Markdown("---") | |
| # CONTROLES | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| arquivo = gr.File( | |
| label="📁 Upload do Dataset (CSV)", | |
| file_types=[".csv"] | |
| ) | |
| gr.Markdown("**⚙️ Configurações de Análise**") | |
| with gr.Row(): | |
| var_cat1 = gr.Dropdown( | |
| label="Variável Categórica 1", | |
| choices=[], | |
| interactive=True | |
| ) | |
| var_cat2 = gr.Dropdown( | |
| label="Variável Categórica 2", | |
| choices=[], | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| var_cont1 = gr.Dropdown( | |
| label="Variável Contínua 1", | |
| choices=[], | |
| interactive=True | |
| ) | |
| var_cont2 = gr.Dropdown( | |
| label="Variável Contínua 2", | |
| choices=[], | |
| interactive=True | |
| ) | |
| btn_analisar = gr.Button( | |
| "🚀 Executar Análise", | |
| variant="primary", | |
| size="lg" | |
| ) | |
| # RESULTADOS | |
| with gr.Column(scale=2): | |
| resultados = gr.HTML( | |
| value=""" | |
| <div style="text-align: center; padding: 50px; background: #f8f9fa; border-radius: 10px;"> | |
| <h3 style="color: #6c757d;">📊 Área de Resultados</h3> | |
| <p style="color: #6c757d;">Configure os parâmetros e execute a análise</p> | |
| </div> | |
| """ | |
| ) | |
| # FUNÇÕES | |
| def atualizar_variaveis(arquivo): | |
| if arquivo is None: | |
| vars_padrao = ['OverallQual', 'FullBath', 'Neighborhood', 'GrLivArea', 'GarageCars', 'BedroomAbvGr'] | |
| return [gr.Dropdown(choices=vars_padrao)] * 4 | |
| else: | |
| try: | |
| df = pd.read_csv(arquivo.name) | |
| variaveis = df.columns.tolist() | |
| return [gr.Dropdown(choices=variaveis)] * 4 | |
| except: | |
| return [gr.Dropdown(choices=[])] * 4 | |
| def executar_analise(arquivo, var_cat1, var_cat2, var_cont1, var_cont2, aba): | |
| try: | |
| if arquivo is None: | |
| df = gerar_dados_exemplo() | |
| else: | |
| df = pd.read_csv(arquivo.name) | |
| if aba == "📊 Análise Exploratória": | |
| return analise_exploratoria(df) | |
| elif aba == "📈 ANOVA": | |
| return analise_anova(df, var_cat1, var_cat2) | |
| else: | |
| return analise_regressao(df, var_cont1, var_cont2, var_cat1) | |
| except Exception as e: | |
| return f""" | |
| <div style="background: #f8d7da; color: #721c24; padding: 20px; border-radius: 10px;"> | |
| <h3>❌ Erro</h3> | |
| <p>{str(e)}</p> | |
| </div> | |
| """ | |
| # CONEXÕES | |
| arquivo.change(atualizar_variaveis, [arquivo], [var_cat1, var_cat2, var_cont1, var_cont2]) | |
| btn_analisar.click(executar_analise, [arquivo, var_cat1, var_cat2, var_cont1, var_cont2, aba], [resultados]) | |
| # FOOTER | |
| gr.Markdown("---") | |
| gr.Markdown( | |
| """ | |
| <div style="text-align: center; color: #6c757d;"> | |
| <p><strong>Desenvolvido por:</strong> Emily Valkiria | <strong>Disciplina:</strong> SIEP - UnB</p> | |
| </div> | |
| """ | |
| ) | |
| return dashboard | |
| def gerar_dados_exemplo(): | |
| np.random.seed(42) | |
| n_imoveis = 500 | |
| dados = pd.DataFrame({ | |
| 'SalePrice': np.random.normal(300000, 80000, n_imoveis), | |
| 'GrLivArea': np.random.normal(1500, 400, n_imoveis), | |
| 'OverallQual': np.random.randint(1, 11, n_imoveis), | |
| 'Neighborhood': np.random.choice(['Centro', 'Norte', 'Sul', 'Leste'], n_imoveis), | |
| 'FullBath': np.random.randint(1, 4, n_imoveis), | |
| 'GarageCars': np.random.randint(0, 4, n_imoveis), | |
| 'BedroomAbvGr': np.random.randint(1, 6, n_imoveis) | |
| }) | |
| dados['SalePrice'] = (dados['SalePrice'] + | |
| dados['GrLivArea'] * 100 + | |
| dados['OverallQual'] * 15000) | |
| dados['SalePrice'] = dados['SalePrice'].astype(int) | |
| return dados | |
| def analise_exploratoria(df): | |
| # Criar gráficos com matplotlib | |
| fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 12)) | |
| # Gráfico 1: Distribuição de preços | |
| ax1.hist(df['SalePrice'], bins=20, color='skyblue', edgecolor='black', alpha=0.7) | |
| ax1.set_title('Distribuição de Preços', fontsize=14, fontweight='bold') | |
| ax1.set_xlabel('Preço (R$)') | |
| ax1.set_ylabel('Frequência') | |
| ax1.grid(True, alpha=0.3) | |
| # Gráfico 2: Área vs Preço | |
| ax2.scatter(df['GrLivArea'], df['SalePrice'], alpha=0.6, color='coral') | |
| ax2.set_title('Relação: Área vs Preço', fontsize=14, fontweight='bold') | |
| ax2.set_xlabel('Área (m²)') | |
| ax2.set_ylabel('Preço (R$)') | |
| ax2.grid(True, alpha=0.3) | |
| # Gráfico 3: Qualidade vs Preço | |
| qualidade_preco = df.groupby('OverallQual')['SalePrice'].mean() | |
| ax3.bar(qualidade_preco.index, qualidade_preco.values, color='lightgreen', alpha=0.7) | |
| ax3.set_title('Preço Médio por Qualidade', fontsize=14, fontweight='bold') | |
| ax3.set_xlabel('Qualidade') | |
| ax3.set_ylabel('Preço Médio (R$)') | |
| ax3.grid(True, alpha=0.3) | |
| # Gráfico 4: Boxplot por bairro | |
| if 'Neighborhood' in df.columns: | |
| df.boxplot(column='SalePrice', by='Neighborhood', ax=ax4) | |
| ax4.set_title('Variação de Preços por Bairro', fontsize=14, fontweight='bold') | |
| ax4.tick_params(axis='x', rotation=45) | |
| plt.tight_layout() | |
| # Converter para base64 | |
| buf = io.BytesIO() | |
| plt.savefig(buf, format='png', dpi=100, bbox_inches='tight') | |
| buf.seek(0) | |
| img_str = base64.b64encode(buf.read()).decode() | |
| plt.close() | |
| # Estatísticas | |
| stats = df['SalePrice'].describe() | |
| return f""" | |
| <div style="font-family: Arial, sans-serif;"> | |
| <h2 style="color: #2E86AB;">📊 ANÁLISE EXPLORATÓRIA</h2> | |
| <div style="background: #e7f3ff; padding: 20px; border-radius: 10px; margin-bottom: 20px;"> | |
| <h3>📈 Estatísticas Descritivas</h3> | |
| <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;"> | |
| <div style="background: white; padding: 10px; border-radius: 5px; text-align: center;"> | |
| <strong>Média</strong><br>R$ {stats['mean']:,.0f} | |
| </div> | |
| <div style="background: white; padding: 10px; border-radius: 5px; text-align: center;"> | |
| <strong>Mediana</strong><br>R$ {stats['50%']:,.0f} | |
| </div> | |
| <div style="background: white; padding: 10px; border-radius: 5px; text-align: center;"> | |
| <strong>Desvio Padrão</strong><br>R$ {stats['std']:,.0f} | |
| </div> | |
| <div style="background: white; padding: 10px; border-radius: 5px; text-align: center;"> | |
| <strong>Total</strong><br>{len(df)} imóveis | |
| </div> | |
| </div> | |
| </div> | |
| <div style="text-align: center;"> | |
| <img src="data:image/png;base64,{img_str}" style="max-width: 100%; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);"> | |
| </div> | |
| </div> | |
| """ | |
| def analise_anova(df, var_cat1, var_cat2): | |
| resultados = [] | |
| for var in [var_cat1, var_cat2]: | |
| if var and var in df.columns: | |
| grupos = [grupo['SalePrice'].values for nome, grupo in df.groupby(var)] | |
| stat, p_valor = kruskal(*grupos) | |
| significativo = p_valor < 0.05 | |
| cor_fundo = '#d4edda' if significativo else '#f8d7da' | |
| cor_borda = '#28a745' if significativo else '#dc3545' | |
| icone = '✅' if significativo else '❌' | |
| resultados.append(f""" | |
| <div style="background: {cor_fundo}; padding: 15px; border-radius: 10px; margin-bottom: 15px; border-left: 5px solid {cor_borda};"> | |
| <h4 style="margin: 0;">{icone} {var}</h4> | |
| <p><strong>Estatística Kruskal-Wallis:</strong> {stat:.4f}</p> | |
| <p><strong>Valor-p:</strong> {p_valor:.6f}</p> | |
| <p><strong>Conclusão:</strong> {'IMPACTA SIGNIFICATIVAMENTE' if significativo else 'NÃO IMPACTA SIGNIFICATIVAMENTE'} o preço</p> | |
| </div> | |
| """) | |
| if resultados: | |
| resultados_html = "\n".join(resultados) | |
| else: | |
| resultados_html = "<p>Selecione variáveis categóricas para análise</p>" | |
| return f""" | |
| <div style="font-family: Arial, sans-serif;"> | |
| <h2 style="color: #A23B72;">📈 ANÁLISE ANOVA</h2> | |
| <div style="background: #f8f9fa; padding: 20px; border-radius: 10px;"> | |
| <h3>Teste Kruskal-Wallis</h3> | |
| {resultados_html} | |
| </div> | |
| </div> | |
| """ | |
| def analise_regressao(df, var_cont1, var_cont2, var_cat): | |
| return """ | |
| <div style="font-family: Arial, sans-serif;"> | |
| <h2 style="color: #18A558;">🤖 REGRESSÃO LINEAR</h2> | |
| <div style="background: #d1ecf1; padding: 20px; border-radius: 10px;"> | |
| <h3>Modelo de Regressão Linear Múltipla</h3> | |
| <p>Selecione variáveis contínuas e categóricas para construir o modelo preditivo.</p> | |
| <p><strong>Funcionalidades:</strong></p> | |
| <ul> | |
| <li>📊 Métricas de desempenho (R², RMSE, MAE)</li> | |
| <li>🔍 Diagnóstico de pressupostos</li> | |
| <li>📈 Interpretação dos coeficientes</li> | |
| <li>🎯 Recomendações práticas</li> | |
| </ul> | |
| </div> | |
| </div> | |
| """ | |
| # INICIAR | |
| if __name__ == "__main__": | |
| dashboard = criar_dashboard() | |
| dashboard.launch() |