Programa de Pós-graduação em Computação Aplicada – PPCA (UnB)
Análise Estatística de Dados e Informações
Professor: João Gabriel de Moraes Souza
Aluno: Angelo Donizete Buso Júnior
Técnicas Estatisicas - ANOVA Aplicadas ao mercado Imobiliário
A estatística aplicada ao mercado imobiliário desempenha um papel fundamental na análise e compreensão dos fatores que influenciam os preços das propriedades. Por meio de técnicas como validação de pressupostos e testes de hipótese, é possível identificar relações significativas entre variáveis como localização, qualidade construtiva e características físicas das propriedades.
Uma dessas ferramentas é o uso da Análise de Variância (ANOVA), permite avaliar avaliar se há diferenças significativas nos preços médios entre grupos categorizados, como bairros ou níveis de qualidade. Contudo, a aplicação do ANOVA requer o cumprimento de pressupostos de normalidade e homogeneidade das variâncias, essenciais para garantir a validade dos resultados. Se tais pressupostos são violados, a análise é complementada por técnicas não paramétricas, permitindo insights robustos sobre a influência de diferentes características no mercado imobiliário.
Problemática a ser resolvida
O presente estudo tem como objetivo procurar responder, com base em evidencia estatística, à seguinte pergunta: "Selecionado algumas características, estas afetam significativamente o preço médio de venda das propriedades?".
E como pergunta alternativa responder ao marketing "É possível realizar uma estratégia de preços única, sem comprometer a percepção de valor no mercado?"
Para alcançar o objetivo, seguimos as etapas abaixo:
Metodologia
1. Exploração Inicial dos Dados
Foi realizada uma análise exploratória para compreender a distribuição de SalePrice e a relação com as três variáveis selecionadas. Identificamos que os dados de SalePrice apresentavam assimetria positiva, indicando a possibilidade de comportamento não linear.
2. Teste ANOVA Tradicional
A ANOVA é uma técnica estatística que avalia se há diferenças significativas entre as médias de grupos categóricos, como bairros ou níveis de qualidade. No entanto, para sua aplicação, é necessário que os dados atendam aos pressupostos de normalidade e homogeneidade de variâncias. Esses pressupostos são essenciais para a validade dos resultados.
3. Abordagem Não Paramétrica
Quando os pressupostos da ANOVA não são atendidos, utilizamos técnicas não paramétricas como o Teste de Kruskal-Wallis, que não requer normalidade nem homogeneidade das variâncias, sendo ideal para avaliar diferenças entre grupos categóricos em situações onde os dados não seguem distribuições normais.
4. Análise Post-Hoc
Após identificar diferenças significativas entre os grupos, foi aplicada a Análise Post-Hoc por meio do Teste de Dunn. Este teste avalia comparações par a par entre os grupos, ajustando os valores-p para múltiplas comparações, destacando quais grupos específicos possuem diferenças significativas.
5. Visualizações
Gráficos como violinos e mapas de calor foram utilizados para ilustrar as distribuições de SalePrice e evidenciar as comparações significativas entre os grupos. Essas visualizações complementam a análise ao destacar tendências e padrões nos dados.
Para Virgillito (2017), o teste ANOVA é uma ferramenta estatística fundamental para avaliar a significância estatística entre grupos. Ele permite verificar se duas ou mais populações apresentam médias significativamente diferentes, utilizando amostras extraídas dessas populações. Em sua explicação, o autor destaca que, "para se comparar o afastamento entre as médias, recorre-se ao conceito de desvio-padrão de cada amostra, o qual, elevado ao quadrado, resulta na variância" (VIRGILLITO, 2017, p. 627). Assim, a análise da variância avalia as diferenças entre as médias por meio do comportamento da variância.
De forma prática, o teste ANOVA é amplamente aplicado em diversas áreas, como pesquisas médicas, produtividade agrícola e até mesmo em estudos de desempenho no marketing. Conforme Virgillito (2017), ele pode ser usado em situações como "a comparação entre a produtividade de dois tipos de grão cultivados com dois tipos de adubo (ANOVA de dois fatores)" ou "a comparação de desempenho de equipes em termos de produtividade e incentivos" (VIRGILLITO, 2017, p. 627).
Além disso, o autor ressalta que, enquanto outros testes comparam apenas duas amostras, o ANOVA "é mais abrangente, visto que pode comparar mais de duas amostras e testar se há ou não igualdade entre as médias das populações das quais elas foram retiradas" (VIRGILLITO, 2017, p. 627). Por isso, é uma técnica essencial em análises multigrupos, tanto com uma variável dependente (ANOVA) quanto com mais de uma variável dependente (MANOVA).
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import f_oneway, shapiro, levene, kruskal, skew, mannwhitneyu
import warnings
import statsmodels.api as sm
from statsmodels.formula.api import ols
import ace_tools_open as tools
import scikit_posthocs as sp
sns.set_theme(style="whitegrid")
plt.rc("figure", figsize=(10, 6))
warnings.filterwarnings('ignore')
Coleta de dados
Os dados utilizados nesta análise foram obtidos do repositório público Ames Housing Dataset, disponível na plataforma Kaggle. Contém informações detalhadas sobre propriedades residenciais em Ames, Iowa, incluindo variáveis como localização, qualidade geral e características físicas das propriedades.
try:
df = pd.read_csv("/home/buso/mestrado/aedi-ppca/dados/AmesHousing.csv")
except FileNotFoundError:
print("Arquivo não encontrado. Por favor, verifique o caminho do dataset.")
Dicionário de Dados
Documento ou estrutura que descreve detalhadamente cada variável presente em um conjunto de dados
| Nome da Variável | Descrição |
|---|---|
| SalePrice | Preço de venda da propriedade em dólares. Esta é a variável alvo que se tenta prever. |
| MSSubClass | Classe do edifício. |
| MSZoning | Classificação geral de zoneamento. |
| LotFrontage | Pés lineares de rua conectados à propriedade. |
| LotArea | Tamanho do lote em pés quadrados. |
| Street | Tipo de acesso à estrada. |
| Alley | Tipo de acesso à viela. |
| LotShape | Formato geral da propriedade. |
| LandContour | Planura da propriedade. |
| Utilities | Tipo de utilidades disponíveis. |
| LotConfig | Configuração do lote. |
| LandSlope | Declive da propriedade. |
| Neighborhood | Localização física dentro dos limites da cidade de Ames. |
| Condition1 | Proximidade a rodovias principais ou ferrovias. |
| Condition2 | Proximidade a rodovias principais ou ferrovias (se houver uma segunda). |
| BldgType | Tipo de habitação. |
| HouseStyle | Estilo da habitação. |
| OverallQual | Qualidade geral do material e acabamento. |
| OverallCond | Classificação geral do estado de conservação. |
| YearBuilt | Ano de construção original. |
| YearRemodAdd | Ano de reforma. |
| RoofStyle | Tipo de telhado. |
| RoofMatl | Material do telhado. |
| Exterior1st | Revestimento exterior principal da casa. |
| Exterior2nd | Revestimento exterior secundário da casa (se houver mais de um material). |
| MasVnrType | Tipo de revestimento de alvenaria. |
| MasVnrArea | Área de revestimento de alvenaria em pés quadrados. |
| ExterQual | Qualidade do material exterior. |
| ExterCond | Condição atual do material no exterior. |
| Foundation | Tipo de fundação. |
| BsmtQual | Altura do porão. |
| BsmtCond | Condição geral do porão. |
| BsmtExposure | Paredes do porão com saída para o jardim ou nível inferior. |
| BsmtFinType1 | Qualidade da área finalizada do porão. |
| BsmtFinSF1 | Pés quadrados finalizados do tipo 1. |
| BsmtFinType2 | Qualidade da segunda área finalizada do porão (se houver). |
| BsmtFinSF2 | Pés quadrados finalizados do tipo 2. |
| BsmtUnfSF | Pés quadrados não finalizados do porão. |
| TotalBsmtSF | Área total do porão em pés quadrados. |
| Heating | Tipo de aquecimento. |
| HeatingQC | Qualidade e condição do aquecimento. |
| CentralAir | Ar condicionado central. |
| Electrical | Sistema elétrico. |
| 1stFlrSF | Área do primeiro andar em pés quadrados. |
| 2ndFlrSF | Área do segundo andar em pés quadrados. |
| LowQualFinSF | Área finalizada de baixa qualidade (todos os andares). |
| GrLivArea | Área habitável acima do nível do solo em pés quadrados. |
| BsmtFullBath | Banheiros completos no porão. |
| BsmtHalfBath | Meio banheiro no porão. |
| FullBath | Banheiros completos acima do nível do solo. |
| HalfBath | Meio banheiro acima do nível do solo. |
| Bedroom | Número de quartos acima do nível do porão. |
| Kitchen | Número de cozinhas. |
| KitchenQual | Qualidade da cozinha. |
| TotRmsAbvGrd | Total de cômodos acima do nível do solo (não inclui banheiros). |
| Functional | Avaliação da funcionalidade da casa. |
| Fireplaces | Número de lareiras. |
| FireplaceQu | Qualidade da lareira. |
| GarageType | Localização da garagem. |
| GarageYrBlt | Ano de construção da garagem. |
| GarageFinish | Acabamento interior da garagem. |
| GarageCars | Tamanho da garagem em capacidade de carros. |
| GarageArea | Tamanho da garagem em pés quadrados. |
| GarageQual | Qualidade da garagem. |
| GarageCond | Condição da garagem. |
| PavedDrive | Entrada pavimentada. |
| WoodDeckSF | Área do deck de madeira em pés quadrados. |
| OpenPorchSF | Área de varanda aberta em pés quadrados. |
| EnclosedPorch | Área de varanda fechada em pés quadrados. |
| 3SsnPorch | Área de varanda de três estações em pés quadrados. |
| ScreenPorch | Área de varanda com tela em pés quadrados. |
| PoolArea | Área da piscina em pés quadrados. |
| PoolQC | Qualidade da piscina. |
| Fence | Qualidade da cerca. |
| MiscFeature | Características diversas não incluídas em outras categorias. |
| MiscVal | Valor ($) de características diversas. |
| MoSold | Mês de venda. |
| YrSold | Ano de venda. |
| SaleType | Tipo de venda. |
| SaleCondition | Condição de venda. |
Análise Exploratória de Dados (EDA)
Uma etapa fundamental no processo de análise estatística e ciência de dados. Seu objetivo é compreender as características principais do conjunto de dados, identificar padrões, verificar anomalias e resumir as relações entre variáveis. Durante a EDA, utilizam-se métodos estatísticos descritivos e visualizações gráficas, como histogramas, boxplots e gráficos de dispersão, para obter insights iniciais que guiam as etapas subsequentes de modelagem e tomada de decisão. Essa abordagem permite não apenas detectar problemas nos dados, como valores ausentes ou inconsistências, mas também revelar tendências e correlações que podem impactar diretamente os resultados da análise.
print(f"Dimensões dos dados: com {df.shape[1]} features e {df.shape[0]} linhas!")
Dimensões dos dados: com 82 features e 2930 linhas!
print("\nPrimeiras 5 linhas dos dados:")
df.head()
Primeiras 5 linhas dos dados:
| Order | PID | MS SubClass | MS Zoning | Lot Frontage | Lot Area | Street | Alley | Lot Shape | Land Contour | ... | Pool Area | Pool QC | Fence | Misc Feature | Misc Val | Mo Sold | Yr Sold | Sale Type | Sale Condition | SalePrice | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 526301100 | 20 | RL | 141.0 | 31770 | Pave | NaN | IR1 | Lvl | ... | 0 | NaN | NaN | NaN | 0 | 5 | 2010 | WD | Normal | 215000 |
| 1 | 2 | 526350040 | 20 | RH | 80.0 | 11622 | Pave | NaN | Reg | Lvl | ... | 0 | NaN | MnPrv | NaN | 0 | 6 | 2010 | WD | Normal | 105000 |
| 2 | 3 | 526351010 | 20 | RL | 81.0 | 14267 | Pave | NaN | IR1 | Lvl | ... | 0 | NaN | NaN | Gar2 | 12500 | 6 | 2010 | WD | Normal | 172000 |
| 3 | 4 | 526353030 | 20 | RL | 93.0 | 11160 | Pave | NaN | Reg | Lvl | ... | 0 | NaN | NaN | NaN | 0 | 4 | 2010 | WD | Normal | 244000 |
| 4 | 5 | 527105010 | 60 | RL | 74.0 | 13830 | Pave | NaN | IR1 | Lvl | ... | 0 | NaN | MnPrv | NaN | 0 | 3 | 2010 | WD | Normal | 189900 |
5 rows × 82 columns
print("\nInformações gerais sobre os dados:")
print(df.info())
Informações gerais sobre os dados: <class 'pandas.core.frame.DataFrame'> RangeIndex: 2930 entries, 0 to 2929 Data columns (total 82 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Order 2930 non-null int64 1 PID 2930 non-null int64 2 MS SubClass 2930 non-null int64 3 MS Zoning 2930 non-null object 4 Lot Frontage 2440 non-null float64 5 Lot Area 2930 non-null int64 6 Street 2930 non-null object 7 Alley 198 non-null object 8 Lot Shape 2930 non-null object 9 Land Contour 2930 non-null object 10 Utilities 2930 non-null object 11 Lot Config 2930 non-null object 12 Land Slope 2930 non-null object 13 Neighborhood 2930 non-null object 14 Condition 1 2930 non-null object 15 Condition 2 2930 non-null object 16 Bldg Type 2930 non-null object 17 House Style 2930 non-null object 18 Overall Qual 2930 non-null int64 19 Overall Cond 2930 non-null int64 20 Year Built 2930 non-null int64 21 Year Remod/Add 2930 non-null int64 22 Roof Style 2930 non-null object 23 Roof Matl 2930 non-null object 24 Exterior 1st 2930 non-null object 25 Exterior 2nd 2930 non-null object 26 Mas Vnr Type 1155 non-null object 27 Mas Vnr Area 2907 non-null float64 28 Exter Qual 2930 non-null object 29 Exter Cond 2930 non-null object 30 Foundation 2930 non-null object 31 Bsmt Qual 2850 non-null object 32 Bsmt Cond 2850 non-null object 33 Bsmt Exposure 2847 non-null object 34 BsmtFin Type 1 2850 non-null object 35 BsmtFin SF 1 2929 non-null float64 36 BsmtFin Type 2 2849 non-null object 37 BsmtFin SF 2 2929 non-null float64 38 Bsmt Unf SF 2929 non-null float64 39 Total Bsmt SF 2929 non-null float64 40 Heating 2930 non-null object 41 Heating QC 2930 non-null object 42 Central Air 2930 non-null object 43 Electrical 2929 non-null object 44 1st Flr SF 2930 non-null int64 45 2nd Flr SF 2930 non-null int64 46 Low Qual Fin SF 2930 non-null int64 47 Gr Liv Area 2930 non-null int64 48 Bsmt Full Bath 2928 non-null float64 49 Bsmt Half Bath 2928 non-null float64 50 Full Bath 2930 non-null int64 51 Half Bath 2930 non-null int64 52 Bedroom AbvGr 2930 non-null int64 53 Kitchen AbvGr 2930 non-null int64 54 Kitchen Qual 2930 non-null object 55 TotRms AbvGrd 2930 non-null int64 56 Functional 2930 non-null object 57 Fireplaces 2930 non-null int64 58 Fireplace Qu 1508 non-null object 59 Garage Type 2773 non-null object 60 Garage Yr Blt 2771 non-null float64 61 Garage Finish 2771 non-null object 62 Garage Cars 2929 non-null float64 63 Garage Area 2929 non-null float64 64 Garage Qual 2771 non-null object 65 Garage Cond 2771 non-null object 66 Paved Drive 2930 non-null object 67 Wood Deck SF 2930 non-null int64 68 Open Porch SF 2930 non-null int64 69 Enclosed Porch 2930 non-null int64 70 3Ssn Porch 2930 non-null int64 71 Screen Porch 2930 non-null int64 72 Pool Area 2930 non-null int64 73 Pool QC 13 non-null object 74 Fence 572 non-null object 75 Misc Feature 106 non-null object 76 Misc Val 2930 non-null int64 77 Mo Sold 2930 non-null int64 78 Yr Sold 2930 non-null int64 79 Sale Type 2930 non-null object 80 Sale Condition 2930 non-null object 81 SalePrice 2930 non-null int64 dtypes: float64(11), int64(28), object(43) memory usage: 1.8+ MB None
print("\nResumo de valores ausentes por coluna:")
missing_data = df.isnull().sum()
missing_data = missing_data[missing_data > 0].sort_values(ascending=False)
print(missing_data)
Resumo de valores ausentes por coluna: Pool QC 2917 Misc Feature 2824 Alley 2732 Fence 2358 Mas Vnr Type 1775 Fireplace Qu 1422 Lot Frontage 490 Garage Qual 159 Garage Cond 159 Garage Yr Blt 159 Garage Finish 159 Garage Type 157 Bsmt Exposure 83 BsmtFin Type 2 81 Bsmt Cond 80 Bsmt Qual 80 BsmtFin Type 1 80 Mas Vnr Area 23 Bsmt Full Bath 2 Bsmt Half Bath 2 BsmtFin SF 1 1 BsmtFin SF 2 1 Electrical 1 Total Bsmt SF 1 Bsmt Unf SF 1 Garage Area 1 Garage Cars 1 dtype: int64
if not missing_data.empty:
plt.figure(figsize=(12, 6))
sns.barplot(x=missing_data.index, y=missing_data.values)
plt.title("Valores Ausentes por Variável")
plt.ylabel("Quantidade de Valores Ausentes")
plt.xticks(rotation=45)
plt.show()
else:
print("Nenhum valor ausente encontrado.")
print("\nEstatísticas descritivas das variáveis numéricas:")
print(df.describe().transpose())
Estatísticas descritivas das variáveis numéricas:
count mean std min \
Order 2930.0 1.465500e+03 8.459625e+02 1.0
PID 2930.0 7.144645e+08 1.887308e+08 526301100.0
MS SubClass 2930.0 5.738737e+01 4.263802e+01 20.0
Lot Frontage 2440.0 6.922459e+01 2.336533e+01 21.0
Lot Area 2930.0 1.014792e+04 7.880018e+03 1300.0
Overall Qual 2930.0 6.094881e+00 1.411026e+00 1.0
Overall Cond 2930.0 5.563140e+00 1.111537e+00 1.0
Year Built 2930.0 1.971356e+03 3.024536e+01 1872.0
Year Remod/Add 2930.0 1.984267e+03 2.086029e+01 1950.0
Mas Vnr Area 2907.0 1.018968e+02 1.791126e+02 0.0
BsmtFin SF 1 2929.0 4.426296e+02 4.555908e+02 0.0
BsmtFin SF 2 2929.0 4.972243e+01 1.691685e+02 0.0
Bsmt Unf SF 2929.0 5.592625e+02 4.394942e+02 0.0
Total Bsmt SF 2929.0 1.051615e+03 4.406151e+02 0.0
1st Flr SF 2930.0 1.159558e+03 3.918909e+02 334.0
2nd Flr SF 2930.0 3.354560e+02 4.283957e+02 0.0
Low Qual Fin SF 2930.0 4.676792e+00 4.631051e+01 0.0
Gr Liv Area 2930.0 1.499690e+03 5.055089e+02 334.0
Bsmt Full Bath 2928.0 4.313525e-01 5.248202e-01 0.0
Bsmt Half Bath 2928.0 6.113388e-02 2.452536e-01 0.0
Full Bath 2930.0 1.566553e+00 5.529406e-01 0.0
Half Bath 2930.0 3.795222e-01 5.026293e-01 0.0
Bedroom AbvGr 2930.0 2.854266e+00 8.277311e-01 0.0
Kitchen AbvGr 2930.0 1.044369e+00 2.140762e-01 0.0
TotRms AbvGrd 2930.0 6.443003e+00 1.572964e+00 2.0
Fireplaces 2930.0 5.993174e-01 6.479209e-01 0.0
Garage Yr Blt 2771.0 1.978132e+03 2.552841e+01 1895.0
Garage Cars 2929.0 1.766815e+00 7.605664e-01 0.0
Garage Area 2929.0 4.728197e+02 2.150465e+02 0.0
Wood Deck SF 2930.0 9.375188e+01 1.263616e+02 0.0
Open Porch SF 2930.0 4.753345e+01 6.748340e+01 0.0
Enclosed Porch 2930.0 2.301160e+01 6.413906e+01 0.0
3Ssn Porch 2930.0 2.592491e+00 2.514133e+01 0.0
Screen Porch 2930.0 1.600205e+01 5.608737e+01 0.0
Pool Area 2930.0 2.243345e+00 3.559718e+01 0.0
Misc Val 2930.0 5.063515e+01 5.663443e+02 0.0
Mo Sold 2930.0 6.216041e+00 2.714492e+00 1.0
Yr Sold 2930.0 2.007790e+03 1.316613e+00 2006.0
SalePrice 2930.0 1.807961e+05 7.988669e+04 12789.0
25% 50% 75% max
Order 7.332500e+02 1465.5 2.197750e+03 2.930000e+03
PID 5.284770e+08 535453620.0 9.071811e+08 1.007100e+09
MS SubClass 2.000000e+01 50.0 7.000000e+01 1.900000e+02
Lot Frontage 5.800000e+01 68.0 8.000000e+01 3.130000e+02
Lot Area 7.440250e+03 9436.5 1.155525e+04 2.152450e+05
Overall Qual 5.000000e+00 6.0 7.000000e+00 1.000000e+01
Overall Cond 5.000000e+00 5.0 6.000000e+00 9.000000e+00
Year Built 1.954000e+03 1973.0 2.001000e+03 2.010000e+03
Year Remod/Add 1.965000e+03 1993.0 2.004000e+03 2.010000e+03
Mas Vnr Area 0.000000e+00 0.0 1.640000e+02 1.600000e+03
BsmtFin SF 1 0.000000e+00 370.0 7.340000e+02 5.644000e+03
BsmtFin SF 2 0.000000e+00 0.0 0.000000e+00 1.526000e+03
Bsmt Unf SF 2.190000e+02 466.0 8.020000e+02 2.336000e+03
Total Bsmt SF 7.930000e+02 990.0 1.302000e+03 6.110000e+03
1st Flr SF 8.762500e+02 1084.0 1.384000e+03 5.095000e+03
2nd Flr SF 0.000000e+00 0.0 7.037500e+02 2.065000e+03
Low Qual Fin SF 0.000000e+00 0.0 0.000000e+00 1.064000e+03
Gr Liv Area 1.126000e+03 1442.0 1.742750e+03 5.642000e+03
Bsmt Full Bath 0.000000e+00 0.0 1.000000e+00 3.000000e+00
Bsmt Half Bath 0.000000e+00 0.0 0.000000e+00 2.000000e+00
Full Bath 1.000000e+00 2.0 2.000000e+00 4.000000e+00
Half Bath 0.000000e+00 0.0 1.000000e+00 2.000000e+00
Bedroom AbvGr 2.000000e+00 3.0 3.000000e+00 8.000000e+00
Kitchen AbvGr 1.000000e+00 1.0 1.000000e+00 3.000000e+00
TotRms AbvGrd 5.000000e+00 6.0 7.000000e+00 1.500000e+01
Fireplaces 0.000000e+00 1.0 1.000000e+00 4.000000e+00
Garage Yr Blt 1.960000e+03 1979.0 2.002000e+03 2.207000e+03
Garage Cars 1.000000e+00 2.0 2.000000e+00 5.000000e+00
Garage Area 3.200000e+02 480.0 5.760000e+02 1.488000e+03
Wood Deck SF 0.000000e+00 0.0 1.680000e+02 1.424000e+03
Open Porch SF 0.000000e+00 27.0 7.000000e+01 7.420000e+02
Enclosed Porch 0.000000e+00 0.0 0.000000e+00 1.012000e+03
3Ssn Porch 0.000000e+00 0.0 0.000000e+00 5.080000e+02
Screen Porch 0.000000e+00 0.0 0.000000e+00 5.760000e+02
Pool Area 0.000000e+00 0.0 0.000000e+00 8.000000e+02
Misc Val 0.000000e+00 0.0 0.000000e+00 1.700000e+04
Mo Sold 4.000000e+00 6.0 8.000000e+00 1.200000e+01
Yr Sold 2.007000e+03 2008.0 2.009000e+03 2.010000e+03
SalePrice 1.295000e+05 160000.0 2.135000e+05 7.550000e+05
Na análise de dados, a identificação de variáveis categóricas é uma etapa essencial, pois essas variáveis representam dados qualitativos que são organizados em categorias ou grupos distintos. As variáveis categóricas podem ser analisadas para identificar padrões de frequência, diferenças entre grupos e sua relação com variáveis dependentes, como o preço de venda. Ferramentas como tabelas de contingência, gráficos de barras e análises de associação são frequentemente utilizadas para explorar essas variáveis e obter insights significativos no contexto da análise. E nem sempre podem estrar representadas em string!
categorical_cols = df.select_dtypes(include=['object']).columns
print("\nVariáveis categóricas:")
print(categorical_cols)
Variáveis categóricas:
Index(['MS Zoning', 'Street', 'Alley', 'Lot Shape', 'Land Contour',
'Utilities', 'Lot Config', 'Land Slope', 'Neighborhood', 'Condition 1',
'Condition 2', 'Bldg Type', 'House Style', 'Roof Style', 'Roof Matl',
'Exterior 1st', 'Exterior 2nd', 'Mas Vnr Type', 'Exter Qual',
'Exter Cond', 'Foundation', 'Bsmt Qual', 'Bsmt Cond', 'Bsmt Exposure',
'BsmtFin Type 1', 'BsmtFin Type 2', 'Heating', 'Heating QC',
'Central Air', 'Electrical', 'Kitchen Qual', 'Functional',
'Fireplace Qu', 'Garage Type', 'Garage Finish', 'Garage Qual',
'Garage Cond', 'Paved Drive', 'Pool QC', 'Fence', 'Misc Feature',
'Sale Type', 'Sale Condition'],
dtype='object')
df.nunique().sort_values()
Street 2
Alley 2
Central Air 2
Land Slope 3
Bsmt Half Bath 3
...
Bsmt Unf SF 1137
Gr Liv Area 1292
Lot Area 1960
Order 2930
PID 2930
Length: 82, dtype: int64
valores_unicos = df.nunique()
possiveis_categoricas = valores_unicos[valores_unicos <= 30]
print("Possíveis variáveis categóricas:")
print(possiveis_categoricas)
Possíveis variáveis categóricas: MS SubClass 16 MS Zoning 7 Street 2 Alley 2 Lot Shape 4 Land Contour 4 Utilities 3 Lot Config 5 Land Slope 3 Neighborhood 28 Condition 1 9 Condition 2 8 Bldg Type 5 House Style 8 Overall Qual 10 Overall Cond 9 Roof Style 6 Roof Matl 8 Exterior 1st 16 Exterior 2nd 17 Mas Vnr Type 4 Exter Qual 4 Exter Cond 5 Foundation 6 Bsmt Qual 5 Bsmt Cond 5 Bsmt Exposure 4 BsmtFin Type 1 6 BsmtFin Type 2 6 Heating 6 Heating QC 5 Central Air 2 Electrical 5 Bsmt Full Bath 4 Bsmt Half Bath 3 Full Bath 5 Half Bath 3 Bedroom AbvGr 8 Kitchen AbvGr 4 Kitchen Qual 5 TotRms AbvGrd 14 Functional 8 Fireplaces 5 Fireplace Qu 5 Garage Type 6 Garage Finish 3 Garage Cars 6 Garage Qual 5 Garage Cond 5 Paved Drive 3 Pool Area 14 Pool QC 4 Fence 4 Misc Feature 5 Mo Sold 12 Yr Sold 5 Sale Type 10 Sale Condition 6 dtype: int64
Análise Univariada
A análise univariada da variável SalePrice (preço de venda) foca na compreensão de sua distribuição e principais características estatísticas, como média, mediana, desvio padrão e assimetria. Essa análise permite identificar a tendência central, dispersão e possíveis outliers no conjunto de dados. Além disso, visualizações como histogramas e boxplots são ferramentas úteis para observar o comportamento da variável, revelando padrões, assimetrias ou concentrações que podem influenciar diretamente na modelagem e interpretação dos resultados.
plt.figure(figsize=(10, 6))
sns.histplot(df["SalePrice"], kde=True, color="blue", bins=30)
plt.xlabel("Preço de Venda (SalePrice)")
plt.ylabel("Frequência")
plt.title('Distribuição do Preço de Venda')
plt.show()
print(df["SalePrice"].describe())
print(df["SalePrice"].quantile([0.95]))
count 2930.000000 mean 180796.060068 std 79886.692357 min 12789.000000 25% 129500.000000 50% 160000.000000 75% 213500.000000 max 755000.000000 Name: SalePrice, dtype: float64 0.95 335000.0 Name: SalePrice, dtype: float64
A variável SalePrice apresenta uma distribuição assimétrica à direita, o que indica que a maioria das propriedades está concentrada em faixas de preços mais baixas. A maior parte dos preços está abaixo de 300.000 dólares, com um pico evidente na faixa entre 150.000 e 200.000 dólares. A análise da curva de densidade suavizada reforça essa assimetria, destacando a concentração de propriedades em preços menores. Além disso, a cauda longa no lado direito da distribuição revela a presença de algumas propriedades com preços excepcionalmente altos, que podem ser considerados outliers. Esses padrões são importantes para entender a dinâmica dos preços e orientar análises mais aprofundadas.
saleprice_skewness = skew(df["SalePrice"], bias=False)
print(f"Skewness de SalePrice: {saleprice_skewness}")
Skewness de SalePrice: 1.743500075737647
A interpretação do coeficiente de skewness (assimetria) é uma medida essencial para avaliar a simetria da distribuição de uma variável. Um valor positivo indica uma assimetria à direita, caracterizada por uma cauda mais longa no lado direito da distribuição, como observado nos gráficos da variável SalePrice. Um valor negativo indica uma assimetria à esquerda, onde a cauda mais longa está no lado esquerdo. Já valores próximos de 0 sugerem uma distribuição aproximadamente simétrica. Essa análise é fundamental para compreender a natureza da variável e suas implicações em modelos estatísticos ou preditivos.
plt.figure(figsize=(8, 6))
sns.boxplot(x=df["SalePrice"], color="orange")
plt.title("Boxplot de SalePrice para Identificação de Outliers")
plt.xlabel("Preço de Venda (SalePrice)")
plt.show()
A análise do gráfico de boxplot para a variável SalePrice destaca importantes características da distribuição dos dados. A linha dentro da caixa representa a mediana, que está em torno de 200.000 dólares, refletindo o preço central da maioria das propriedades. A maior parte dos dados está concentrada no intervalo interquartil (IQR), que varia aproximadamente entre 150.000 e 250.000 dólares, abrangendo cerca de 50% das observações. No entanto, uma análise baseada no princípio de Pareto revela que uma minoria das propriedades, representada por valores acima de 300.000 dólares, contribui de forma desproporcional para o valor total. Esses valores são identificados como outliers, indicados pelos pontos isolados no gráfico. Entre eles, um ou mais valores ultrapassam 700.000 dólares, reforçando a existência de propriedades de altíssimo valor que desviam significativamente da norma, o que pode influenciar análises estatísticas e preditivas.
Seleção de Variáveis para ANOVA
1. Neighborhood (Bairros)
Motivo da Escolha: A localização é um dos fatores mais importantes no mercado imobiliário, com bairros apresentando preços médios significativamente diferentes.
Níveis para ANOVA: Cada bairro é considerado um nível, permitindo comparações diretas entre eles.
2. OverallQual (Qualidade Geral dos Materiais e Acabamentos)
Motivo da Escolha: A qualidade dos materiais e acabamentos impacta diretamente o preço de venda. Propriedades de alta qualidade são geralmente mais valorizadas.
Níveis para ANOVA: Classificações de qualidade (de 1 a 10) fornecem grupos claros para análise.
3. GarageCars (Capacidade da Garagem em Carros)
Motivo da Escolha: O tamanho da garagem é um fator prático e valorizado pelos compradores. Garagens maiores tendem a influenciar positivamente o preço.
Níveis para ANOVA: O número de carros suportados (0, 1, 2, etc.) fornece uma divisão natural para comparação.
O pré-processamento dos dados foi realizado com base em dois aspectos principais: (i) devido à sensibilidade da técnica ANOVA de lidar com valores nulos e constatou que 1 registro contém dados falatantes, adotou-se a premissa de excluir todo o registro. É importante destacar que lidar com valores missing exige técnicas específicas e conhecimento do domínio do negócio para minimizar impactos na análise. (ii) Além disso, foi realizada a padronização dos rótulos das features selecionadas, removendo espaços nos nomes das variáveis para garantir consistência e facilitar o processamento posterior. Esses passos foram essenciais para preparar o conjunto de dados para a aplicação das técnicas estatísticas.
print(missing_data)
Pool QC 2917 Misc Feature 2824 Alley 2732 Fence 2358 Mas Vnr Type 1775 Fireplace Qu 1422 Lot Frontage 490 Garage Qual 159 Garage Cond 159 Garage Yr Blt 159 Garage Finish 159 Garage Type 157 Bsmt Exposure 83 BsmtFin Type 2 81 Bsmt Cond 80 Bsmt Qual 80 BsmtFin Type 1 80 Mas Vnr Area 23 Bsmt Full Bath 2 Bsmt Half Bath 2 BsmtFin SF 1 1 BsmtFin SF 2 1 Electrical 1 Total Bsmt SF 1 Bsmt Unf SF 1 Garage Area 1 Garage Cars 1 dtype: int64
feature_anova = ['Neighborhood', 'Garage Cars', 'Overall Qual', 'SalePrice']
df_anova = df[feature_anova]
df_anova.head()
| Neighborhood | Garage Cars | Overall Qual | SalePrice | |
|---|---|---|---|---|
| 0 | NAmes | 2.0 | 6 | 215000 |
| 1 | NAmes | 1.0 | 5 | 105000 |
| 2 | NAmes | 1.0 | 6 | 172000 |
| 3 | NAmes | 2.0 | 7 | 244000 |
| 4 | Gilbert | 2.0 | 5 | 189900 |
df_anova.shape
(2930, 4)
df_anova.dropna(axis=0, inplace=True)
df_anova.shape
(2929, 4)
df_anova.columns
Index(['Neighborhood', 'Garage Cars', 'Overall Qual', 'SalePrice'], dtype='object')
df_anova.rename(columns={'Garage Cars': 'GarageCars', 'Overall Qual':'OverallQual'}, inplace=True)
df_anova.head()
| Neighborhood | GarageCars | OverallQual | SalePrice | |
|---|---|---|---|---|
| 0 | NAmes | 2.0 | 6 | 215000 |
| 1 | NAmes | 1.0 | 5 | 105000 |
| 2 | NAmes | 1.0 | 6 | 172000 |
| 3 | NAmes | 2.0 | 7 | 244000 |
| 4 | Gilbert | 2.0 | 5 | 189900 |
Neighborhood vs. SalePrice
Objetivo: Analisar como diferentes bairros influenciam o preço médio das propriedades.
Os bairros podem desempenhar um papel crucial na determinação do preço de venda das propriedades? Empiricamente, fatores como localização, infraestrutura, segurança e proximidade a serviços essenciais variam entre regiões, e se não tivermos de posse disso, como faremos?
Nesta análise, a variável Neighborhood será examinada em relação ao SalePrice, utilizando a ANOVA para identificar diferenças significativas entre os preços médios das propriedades nos diferentes bairros.
df_anova.groupby('Neighborhood')['SalePrice'].mean()
Neighborhood Blmngtn 196661.678571 Blueste 143590.000000 BrDale 105608.333333 BrkSide 124756.250000 ClearCr 208662.090909 CollgCr 201803.434457 Crawfor 207550.834951 Edwards 130843.381443 Gilbert 190646.575758 Greens 193531.250000 GrnHill 280000.000000 IDOTRR 103240.336957 Landmrk 137000.000000 MeadowV 95756.486486 Mitchel 162226.631579 NAmes 145097.349887 NPkVill 140710.869565 NWAmes 188406.908397 NoRidge 330319.126761 NridgHt 322018.265060 OldTown 123991.891213 SWISU 135071.937500 Sawyer 136751.152318 SawyerW 184070.184000 Somerst 229707.324176 StoneBr 324229.196078 Timber 246599.541667 Veenker 248314.583333 Name: SalePrice, dtype: float64
plt.figure(figsize=(12, 6))
sns.boxplot(data=df_anova, x='Neighborhood', y='SalePrice')
plt.xticks(rotation=45)
plt.title('Distribuição de SalePrice por Neighborhood')
plt.ylabel('Preço de Venda (SalePrice)')
plt.xlabel('Bairro (Neighborhood)')
plt.show()
A análise da relação entre Neighborhood e SalePrice revela padrões claros no impacto da localização sobre os preços das propriedades. Bairros como NridgHt e StoneBr possuem preços consistentemente altos, refletindo maior valorização e exclusividade, enquanto bairros como Edwards e BrDale apresentam preços médios mais baixos, indicando menor valorização imobiliária. A variabilidade de preços também varia entre os bairros: regiões como NAmes e Gilbert mostram ampla dispersão, incluindo outliers significativos, enquanto BrDale apresenta uma faixa de preços mais estreita. Esses resultados reforçam que o bairro é um forte indicador do preço das propriedades, com áreas de prestígio mostrando maior demanda e preços elevados.
OverallQual vs. SalePrice
Objetivo: Explorar como a qualidade geral dos materiais e acabamentos influencia o preço de venda.
A variável OverallQual mede a qualidade geral dos materiais e acabamentos de uma propriedade, com classificações que variam de 1 (qualidade muito baixa) a 10 (qualidade excelente). Essa característica tem um impacto direto no preço de venda, pois propriedades com materiais e acabamentos superiores geralmente são mais valorizadas. Faz sentido? vamos testar?
df_anova.groupby('OverallQual')['SalePrice'].mean()
OverallQual 1 48725.000000 2 52325.307692 3 83185.975000 4 106485.097345 5 134732.908981 6 162130.318306 7 205025.760797 8 270913.594286 9 368336.766355 10 450217.322581 Name: SalePrice, dtype: float64
avg_price_quality = df_anova.groupby('OverallQual')['SalePrice'].mean().reset_index()
plt.figure(figsize=(8, 5))
sns.barplot(data=avg_price_quality, x='OverallQual', y='SalePrice')
plt.title('Média de SalePrice por Overall Qual')
plt.ylabel('Preço Médio de Venda (SalePrice)')
plt.xlabel('Qualidade Geral (Overall Qual)')
plt.show()
A análise de OverallQual mostra uma tendência crescente, onde o preço médio de venda (SalePrice) aumenta consistentemente com a qualidade geral. Casas com qualidade superior (níveis 9 e 10) apresentam preços médios significativamente mais altos, frequentemente acima de $400.000.
plt.figure(figsize=(8, 5))
sns.regplot(data=df_anova, x='OverallQual', y='SalePrice', scatter_kws={'alpha':0.6})
plt.title('Relação entre OverallQual e SalePrice')
plt.ylabel('Preço de Venda (SalePrice)')
plt.xlabel('Qualidade Geral (OverallQual)')
plt.show()
A análise de OverallQual revela uma correlação linear positiva com SalePrice, evidenciada pela linha de regressão ajustada. No entanto, há variabilidade dentro de cada nível de qualidade, indicando que outros fatores também influenciam o preço final.
GarageCars vs. SalePrice
Objetivo: Avaliar o impacto do tamanho da garagem no preço de venda.
A variável GarageCars representa a capacidade da garagem, medida pelo número de carros que ela pode acomodar.
df_anova.groupby('GarageCars')['SalePrice'].mean()
GarageCars 0.0 104949.254777 1.0 127267.422879 2.0 183562.102932 3.0 310304.622995 4.0 228748.687500 5.0 126500.000000 Name: SalePrice, dtype: float64
avg_price_garage = df_anova.groupby('GarageCars')['SalePrice'].mean().reset_index()
plt.figure(figsize=(8, 5))
sns.barplot(data=avg_price_garage, x='GarageCars', y='SalePrice')
plt.title('Média de SalePrice por GarageCars')
plt.ylabel('Preço Médio de Venda (SalePrice)')
plt.xlabel('Capacidade da Garagem (GarageCars)')
plt.show()
A análise de GarageCars mostra que o preço médio de venda (SalePrice) aumenta com a capacidade da garagem, atingindo o pico em garagens para 3 carros (~$300.000), que são altamente valorizadas. No entanto, garagens maiores (4 ou mais carros) apresentam preços médios menores.
plt.figure(figsize=(8, 5))
sns.scatterplot(data=df_anova, x='GarageCars', y='SalePrice', alpha=0.6)
plt.title('Relação entre Garage Cars e SalePrice')
plt.ylabel('Preço de Venda (SalePrice)')
plt.xlabel('Capacidade da Garagem (Garage Cars)')
plt.show()
A análise de GarageCars indica uma correlação positiva entre a capacidade da garagem e o preço de venda (SalePrice), com propriedades maiores tendendo a preços mais altos. Capacidades de 0, 1 e 2 carros apresentam maior densidade de propriedades, enquanto garagens para 3 carros têm preços significativamente maiores, mas também mostram maior variabilidade, incluindo outliers. Garagens para 4 ou 5 carros são raras e algumas apresentam preços muito elevados, sugerindo influência de fatores adicionais, como localização ou qualidade geral.
ANOVA: Comparação de Preços Médios
Nesta etapa, aplica-se o teste de ANOVA para avaliar se há diferenças significativas nos preços de venda (SalePrice) em relação às três características selecionadas: Neighborhood, OverallQual, e GarageCars. Para cada variável, o teste de ANOVA compara as médias dos preços entre os grupos formados por suas categorias. O objetivo é identificar se a variação do preço médio pode ser explicada de forma estatisticamente significativa por essas características. Os valores-p resultantes para cada análise são armazenados em um dicionário consolidado para facilitar a revisão e interpretação dos resultados.
Princípios do ANOVA
Hipóteses:
- H₀: Todas as médias dos grupos são iguais.
- H₁: Pelo menos uma média de grupo é diferente.
Divisão da Variância: O ANOVA divide a variância total em duas partes:
- Entre os grupos: Diferença nas médias dos grupos.
- Dentro dos grupos: Variabilidade interna de cada grupo.
Resultado do Teste: O valor-p representa a probabilidade de que as diferenças observadas entre as médias sejam devido ao acaso. Se valor-p < 0.05, rejeitamos H₀, indicando diferenças significativas.
anova_results = {}
anova_neighborhood = f_oneway(*[df_anova[df_anova['Neighborhood'] == n]['SalePrice'] for n in df_anova['Neighborhood'].unique()])
anova_results['Neighborhood'] = anova_neighborhood.pvalue
anova_overallqual = f_oneway(*[df_anova[df_anova['OverallQual'] == q]['SalePrice'] for q in df_anova['OverallQual'].unique()])
anova_results['Overall Qual'] = anova_overallqual.pvalue
anova_garagecars = f_oneway(*[df_anova[df_anova['GarageCars'] == g]['SalePrice'] for g in df_anova['GarageCars'].unique()])
anova_results['Garage Cars'] = anova_garagecars.pvalue
results = {"ANOVA Results (p-values)": anova_results}
tools.display_dataframe_to_user(name="Resultados de ANOVA e Validação de Pressupostos", dataframe=pd.DataFrame(results))
Resultados de ANOVA e Validação de Pressupostos
| ANOVA Results (p-values) | |
|---|---|
| Loading ITables v2.2.4 from the internet... (need help?) |
Os resultados da ANOVA mostram que, para todas as variáveis analisadas (Neighborhood, OverallQual, e GarageCars), os valores-p foram iguais a 0, indicando diferenças significativas nos preços médios de venda. Conclui-se que a localização, a qualidade geral dos materiais e acabamentos, e o tamanho da garagem são fatores relevantes que impactam diretamente o preço de venda.
from statsmodels.formula.api import ols
# Melting the filtered data for analysis in the OLS model
melted_data_for_ols_Neighborhood = pd.melt(df_anova, id_vars=['Neighborhood'], value_vars=['SalePrice'])
# Ordinary Least Squares (OLS) model
model_Neighborhood = ols('value ~ Neighborhood', data=melted_data_for_ols_Neighborhood).fit()
# Performing ANOVA
anova_table_Neighborhood = sm.stats.anova_lm(model_Neighborhood, typ=2)
# Melting the filtered data for analysis in the OLS model
melted_data_for_ols_OverallQual = pd.melt(df_anova, id_vars=['OverallQual'], value_vars=['SalePrice'])
# Ordinary Least Squares (OLS) model
model_OverallQual = ols('value ~ OverallQual', data=melted_data_for_ols_OverallQual).fit()
# Performing ANOVA
anova_table_OverallQual = sm.stats.anova_lm(model_OverallQual, typ=2)
# Melting the filtered data for analysis in the OLS model
melted_data_for_ols_GarageCars = pd.melt(df_anova, id_vars=['GarageCars'], value_vars=['SalePrice'])
# Ordinary Least Squares (OLS) model
model_GarageCars = ols('value ~ GarageCars', data=melted_data_for_ols_GarageCars).fit()
# Performing ANOVA
anova_table_GarageCars = sm.stats.anova_lm(model_GarageCars, typ=2)
# Displaying the ANOVA table
anova_table_Neighborhood
| sum_sq | df | F | PR(>F) | |
|---|---|---|---|---|
| Neighborhood | 1.071736e+13 | 27.0 | 144.404258 | 0.0 |
| Residual | 7.974285e+12 | 2901.0 | NaN | NaN |
# Displaying the ANOVA table
anova_table_OverallQual
| sum_sq | df | F | PR(>F) | |
|---|---|---|---|---|
| OverallQual | 1.194065e+13 | 1.0 | 5177.056079 | 0.0 |
| Residual | 6.750995e+12 | 2927.0 | NaN | NaN |
# Displaying the ANOVA table
anova_table_GarageCars
| sum_sq | df | F | PR(>F) | |
|---|---|---|---|---|
| GarageCars | 7.845707e+12 | 1.0 | 2117.325984 | 0.0 |
| Residual | 1.084594e+13 | 2927.0 | NaN | NaN |
Validação de Pressupostos para Interpretação da ANOVA
Antes de interpretar os resultados do teste ANOVA tradicional, é essencial validar seus pressupostos. A ANOVA assume que os dados seguem uma distribuição normal em cada grupo e que as variâncias entre os grupos são homogêneas. A validação desses pressupostos é crucial para garantir a confiabilidade dos resultados e evitar conclusões equivocadas. Caso essas condições não sejam atendidas, métodos alternativos, como testes não paramétricos, devem ser considerados.
Teste de Normalidade
Objetivo: Verificar se os resíduos do modelo ANOVA seguem uma distribuição normal, conforme exigido pelo pressuposto da ANOVA tradicional.
Para testar a normalidade, utiliza-se o teste de Shapiro-Wilk, bem como visualizações como o histograma e o Q-Q Plot. Resíduos que não seguem uma distribuição normal podem comprometer a validade dos resultados da ANOVA. Desvios significativos, especialmente nas extremidades, indicam que o pressuposto de normalidade foi violado, sendo necessário considerar alternativas não paramétricas para fazer inferências.
shapiro_tests = {}
shapiro_tests['Neighborhood'] = shapiro(df_anova['SalePrice'])[1]
shapiro_tests['OverallQual'] = shapiro(df_anova['SalePrice'])[1]
shapiro_tests['GarageCars'] = shapiro(df_anova['SalePrice'])[1]
results = {
"Normalidade (Shapiro-Wilk p-values)": shapiro_tests
}
tools.display_dataframe_to_user(name="Validação de Pressupostos", dataframe=pd.DataFrame(results))
Validação de Pressupostos
| Normalidade (Shapiro-Wilk p-values) | |
|---|---|
| Loading ITables v2.2.4 from the internet... (need help?) |
Os p-valores extremamente baixos (2.408963e-43) indicam violação da normalidade dos resíduos.
Teste de Homogeneidade das Variâncias
Objetivo: Avaliar se as variâncias dos grupos são homogêneas, uma condição essencial para a aplicação da ANOVA tradicional.
O teste de Levene ou de Bartlett pode ser usado para verificar a homogeneidade das variâncias. No scatterplot de resíduos versus valores ajustados, padrões como aumento da variabilidade (padrão em funil) sugerem heterocedasticidade. A violação deste pressuposto pode impactar a confiabilidade das conclusões, indicando a necessidade de técnicas robustas ou ajustes nos dados.
levene_tests = {}
levene_tests['Neighborhood'] = levene(*[df_anova[df_anova['Neighborhood'] == n]['SalePrice'] for n in df_anova['Neighborhood'].unique()]).pvalue
levene_tests['OverallQual'] = levene(*[df_anova[df_anova['OverallQual'] == q]['SalePrice'] for q in df_anova['OverallQual'].unique()]).pvalue
levene_tests['GarageCars'] = levene(*[df_anova[df_anova['GarageCars'] == g]['SalePrice'] for g in df_anova['GarageCars'].unique()]).pvalue
results = {
"Homogeneidade (Levene p-values)": levene_tests
}
tools.display_dataframe_to_user(name="Validação de Pressupostos", dataframe=pd.DataFrame(results))
Validação de Pressupostos
| Homogeneidade (Levene p-values) | |
|---|---|
| Loading ITables v2.2.4 from the internet... (need help?) |
P-valores muito baixos para todas as características (Neighborhood, OverallQual, GarageCars), indicando que as variâncias entre os grupos não são homogêneas.
Teste dos Resíduos com ANOVA Tradicional
Objetivo: Verificar se os resíduos do modelo ANOVA tradicional atendem aos pressupostos de normalidade, homogeneidade de variâncias e independência.
Os resíduos do modelo são as diferenças entre os valores observados e as médias estimadas para cada grupo. Na ANOVA tradicional, é crucial testar se esses resíduos:
- Seguem uma distribuição normal, validada por testes como Shapiro-Wilk ou QQ-Plot;
- Apresentam homogeneidade de variâncias, avaliada por testes como Levene ou Bartlett;
- São independentes, não pode haver multicolinearidade entre as varíaveis preditoras.
def plot_residuals(variable, data):
model = ols(f'SalePrice ~ C({variable})', data=data).fit()
residuals = model.resid
# Histograma dos resíduos
plt.figure(figsize=(12, 6))
plt.subplot(1, 3, 1)
sns.histplot(residuals, kde=True, color='blue')
plt.title(f'Histograma dos Resíduos ({variable})')
plt.xlabel('Resíduos')
# Q-Q Plot
plt.subplot(1, 3, 2)
sm.qqplot(residuals, line='s', ax=plt.gca())
plt.title(f'Q-Q Plot ({variable})')
# Scatterplot: Resíduos vs Valores Ajustados
fitted_values = model.fittedvalues
plt.subplot(1, 3, 3)
plt.scatter(fitted_values, residuals, alpha=0.6, color='red')
plt.axhline(0, color='black', linestyle='--', linewidth=1)
plt.title(f'Resíduos vs Ajustados ({variable})')
plt.xlabel('Valores Ajustados')
plt.ylabel('Resíduos')
plt.tight_layout()
plt.show()
plot_residuals('Neighborhood', df_anova)
plot_residuals('OverallQual', df_anova)
plot_residuals('GarageCars', df_anova)
A análise dos resíduos revela que os pressupostos da ANOVA tradicional foram violados. O histograma dos resíduos mostra assimetria, indicando que a normalidade não é perfeita. No Q-Q Plot, os desvios das caudas reforçam a ausência de normalidade. O scatterplot de resíduos versus valores ajustados sugere heterocedasticidade, com maior variabilidade em valores ajustados mais altos, violando a homogeneidade das variâncias. Esses resultados destacam limitações na aplicação da ANOVA tradicional.
Testes não paramétricos
O teste de Kruskal-Wallis é uma alternativa não paramétrica à ANOVA, utilizado para comparar k amostras independentes (k > 2), especialmente quando as hipóteses de normalidade e homogeneidade das variâncias são violadas ou quando os dados estão em escala ordinal. Segundo Belfiore (2015), este teste verifica se as k amostras são provenientes da mesma população ou de populações com a mesma mediana (μ). Os dados são organizados em uma tabela de dupla entrada, onde as linhas representam as observações e as colunas, os grupos. Em casos com k = 2, o teste é equivalente ao teste Mann-Whitney. O Kruskal-Wallis é particularmente útil em situações com tamanhos de amostra pequenos ou dados que não atendem às premissas dos testes paramétricos, proporcionando uma análise robusta e confiável em cenários desafiadores. (BELFIORE, 2015)
Sendo uma alternativa não paramétrica ao ANOVA e utilizado quando as premissas de normalidade e homogeneidade das variâncias são violadas, esse teste de Kruskal-Wallis compara as medianas de dois ou mais grupos, sendo ideal para variáveis categóricas com múltiplos níveis (como Neighborhood) e uma variável contínua (SalePrice).
Hipóteses:
- H₀: As distribuições dos grupos são idênticas.
- H₁: Pelo menos uma distribuição é diferente.
Funcionamento: Os valores são ranqueados, e o teste avalia diferenças nas somas dos rankings entre os grupos. O valor-p indica se as diferenças observadas são significativas:
- Valor-p < 0.05: Rejeitamos H₀, indicando diferenças significativas.
- Valor-p ≥ 0.05: Não rejeitamos H₀, sugerindo medianas similares.
# Neighborhood
kruskal_neighborhood = kruskal(*[df_anova[df_anova['Neighborhood'] == n]['SalePrice'] for n in df_anova['Neighborhood'].unique()])
# OverallQual
kruskal_overallqual = kruskal(*[df_anova[df_anova['OverallQual'] == q]['SalePrice'] for q in df_anova['OverallQual'].unique()])
# GarageCars
kruskal_garagecars = kruskal(*[df_anova[df_anova['GarageCars'] == g]['SalePrice'] for g in df_anova['GarageCars'].unique()])
print("Kruskal-Wallis Results:")
print(f"Neighborhood: H-statistic = {kruskal_neighborhood.statistic}, p-value = {kruskal_neighborhood.pvalue}")
print(f"OverallQual: H-statistic = {kruskal_overallqual.statistic}, p-value = {kruskal_overallqual.pvalue}")
print(f"GarageCars: H-statistic = {kruskal_garagecars.statistic}, p-value = {kruskal_garagecars.pvalue}")
Kruskal-Wallis Results: Neighborhood: H-statistic = 1799.0853609248172, p-value = 0.0 OverallQual: H-statistic = 1937.79982200856, p-value = 0.0 GarageCars: H-statistic = 1459.5960458881416, p-value = 0.0
Os resultados do teste de Kruskal-Wallis indicam que todas as variáveis analisadas (Neighborhood, OverallQual, e GarageCars) têm um impacto significativo no preço de venda (SalePrice). Com valores-p iguais a 0 para todas as variáveis, rejeitamos a hipótese nula, concluindo que há diferenças estatisticamente significativas entre os grupos. Esses resultados destacam que localização, qualidade geral e capacidade da garagem influenciam diretamente o preço dos imóveis.
Após os resultados do teste de Kruskal-Wallis, que indicaram diferenças significativas entre os grupos das variáveis Neighborhood, OverallQual, e GarageCars, utilizamos o gráfico de violino para ilustrar visualmente essas diferenças. Esse tipo de gráfico combina a distribuição dos dados em cada classe com uma representação da densidade, permitindo observar tanto a variabilidade interna dos grupos quanto a sobreposição entre eles. Dessa forma, os gráficos de violino reforçam os resultados estatísticos, destacando como cada classe dentro das variáveis analisadas contribui para a diferenciação nos preços de venda (SalePrice).
plt.figure(figsize=(14, 8))
sns.violinplot(x='Neighborhood', y='SalePrice', data=df_anova, inner='quartile')
plt.title('Distribuição de Preços por Bairro (Neighborhood)')
plt.xticks(rotation=45)
plt.show()
O gráfico de violino para Neighborhood mostra diferenças claras na distribuição de preços entre os bairros. Alguns bairros, como NridgHt e StoneBr, possuem distribuições com preços consistentemente altos, enquanto outros, como BrDale e MeadowV, apresentam preços mais baixos e menos variabilidade. A presença de distribuições assimétricas e outliers em alguns bairros reforça a importância da localização como fator determinante no preço de venda.
plt.figure(figsize=(10, 6))
sns.violinplot(x='OverallQual', y='SalePrice', data=df_anova, inner='quartile')
plt.title('Distribuição de Preços por Qualidade Geral (OverallQual)')
plt.show()
Para OverallQual, esse plot revela uma tendência clara: conforme a qualidade geral dos materiais aumenta, o preço de venda (SalePrice) também cresce significativamente. Níveis mais altos de qualidade (9 e 10) apresentam distribuições mais amplas, incluindo propriedades com preços mais altos. Já níveis baixos de qualidade (1 a 4) têm uam densidade de concentração nos níveis de preços mais baixos. Isso reforça o impacto direto da qualidade dos materiais no valor de mercado das propriedades.
plt.figure(figsize=(10, 6))
sns.violinplot(x='GarageCars', y='SalePrice', data=df_anova, inner='quartile')
plt.title('Distribuição de Preços por Capacidade de Garagem (GarageCars)')
plt.show()
Para a quantidade de garagens dessas casas, GarageCars, mostra que o preço de venda (SalePrice) tende a aumentar conforme a capacidade da garagem cresce, especialmente até o nível de 3 carros. Sendo esse nível (até 3 carros) que apresenta os preços mais elevados e uma ampla variabilidade.
Após os resultados do teste de Kruskal-Wallis, que indicaram diferenças significativas nos preços de venda (SalePrice) entre os bairros, foi necessário investigar mais profundamente como essas diferenças se manifestam entre pares de bairros específicos. Para isso, utilizamos o teste não paramétrico Mann-Whitney U, ideal para comparar duas amostras independentes, como os bairros "Gilbert" e "StoneBr". Esses bairros foram escolhidos com base em suas distribuições de preços no gráfico de violino, que indicaram diferenças aparentes em suas medianas e amplitudes. Essa abordagem permite identificar se as diferenças observadas entre os dois bairros são estatisticamente significativas.
Segundo Belfiore (2015), o teste U de Mann-Whitney é uma alternativa não paramétrica ao teste t de Student, utilizado para comparar duas amostras independentes quando a hipótese de normalidade é violada ou o tamanho da amostra é pequeno. Esse teste avalia a igualdade das medianas entre as amostras, utilizando a transformação dos dados em postos. Embora perca um pouco de poder em relação ao teste t, é amplamente aplicado devido à sua robustez em condições menos restritivas.
group1 = df_anova[df_anova['Neighborhood'] == "Gilbert"]['SalePrice']
group2 = df_anova[df_anova['Neighborhood'] == "StoneBr"]['SalePrice']
mann_whitney_result = mannwhitneyu(group1, group2)
test_results = {
"Mann-Whitney U (Neighborhoods entre Gilbert e StoneBr)": {
"Statistic": mann_whitney_result.statistic,
"p-value": mann_whitney_result.pvalue,
}
}
tools.display_dataframe_to_user(name="Resultados dos Testes Não Paramétricos", dataframe=pd.DataFrame(test_results))
Resultados dos Testes Não Paramétricos
| Mann-Whitney U (Neighborhoods entre Gilbert e StoneBr) | |
|---|---|
| Loading ITables v2.2.4 from the internet... (need help?) |
O valor-p é extremamente pequeno (muito menor que 0.05), indicando que há uma diferença significativa entre os dois bairros analisados. Isso significa que as distribuições dos preços de venda (SalePrice) nesses dois bairros não são iguais.
Após identificar diferenças significativas entre múltiplos grupos por meio de testes como o Kruskal-Wallis, é fundamental determinar quais grupos específicos diferem entre si. Para isso, utilizamos testes post hoc, que realizam comparações múltiplas para identificar pares de grupos com diferenças estatisticamente significativas (Estatística Fácil).
Entre os testes post hoc disponíveis, o teste de Dunn é uma análise não paramétrica eficaz para comparações múltiplas entre grupos independentes. Ele realiza comparações par a par entre os grupos e indica quais pares apresentam diferenças estatisticamente significativas em um determinado nível de significância (Statorials).
O ajuste de Bonferroni foi utilizado como parâmetro no teste de Dunn para corrigir o nível de significância em comparações múltiplas. Quando realizamos muitos testes simultaneamente, como no caso de comparações par a par entre grupos, o risco de cometer erros do tipo I (falsos positivos) aumenta. O ajuste de Bonferroni reduz esse risco, dividindo o nível de significância (α) pelo número de comparações realizadas. Isso garante que os resultados permaneçam confiáveis, mesmo ao lidar com múltiplos pares de grupos.
# Neighborhood
dunn_neighborhood = sp.posthoc_dunn(df_anova, val_col='SalePrice', group_col='Neighborhood', p_adjust='bonferroni')
# indicando os nomes dos bairros
dunn_neighborhood.index = dunn_neighborhood.columns = df_anova['Neighborhood'].unique()
# OverallQual
dunn_overallqual = sp.posthoc_dunn(df_anova, val_col='SalePrice', group_col='OverallQual', p_adjust='bonferroni')
# GarageCars
dunn_garagecars = sp.posthoc_dunn(df_anova, val_col='SalePrice', group_col='GarageCars', p_adjust='bonferroni')
results_dunn = {
"Neighborhood": dunn_neighborhood,
"OverallQual": dunn_overallqual,
"GarageCars": dunn_garagecars
}
for variable, result in results_dunn.items():
print(f"Resultados do Teste de Dunn para {variable}:")
print(result)
print("\n")
Resultados do Teste de Dunn para Neighborhood:
NAmes Gilbert StoneBr NWAmes Somerst \
NAmes 1.000000e+00 1.000000 9.476928e-11 3.642617e-09 1.000000e+00
Gilbert 1.000000e+00 1.000000 1.000000e+00 1.000000e+00 4.599787e-01
StoneBr 9.476928e-11 1.000000 1.000000e+00 1.000000e+00 5.757742e-14
NWAmes 3.642617e-09 1.000000 1.000000e+00 1.000000e+00 5.855917e-14
Somerst 1.000000e+00 0.459979 5.757742e-14 5.855917e-14 1.000000e+00
BrDale 1.000000e+00 0.562534 3.707741e-19 1.741906e-30 1.000000e+00
NPkVill 1.000000e+00 0.717226 1.814349e-16 8.814735e-21 1.000000e+00
NridgHt 3.581866e-09 1.000000 1.000000e+00 1.000000e+00 1.220744e-14
Blmngtn 1.000000e+00 0.845474 2.088080e-17 1.142385e-24 1.000000e+00
NoRidge 1.000000e+00 1.000000 6.222772e-04 3.655834e-02 1.000000e+00
SawyerW 1.000000e+00 1.000000 1.143249e-01 9.333566e-01 1.000000e+00
Sawyer 6.763374e-14 1.000000 1.000000e+00 1.000000e+00 2.152595e-20
Greens 1.000000e+00 1.000000 1.000000e+00 1.000000e+00 1.000000e+00
BrkSide 6.489281e-13 1.000000 1.000000e+00 1.000000e+00 4.115140e-17
OldTown 2.971875e-01 1.000000 1.211676e-06 1.571007e-05 1.166521e-02
IDOTRR 2.782004e-05 1.000000 1.353277e-03 8.537697e-02 3.128040e-09
ClearCr 3.366738e-02 1.000000 1.000000e+00 1.000000e+00 3.948854e-03
SWISU 1.000000e+00 1.000000 2.552779e-15 7.647365e-20 1.000000e+00
Edwards 3.645136e-02 0.000002 4.350657e-35 2.852576e-49 4.658095e-03
CollgCr 5.892801e-02 0.000003 1.788844e-39 2.407841e-69 4.673292e-03
Crawfor 2.695215e-11 1.000000 1.000000e+00 1.000000e+00 5.030906e-18
Blueste 9.540438e-05 1.000000 1.000000e+00 1.000000e+00 6.399638e-07
Mitchel 1.727987e-06 1.000000 1.266739e-01 1.000000e+00 1.911439e-10
Timber 1.000000e+00 1.000000 1.381964e-12 5.488557e-15 1.000000e+00
MeadowV 1.000000e+00 0.008635 2.756164e-26 7.454469e-43 1.000000e+00
Veenker 1.000000e+00 0.000106 5.691476e-27 4.102302e-33 6.745770e-01
GrnHill 1.000000e+00 0.004509 1.404205e-23 2.040611e-30 1.000000e+00
Landmrk 1.000000e+00 0.022101 5.923956e-15 7.585747e-14 1.000000e+00
BrDale NPkVill NridgHt Blmngtn NoRidge \
NAmes 1.000000e+00 1.000000e+00 3.581866e-09 1.000000e+00 1.000000
Gilbert 5.625342e-01 7.172258e-01 1.000000e+00 8.454735e-01 1.000000
StoneBr 3.707741e-19 1.814349e-16 1.000000e+00 2.088080e-17 0.000622
NWAmes 1.741906e-30 8.814735e-21 1.000000e+00 1.142385e-24 0.036558
Somerst 1.000000e+00 1.000000e+00 1.220744e-14 1.000000e+00 1.000000
BrDale 1.000000e+00 1.000000e+00 1.475204e-40 1.000000e+00 1.000000
NPkVill 1.000000e+00 1.000000e+00 3.872894e-24 1.000000e+00 1.000000
NridgHt 1.475204e-40 3.872894e-24 1.000000e+00 1.283627e-30 0.060739
Blmngtn 1.000000e+00 1.000000e+00 1.283627e-30 1.000000e+00 1.000000
NoRidge 1.000000e+00 1.000000e+00 6.073925e-02 1.000000e+00 1.000000
SawyerW 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000
Sawyer 2.793761e-42 5.627196e-30 5.981728e-01 3.543503e-35 0.000667
Greens 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000
BrkSide 3.557324e-25 4.641957e-21 2.234424e-01 1.194421e-22 0.000148
OldTown 6.917644e-06 1.131685e-03 5.325278e-06 2.929627e-04 1.000000
IDOTRR 2.128116e-33 1.780604e-16 5.064922e-02 1.881576e-22 1.000000
ClearCr 9.233306e-04 3.035585e-03 1.000000e+00 2.865896e-03 1.000000
SWISU 1.000000e+00 1.000000e+00 1.094676e-23 1.000000e+00 1.000000
Edwards 4.537258e-10 3.637133e-07 1.751134e-56 2.259631e-09 1.000000
CollgCr 2.730388e-15 5.886943e-09 2.328697e-89 4.892628e-13 1.000000
Crawfor 2.094612e-54 6.136811e-31 1.000000e+00 2.853991e-40 0.014615
Blueste 9.428136e-11 1.585909e-08 1.000000e+00 3.259932e-09 0.579072
Mitchel 6.338688e-26 2.865744e-16 1.000000e+00 5.965175e-20 0.391826
Timber 1.000000e+00 1.000000e+00 1.521537e-17 1.000000e+00 1.000000
MeadowV 9.358315e-02 1.000000e+00 4.725132e-55 1.539159e-01 1.000000
Veenker 3.177103e-04 4.815326e-03 2.800422e-36 4.184084e-04 1.000000
GrnHill 2.346396e-01 1.000000e+00 2.060433e-34 2.417734e-01 1.000000
Landmrk 1.000000e+00 1.000000e+00 5.289234e-14 1.000000e+00 1.000000
... Edwards CollgCr Crawfor Blueste \
NAmes ... 3.645136e-02 5.892801e-02 2.695215e-11 9.540438e-05
Gilbert ... 1.990410e-06 3.243735e-06 1.000000e+00 1.000000e+00
StoneBr ... 4.350657e-35 1.788844e-39 1.000000e+00 1.000000e+00
NWAmes ... 2.852576e-49 2.407841e-69 1.000000e+00 1.000000e+00
Somerst ... 4.658095e-03 4.673292e-03 5.030906e-18 6.399638e-07
BrDale ... 4.537258e-10 2.730388e-15 2.094612e-54 9.428136e-11
NPkVill ... 3.637133e-07 5.886943e-09 6.136811e-31 1.585909e-08
NridgHt ... 1.751134e-56 2.328697e-89 1.000000e+00 1.000000e+00
Blmngtn ... 2.259631e-09 4.892628e-13 2.853991e-40 3.259932e-09
NoRidge ... 1.000000e+00 1.000000e+00 1.461455e-02 5.790718e-01
SawyerW ... 1.000000e+00 1.000000e+00 6.987211e-01 1.000000e+00
Sawyer ... 1.790491e-60 3.998349e-83 1.000000e+00 7.392170e-01
Greens ... 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
BrkSide ... 1.000141e-42 1.029715e-49 1.000000e+00 1.695098e-01
OldTown ... 6.155017e-23 1.632311e-31 1.778103e-09 9.878922e-01
IDOTRR ... 2.344279e-48 1.565441e-86 1.007747e-05 1.000000e+00
ClearCr ... 7.494066e-14 1.322076e-14 1.000000e+00 1.000000e+00
SWISU ... 4.188193e-10 1.511538e-13 3.475265e-31 2.022985e-07
Edwards ... 1.000000e+00 1.000000e+00 5.388632e-66 1.256984e-26
CollgCr ... 1.000000e+00 1.000000e+00 5.413457e-109 1.242282e-31
Crawfor ... 5.388632e-66 5.413457e-109 1.000000e+00 1.000000e+00
Blueste ... 1.256984e-26 1.242282e-31 1.000000e+00 1.000000e+00
Mitchel ... 1.281790e-44 1.009594e-66 1.000000e+00 1.000000e+00
Timber ... 3.548152e-13 7.854088e-18 9.926279e-24 4.068527e-05
MeadowV ... 7.626218e-03 1.265331e-03 1.056487e-69 9.064469e-18
Veenker ... 1.000000e+00 1.000000e+00 2.386181e-42 1.291921e-18
GrnHill ... 1.000000e+00 1.000000e+00 1.862816e-41 3.094264e-15
Landmrk ... 1.000000e+00 1.000000e+00 2.090393e-16 2.213201e-08
Mitchel Timber MeadowV Veenker GrnHill \
NAmes 1.727987e-06 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
Gilbert 1.000000e+00 1.000000e+00 8.635027e-03 1.064576e-04 4.509084e-03
StoneBr 1.266739e-01 1.381964e-12 2.756164e-26 5.691476e-27 1.404205e-23
NWAmes 1.000000e+00 5.488557e-15 7.454469e-43 4.102302e-33 2.040611e-30
Somerst 1.911439e-10 1.000000e+00 1.000000e+00 6.745770e-01 1.000000e+00
BrDale 6.338688e-26 1.000000e+00 9.358315e-02 3.177103e-04 2.346396e-01
NPkVill 2.865744e-16 1.000000e+00 1.000000e+00 4.815326e-03 1.000000e+00
NridgHt 1.000000e+00 1.521537e-17 4.725132e-55 2.800422e-36 2.060433e-34
Blmngtn 5.965175e-20 1.000000e+00 1.539159e-01 4.184084e-04 2.417734e-01
NoRidge 3.918259e-01 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
SawyerW 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
Sawyer 5.908286e-03 1.362620e-23 2.776512e-55 3.207251e-42 4.697358e-40
Greens 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
BrkSide 6.625595e-03 1.708782e-16 1.107351e-33 1.732684e-32 4.009724e-29
OldTown 2.259572e-02 1.000000e+00 7.667610e-14 8.678911e-14 2.252960e-10
IDOTRR 1.000000e+00 3.095698e-10 2.039432e-48 8.495996e-29 1.347805e-26
ClearCr 1.000000e+00 2.256711e-01 1.882041e-07 5.671568e-10 2.526161e-07
SWISU 2.847849e-15 1.000000e+00 2.989857e-02 9.019558e-05 5.943192e-02
Edwards 1.281790e-44 3.548152e-13 7.626218e-03 1.000000e+00 1.000000e+00
CollgCr 1.009594e-66 7.854088e-18 1.265331e-03 1.000000e+00 1.000000e+00
Crawfor 1.000000e+00 9.926279e-24 1.056487e-69 2.386181e-42 1.862816e-41
Blueste 1.000000e+00 4.068527e-05 9.064469e-18 1.291921e-18 3.094264e-15
Mitchel 1.000000e+00 1.115298e-10 1.265653e-38 1.386755e-28 8.615831e-26
Timber 1.115298e-10 1.000000e+00 1.018291e-04 7.173827e-07 8.508374e-04
MeadowV 1.265653e-38 1.018291e-04 1.000000e+00 1.000000e+00 1.000000e+00
Veenker 1.386755e-28 7.173827e-07 1.000000e+00 1.000000e+00 1.000000e+00
GrnHill 8.615831e-26 8.508374e-04 1.000000e+00 1.000000e+00 1.000000e+00
Landmrk 7.044197e-11 3.702665e-01 1.000000e+00 1.000000e+00 1.000000e+00
Landmrk
NAmes 1.000000e+00
Gilbert 2.210129e-02
StoneBr 5.923956e-15
NWAmes 7.585747e-14
Somerst 1.000000e+00
BrDale 1.000000e+00
NPkVill 1.000000e+00
NridgHt 5.289234e-14
Blmngtn 1.000000e+00
NoRidge 1.000000e+00
SawyerW 1.000000e+00
Sawyer 5.043907e-19
Greens 1.000000e+00
BrkSide 1.708875e-17
OldTown 2.374524e-04
IDOTRR 1.248124e-09
ClearCr 8.081704e-05
SWISU 1.000000e+00
Edwards 1.000000e+00
CollgCr 1.000000e+00
Crawfor 2.090393e-16
Blueste 2.213201e-08
Mitchel 7.044197e-11
Timber 3.702665e-01
MeadowV 1.000000e+00
Veenker 1.000000e+00
GrnHill 1.000000e+00
Landmrk 1.000000e+00
[28 rows x 28 columns]
Resultados do Teste de Dunn para OverallQual:
1 2 3 4 5 \
1 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
2 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.263615e-02
3 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.136036e-05
4 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 4.346188e-11
5 1.000000e+00 1.263615e-02 1.136036e-05 4.346188e-11 1.000000e+00
6 6.766878e-02 4.659551e-07 9.379318e-17 1.441635e-47 3.461726e-29
7 1.825201e-04 5.335505e-15 1.181649e-37 1.027198e-121 1.333976e-129
8 4.328370e-07 5.255800e-23 7.704950e-58 1.124369e-174 3.293898e-189
9 8.294305e-09 6.518857e-27 3.293642e-60 3.843044e-122 8.515679e-104
10 5.186127e-08 4.221323e-21 7.068872e-36 1.404916e-45 1.725053e-32
6 7 8 9 10
1 6.766878e-02 1.825201e-04 4.328370e-07 8.294305e-09 5.186127e-08
2 4.659551e-07 5.335505e-15 5.255800e-23 6.518857e-27 4.221323e-21
3 9.379318e-17 1.181649e-37 7.704950e-58 3.293642e-60 7.068872e-36
4 1.441635e-47 1.027198e-121 1.124369e-174 3.843044e-122 1.404916e-45
5 3.461726e-29 1.333976e-129 3.293898e-189 8.515679e-104 1.725053e-32
6 1.000000e+00 1.550159e-37 1.588719e-86 7.063796e-56 1.500973e-17
7 1.550159e-37 1.000000e+00 6.803223e-16 2.441885e-17 2.507932e-05
8 1.588719e-86 6.803223e-16 1.000000e+00 4.882564e-02 1.000000e+00
9 7.063796e-56 2.441885e-17 4.882564e-02 1.000000e+00 1.000000e+00
10 1.500973e-17 2.507932e-05 1.000000e+00 1.000000e+00 1.000000e+00
Resultados do Teste de Dunn para GarageCars:
0.0 1.0 2.0 3.0 4.0 \
0.0 1.000000e+00 5.982412e-04 4.446881e-64 2.967527e-146 7.526057e-12
1.0 5.982412e-04 1.000000e+00 1.419913e-130 6.033504e-243 1.757405e-08
2.0 4.446881e-64 1.419913e-130 1.000000e+00 4.375129e-71 9.259091e-01
3.0 2.967527e-146 6.033504e-243 4.375129e-71 1.000000e+00 4.115659e-01
4.0 7.526057e-12 1.757405e-08 9.259091e-01 4.115659e-01 1.000000e+00
5.0 1.000000e+00 1.000000e+00 1.000000e+00 3.972046e-01 1.000000e+00
5.0
0.0 1.000000
1.0 1.000000
2.0 1.000000
3.0 0.397205
4.0 1.000000
5.0 1.000000
Para aprofundar a análise do impacto do bairro (Neighborhood) no preço de venda (SalePrice), será construído um heatmap. Este gráfico permitirá identificar pares de bairros onde o valor de alfa é menor que 0,05, representados por "1", enquanto pares com alfa maior ou igual a 0,05 serão representados por "0". Essa binarização facilita a visualização e compreensão das relações significativas entre os bairros.
dunn_matrix_neighborhood = dunn_neighborhood.copy()
# Converter valores-p em uma matriz binária: 1 (significativo), 0 (não significativo)
significance_matrix = dunn_matrix_neighborhood.applymap(lambda x: 1 if x < 0.05 else 0)
plt.figure(figsize=(12, 10))
sns.heatmap(significance_matrix, cmap="coolwarm", cbar_kws={'label': 'Significância (0 = Não (p-value ≥ 0.05), 1 = Sim (p-value < 0.05)'})
plt.title("Matriz de Significância do Teste de Dunn - Neighborhood")
plt.xticks(rotation=45, ha='right')
plt.yticks(rotation=0)
plt.show()
O mapa de calor utiliza uma matriz binária para representar a significância estatística entre grupos de Neighborhood:
- 1 (cor quente): Comparação significativa (
p-value < 0.05), indicando diferença nos preços médios. - 0 (cor fria): Comparação não significativa (
p-value ≥ 0.05), sugerindo preços médios semelhantes.
Por exemplo, uma célula quente entre "NAmes" e "StoneBr" indica preços significativamente diferentes, enquanto uma célula fria entre "NAmes" e "Gilbert" sugere preços médios semelhantes.
Conclusões
Com base na análise realizada, selecionamos três características do banco de dados para avaliar seu impacto no preço médio de venda (SalePrice) das propriedades. Essas características foram: Neighborhood (bairros), que representa as localizações físicas das propriedades dentro dos limites da cidade de Ames; OverallQual (qualidade geral), que reflete a qualidade dos materiais e acabamentos; e GarageCars (capacidade da garagem), que indica o número de carros que podem ser acomodados. Os testes aplicados, incluindo ANOVA tradicional, Kruskal-Wallis e testes post hoc (como o de Dunn), mostraram que todas as três variáveis influenciam significativamente o preço médio de venda.
A análise revelou que as distribuições dos preços diferem estatisticamente entre bairros, níveis de qualidade geral e capacidades de garagem, indicando que essas características desempenham papéis determinantes na precificação dos imóveis. Além disso, ao investigar as comparações par a par entre categorias dentro de cada variável, observamos diferenças consistentes, reforçando a importância dessas variáveis como fatores críticos para a valorização das propriedades.
Como questão secundária, avaliamos a possibilidade de linearizar os preços das propriedades para implementar uma campanha promocional com preços únicos para todas as casas do portfólio. No entanto, os resultados indicam que essa abordagem não seria viável. As diferenças significativas encontradas entre os grupos sugerem que os preços são fortemente influenciados por características específicas, como localização, qualidade e tamanho da garagem. Assim, alinhar todos os preços a um valor único ignoraria essas variações e poderia levar a decisões de precificação inadequadas, afetando negativamente o equilíbrio do mercado e a percepção de valor dos imóveis.
Bibliografia
BELFIORE, Patrícia. Estatística - Aplicada à Administração, Contabilidade e Economia com Excel e SPSS. Rio de Janeiro: GEN LTC, 2015. E-book ISBN 9788595155596. Disponível em: https://unibb.minhabiblioteca.com.br/reader/books/9788595155596/. Acesso em: 04 dez. 2024.
Estatística Fácil. "O que é: Post-Hoc Test". Disponível em: https://estatisticafacil.org/glossario/o-que-e-post-hoc-test/. Acesso em: 05 dez. 2024.
KAGGLE. Ames Housing Dataset. Disponível em: https://www.kaggle.com/datasets/prevek18/ames-housing-dataset/data. Acesso em: 08 dez. 2024.
Statorials. "Teste de Dunn para comparações múltiplas". Disponível em: https://statorials.org/pt/teste-dunn/. Acesso em: 05 dez. 2024.
VIRGILLITO, Salvatore B. Estatística Aplicada. Rio de Janeiro: Saraiva Uni, 2017. ISBN 9788547214753. Disponível em: https://unibb.minhabiblioteca.com.br/reader/books/9788547214753/. Acesso em: 04 dez. 2024.