Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python | |
| # coding: utf-8 | |
| # ===================================================== | |
| # Dashboard - Testes de Hipóteses com AmesHousing | |
| # ===================================================== | |
| import streamlit as st | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| import seaborn as sns | |
| import plotly.express as px | |
| import numpy as np | |
| from scipy import stats | |
| from scipy.stats import shapiro, levene, kruskal | |
| from statsmodels.formula.api import ols | |
| import statsmodels.api as sm | |
| # ----------------------------------------------------- | |
| # Configuração da Página | |
| # ----------------------------------------------------- | |
| st.set_page_config( | |
| page_title="Dashboard - Testes de Hipóteses com AmesHousing", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| st.markdown("<h1 style='text-align:center;color:#003366;'>Simulador de Testes de Hipótese</h1>", unsafe_allow_html=True) | |
| st.markdown("<h3 style='text-align:center;color:#003366;'>Análise do Dataset AmesHousing</h3>", unsafe_allow_html=True) | |
| st.markdown("---") | |
| # ----------------------------------------------------- | |
| # Abas do Dashboard | |
| # ----------------------------------------------------- | |
| tabs = st.tabs(["Simulações Teóricas", "Análise AmesHousing"]) | |
| # ----------------------------------------------------- | |
| # Aba 1: Simulações Teóricas | |
| # ----------------------------------------------------- | |
| with tabs[0]: | |
| st.subheader("Teste de Hipótese para cálculo do valor das casas") | |
| st.sidebar.markdown("### Parâmetros do Teste (Proporção)") | |
| p_pop = st.sidebar.slider("Proporção populacional (H0)", 0.0, 1.0, 0.1, 0.01, key="p_pop") | |
| p_sample = st.sidebar.slider("Proporção amostral", 0.0, 1.0, 0.12, 0.01, key="p_sample") | |
| n = st.sidebar.slider("Tamanho da amostra", 100, 10000, 1000, 10, key="n_sample") | |
| alpha_prop = st.sidebar.slider("Nível de significância (α)", 0.01, 0.10, 0.05, 0.01, key="alpha_prop") | |
| se = np.sqrt(p_pop*(1-p_pop)/n) | |
| z = (p_sample - p_pop)/se | |
| p_value = 2*(1 - stats.norm.cdf(abs(z))) | |
| st.write(f"**Z** = {z:.4f}") | |
| st.write(f"**p-valor** = {p_value:.4f}") | |
| if p_value < alpha_prop: | |
| st.write("**Rejeitamos H0**: diferença significativa.") | |
| else: | |
| st.write("**Não rejeitamos H0**: sem diferença significativa.") | |
| # ----------------------------------------------------- | |
| # Aba 2: Análise AmesHousing | |
| # ----------------------------------------------------- | |
| with tabs[1]: | |
| st.subheader("Análise de Variância - AmesHousing Dataset") | |
| st.markdown("---") | |
| # Leitura do CSV | |
| casa_data = pd.read_csv("../Dados/AmesHousing.csv") | |
| casa_data.columns = casa_data.columns.str.strip().str.replace(" ", "_") | |
| # ----------------------------- | |
| # Amostragem | |
| # ----------------------------- | |
| n_amostra = st.session_state.get("n_sample", len(casa_data)) | |
| if n_amostra < len(casa_data): | |
| dados = casa_data.sample(n=n_amostra, random_state=42) | |
| else: | |
| dados = casa_data.copy() | |
| # ----------------------------- | |
| # Filtro interativo no sidebar | |
| # ----------------------------- | |
| st.sidebar.markdown("### Filtros AmesHousing") | |
| bairros = st.sidebar.multiselect( | |
| "Selecione bairros", | |
| options=sorted(dados["Neighborhood"].dropna().unique()), | |
| default=None | |
| ) | |
| # Aplicar filtro | |
| dados_filtrados = dados.copy() | |
| if bairros: | |
| dados_filtrados = dados_filtrados[dados_filtrados["Neighborhood"].isin(bairros)] | |
| # ------------------------------------------------- | |
| # Análise Exploratória | |
| # ------------------------------------------------- | |
| st.markdown("### Distribuição do Preço de Venda") | |
| if not dados_filtrados.empty: | |
| fig, ax = plt.subplots(figsize=(8,5)) | |
| sns.histplot(dados_filtrados['SalePrice'], kde=True, ax=ax) | |
| ax.set_title("Distribuição do Preço de Venda") | |
| st.pyplot(fig) | |
| else: | |
| st.warning("Nenhum dado disponível com os filtros aplicados.") | |
| # Boxplots | |
| st.markdown("### Boxplots das Variáveis Selecionadas") | |
| variavel = st.selectbox( | |
| "Escolha a variável categórica para comparar preços:", | |
| ["Neighborhood","Garage_Type","Fireplaces"] | |
| ) | |
| if not dados_filtrados.empty: | |
| if len(dados_filtrados[variavel].dropna().unique()) > 1: | |
| fig2, ax2 = plt.subplots(figsize=(12,6)) | |
| sns.boxplot(x=variavel, y="SalePrice", data=dados_filtrados, ax=ax2) | |
| plt.xticks(rotation=90) | |
| ax2.set_title(f"Preço de Venda por {variavel}") | |
| st.pyplot(fig2) | |
| else: | |
| st.warning(f"Não é possível gerar boxplot: apenas uma categoria em {variavel} após os filtros.") | |
| # Scatter interativo (média de preço por bairro) | |
| st.markdown("### Preço Médio de Venda por Bairro") | |
| if not dados_filtrados.empty: | |
| bairro_grouped = dados_filtrados.groupby('Neighborhood').agg( | |
| count=('SalePrice','size'), | |
| mean_price=('SalePrice','mean') | |
| ).reset_index() | |
| bairro_filtered = bairro_grouped[bairro_grouped['count'] >= 5] | |
| if not bairro_filtered.empty: | |
| fig3 = px.scatter( | |
| bairro_filtered, | |
| x='mean_price', | |
| y='Neighborhood', | |
| size='count', | |
| color='Neighborhood', | |
| title='Preço Médio de Venda vs Bairro (Ames, Iowa)', | |
| labels={'mean_price': 'Preço Médio de Venda', 'Neighborhood':'Bairro'}, | |
| opacity=0.8 | |
| ) | |
| st.plotly_chart(fig3, use_container_width=True) | |
| else: | |
| st.warning("Não há bairros suficientes após filtros para gerar o gráfico.") | |
| # ------------------------------------------------- | |
| # ANOVA | |
| # ------------------------------------------------- | |
| st.markdown("### ANOVA para Neighborhood, Garage_Type e Fireplaces") | |
| alpha = st.sidebar.slider( | |
| "Nível de significância (α) - ANOVA AmesHousing", | |
| 0.01,0.10,0.05,0.01, | |
| key="alpha_ames" | |
| ) | |
| if not dados_filtrados.empty: | |
| for nome in ["Neighborhood", "Garage_Type", "Fireplaces"]: | |
| categorias = dados_filtrados[nome].dropna().unique() | |
| if len(categorias) < 2: | |
| st.warning(f"ANOVA não pôde ser realizada para **{nome}** (menos de 2 grupos após os filtros).") | |
| continue | |
| modelo = ols(f'SalePrice ~ C({nome})', data=dados_filtrados).fit() | |
| st.markdown(f"#### ANOVA - {nome}") | |
| anova = sm.stats.anova_lm(modelo, typ=2) | |
| st.dataframe(anova) | |
| # ------------------------------------------------- | |
| # Validação dos Pressupostos | |
| # ------------------------------------------------- | |
| st.markdown("### Validação dos Pressupostos da ANOVA") | |
| st.markdown("#### Teste de Normalidade (Shapiro-Wilk)") | |
| for nome in ["Neighborhood","Garage_Type","Fireplaces"]: | |
| categorias = dados_filtrados[nome].dropna().unique() | |
| if len(categorias) < 2: | |
| st.warning(f"Shapiro-Wilk não pôde ser realizado para **{nome}** (menos de 2 grupos após os filtros).") | |
| continue | |
| modelo = ols(f'SalePrice ~ C({nome})', data=dados_filtrados).fit() | |
| residuos = modelo.resid | |
| stat, p = shapiro(residuos.dropna()) | |
| st.write(f"{nome}: estatística={stat:.3f}, p={p:.3f} " | |
| + ("resíduos normais" if p >= alpha else "violação de normalidade")) | |
| st.markdown("#### Teste de Homocedasticidade (Levene)") | |
| for nome in ["Neighborhood","Garage_Type","Fireplaces"]: | |
| grupos = [grupo["SalePrice"].dropna() for _, grupo in dados_filtrados.groupby(nome)] | |
| if len(grupos) < 2: | |
| st.warning(f"Levene não pôde ser realizado para **{nome}** (menos de 2 grupos após os filtros).") | |
| continue | |
| stat, p = levene(*grupos) | |
| st.write(f"{nome}: estatística={stat:.3f}, p={p:.3f} " | |
| + ("variâncias iguais" if p >= alpha else "variâncias diferentes")) | |
| # ------------------------------------------------- | |
| # Kruskal-Wallis | |
| # ------------------------------------------------- | |
| st.markdown("### Teste não-paramétrico (Kruskal-Wallis)") | |
| for nome in ["Neighborhood","Garage_Type","Fireplaces"]: | |
| grupos = [grupo["SalePrice"].dropna() for _, grupo in dados_filtrados.groupby(nome)] | |
| if len(grupos) < 2: | |
| st.warning(f"Kruskal-Wallis não pôde ser realizado para **{nome}** (menos de 2 grupos após os filtros).") | |
| continue | |
| stat, p = kruskal(*grupos) | |
| st.write(f"{nome}: estatística={stat:.3f}, p={p:.3f} " | |
| + ("diferenças significativas" if p < alpha else "sem diferença significativa")) | |