#!/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("

Simulador de Testes de Hipótese

", unsafe_allow_html=True) st.markdown("

Análise do Dataset AmesHousing

", 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"))