Neste projeto, procurarei realizar uma Análise Exploratória mais detalhada do dataset "House Prices - Advanced Regression Techniques", obtido no link "https://www.kaggle.com/c/house-prices-advanced-regression-techniques".
Este conjunto se constitui em 79 features, que é considerado um número razoavelmente alto, de onde podem se obter informações diversas.
Procuraremos realizar uma análise voltada a entender cada tipo de variável, bem como analisar graficamente cada uma.
Ao final, analisaremos ainda, algumas das principais características dos outliers.
# Importando as bibliotecas necessárias
#Para cálculos e dataframe
import pandas as pd
import numpy as np
#Para criação de gráficos
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
# Algumas configurações iniciais
pd.set_option('display.max_columns',81)
# Carregando os dados de treino
train = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/Projetos/Advanced Houses/train.csv')
# Exibindo o dataset
train
Id | MSSubClass | MSZoning | LotFrontage | LotArea | Street | Alley | LotShape | LandContour | Utilities | LotConfig | LandSlope | Neighborhood | Condition1 | Condition2 | BldgType | HouseStyle | OverallQual | OverallCond | YearBuilt | YearRemodAdd | RoofStyle | RoofMatl | Exterior1st | Exterior2nd | MasVnrType | MasVnrArea | ExterQual | ExterCond | Foundation | BsmtQual | BsmtCond | BsmtExposure | BsmtFinType1 | BsmtFinSF1 | BsmtFinType2 | BsmtFinSF2 | BsmtUnfSF | TotalBsmtSF | Heating | HeatingQC | CentralAir | Electrical | 1stFlrSF | 2ndFlrSF | LowQualFinSF | GrLivArea | BsmtFullBath | BsmtHalfBath | FullBath | HalfBath | BedroomAbvGr | KitchenAbvGr | KitchenQual | TotRmsAbvGrd | Functional | Fireplaces | FireplaceQu | GarageType | GarageYrBlt | GarageFinish | GarageCars | GarageArea | GarageQual | GarageCond | PavedDrive | WoodDeckSF | OpenPorchSF | EnclosedPorch | 3SsnPorch | ScreenPorch | PoolArea | PoolQC | Fence | MiscFeature | MiscVal | MoSold | YrSold | SaleType | SaleCondition | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 60 | RL | 65.0 | 8450 | Pave | NaN | Reg | Lvl | AllPub | Inside | Gtl | CollgCr | Norm | Norm | 1Fam | 2Story | 7 | 5 | 2003 | 2003 | Gable | CompShg | VinylSd | VinylSd | BrkFace | 196.0 | Gd | TA | PConc | Gd | TA | No | GLQ | 706 | Unf | 0 | 150 | 856 | GasA | Ex | Y | SBrkr | 856 | 854 | 0 | 1710 | 1 | 0 | 2 | 1 | 3 | 1 | Gd | 8 | Typ | 0 | NaN | Attchd | 2003.0 | RFn | 2 | 548 | TA | TA | Y | 0 | 61 | 0 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 2 | 2008 | WD | Normal | 208500 |
1 | 2 | 20 | RL | 80.0 | 9600 | Pave | NaN | Reg | Lvl | AllPub | FR2 | Gtl | Veenker | Feedr | Norm | 1Fam | 1Story | 6 | 8 | 1976 | 1976 | Gable | CompShg | MetalSd | MetalSd | None | 0.0 | TA | TA | CBlock | Gd | TA | Gd | ALQ | 978 | Unf | 0 | 284 | 1262 | GasA | Ex | Y | SBrkr | 1262 | 0 | 0 | 1262 | 0 | 1 | 2 | 0 | 3 | 1 | TA | 6 | Typ | 1 | TA | Attchd | 1976.0 | RFn | 2 | 460 | TA | TA | Y | 298 | 0 | 0 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 5 | 2007 | WD | Normal | 181500 |
2 | 3 | 60 | RL | 68.0 | 11250 | Pave | NaN | IR1 | Lvl | AllPub | Inside | Gtl | CollgCr | Norm | Norm | 1Fam | 2Story | 7 | 5 | 2001 | 2002 | Gable | CompShg | VinylSd | VinylSd | BrkFace | 162.0 | Gd | TA | PConc | Gd | TA | Mn | GLQ | 486 | Unf | 0 | 434 | 920 | GasA | Ex | Y | SBrkr | 920 | 866 | 0 | 1786 | 1 | 0 | 2 | 1 | 3 | 1 | Gd | 6 | Typ | 1 | TA | Attchd | 2001.0 | RFn | 2 | 608 | TA | TA | Y | 0 | 42 | 0 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 9 | 2008 | WD | Normal | 223500 |
3 | 4 | 70 | RL | 60.0 | 9550 | Pave | NaN | IR1 | Lvl | AllPub | Corner | Gtl | Crawfor | Norm | Norm | 1Fam | 2Story | 7 | 5 | 1915 | 1970 | Gable | CompShg | Wd Sdng | Wd Shng | None | 0.0 | TA | TA | BrkTil | TA | Gd | No | ALQ | 216 | Unf | 0 | 540 | 756 | GasA | Gd | Y | SBrkr | 961 | 756 | 0 | 1717 | 1 | 0 | 1 | 0 | 3 | 1 | Gd | 7 | Typ | 1 | Gd | Detchd | 1998.0 | Unf | 3 | 642 | TA | TA | Y | 0 | 35 | 272 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 2 | 2006 | WD | Abnorml | 140000 |
4 | 5 | 60 | RL | 84.0 | 14260 | Pave | NaN | IR1 | Lvl | AllPub | FR2 | Gtl | NoRidge | Norm | Norm | 1Fam | 2Story | 8 | 5 | 2000 | 2000 | Gable | CompShg | VinylSd | VinylSd | BrkFace | 350.0 | Gd | TA | PConc | Gd | TA | Av | GLQ | 655 | Unf | 0 | 490 | 1145 | GasA | Ex | Y | SBrkr | 1145 | 1053 | 0 | 2198 | 1 | 0 | 2 | 1 | 4 | 1 | Gd | 9 | Typ | 1 | TA | Attchd | 2000.0 | RFn | 3 | 836 | TA | TA | Y | 192 | 84 | 0 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 12 | 2008 | WD | Normal | 250000 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1455 | 1456 | 60 | RL | 62.0 | 7917 | Pave | NaN | Reg | Lvl | AllPub | Inside | Gtl | Gilbert | Norm | Norm | 1Fam | 2Story | 6 | 5 | 1999 | 2000 | Gable | CompShg | VinylSd | VinylSd | None | 0.0 | TA | TA | PConc | Gd | TA | No | Unf | 0 | Unf | 0 | 953 | 953 | GasA | Ex | Y | SBrkr | 953 | 694 | 0 | 1647 | 0 | 0 | 2 | 1 | 3 | 1 | TA | 7 | Typ | 1 | TA | Attchd | 1999.0 | RFn | 2 | 460 | TA | TA | Y | 0 | 40 | 0 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 8 | 2007 | WD | Normal | 175000 |
1456 | 1457 | 20 | RL | 85.0 | 13175 | Pave | NaN | Reg | Lvl | AllPub | Inside | Gtl | NWAmes | Norm | Norm | 1Fam | 1Story | 6 | 6 | 1978 | 1988 | Gable | CompShg | Plywood | Plywood | Stone | 119.0 | TA | TA | CBlock | Gd | TA | No | ALQ | 790 | Rec | 163 | 589 | 1542 | GasA | TA | Y | SBrkr | 2073 | 0 | 0 | 2073 | 1 | 0 | 2 | 0 | 3 | 1 | TA | 7 | Min1 | 2 | TA | Attchd | 1978.0 | Unf | 2 | 500 | TA | TA | Y | 349 | 0 | 0 | 0 | 0 | 0 | NaN | MnPrv | NaN | 0 | 2 | 2010 | WD | Normal | 210000 |
1457 | 1458 | 70 | RL | 66.0 | 9042 | Pave | NaN | Reg | Lvl | AllPub | Inside | Gtl | Crawfor | Norm | Norm | 1Fam | 2Story | 7 | 9 | 1941 | 2006 | Gable | CompShg | CemntBd | CmentBd | None | 0.0 | Ex | Gd | Stone | TA | Gd | No | GLQ | 275 | Unf | 0 | 877 | 1152 | GasA | Ex | Y | SBrkr | 1188 | 1152 | 0 | 2340 | 0 | 0 | 2 | 0 | 4 | 1 | Gd | 9 | Typ | 2 | Gd | Attchd | 1941.0 | RFn | 1 | 252 | TA | TA | Y | 0 | 60 | 0 | 0 | 0 | 0 | NaN | GdPrv | Shed | 2500 | 5 | 2010 | WD | Normal | 266500 |
1458 | 1459 | 20 | RL | 68.0 | 9717 | Pave | NaN | Reg | Lvl | AllPub | Inside | Gtl | NAmes | Norm | Norm | 1Fam | 1Story | 5 | 6 | 1950 | 1996 | Hip | CompShg | MetalSd | MetalSd | None | 0.0 | TA | TA | CBlock | TA | TA | Mn | GLQ | 49 | Rec | 1029 | 0 | 1078 | GasA | Gd | Y | FuseA | 1078 | 0 | 0 | 1078 | 1 | 0 | 1 | 0 | 2 | 1 | Gd | 5 | Typ | 0 | NaN | Attchd | 1950.0 | Unf | 1 | 240 | TA | TA | Y | 366 | 0 | 112 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 4 | 2010 | WD | Normal | 142125 |
1459 | 1460 | 20 | RL | 75.0 | 9937 | Pave | NaN | Reg | Lvl | AllPub | Inside | Gtl | Edwards | Norm | Norm | 1Fam | 1Story | 5 | 6 | 1965 | 1965 | Gable | CompShg | HdBoard | HdBoard | None | 0.0 | Gd | TA | CBlock | TA | TA | No | BLQ | 830 | LwQ | 290 | 136 | 1256 | GasA | Gd | Y | SBrkr | 1256 | 0 | 0 | 1256 | 1 | 0 | 1 | 1 | 3 | 1 | TA | 6 | Typ | 0 | NaN | Attchd | 1965.0 | Fin | 1 | 276 | TA | TA | Y | 736 | 68 | 0 | 0 | 0 | 0 | NaN | NaN | NaN | 0 | 6 | 2008 | WD | Normal | 147500 |
1460 rows × 81 columns
Nosso conjunto de dados apresenta 1460 linhas e 81 colunas, que é um número bastante alto de features.
Nesta etapa, vamos procurar entender cada tipo de dado contido no dataset, e estudar de que maneira está distribuída, bem como as relações entre as features e a variável target ('SalePrice').
Primeiramente precisamos entender que tipo de dados temos em cada coluna. Como vimos, o dataset contém 81 colunas. Vejamos quais os tipos de cada uma:
pd.DataFrame(train.dtypes, columns = ['Type']).T
Id | MSSubClass | MSZoning | LotFrontage | LotArea | Street | Alley | LotShape | LandContour | Utilities | LotConfig | LandSlope | Neighborhood | Condition1 | Condition2 | BldgType | HouseStyle | OverallQual | OverallCond | YearBuilt | YearRemodAdd | RoofStyle | RoofMatl | Exterior1st | Exterior2nd | MasVnrType | MasVnrArea | ExterQual | ExterCond | Foundation | BsmtQual | BsmtCond | BsmtExposure | BsmtFinType1 | BsmtFinSF1 | BsmtFinType2 | BsmtFinSF2 | BsmtUnfSF | TotalBsmtSF | Heating | HeatingQC | CentralAir | Electrical | 1stFlrSF | 2ndFlrSF | LowQualFinSF | GrLivArea | BsmtFullBath | BsmtHalfBath | FullBath | HalfBath | BedroomAbvGr | KitchenAbvGr | KitchenQual | TotRmsAbvGrd | Functional | Fireplaces | FireplaceQu | GarageType | GarageYrBlt | GarageFinish | GarageCars | GarageArea | GarageQual | GarageCond | PavedDrive | WoodDeckSF | OpenPorchSF | EnclosedPorch | 3SsnPorch | ScreenPorch | PoolArea | PoolQC | Fence | MiscFeature | MiscVal | MoSold | YrSold | SaleType | SaleCondition | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Type | int64 | int64 | object | float64 | int64 | object | object | object | object | object | object | object | object | object | object | object | object | int64 | int64 | int64 | int64 | object | object | object | object | object | float64 | object | object | object | object | object | object | object | int64 | object | int64 | int64 | int64 | object | object | object | object | int64 | int64 | int64 | int64 | int64 | int64 | int64 | int64 | int64 | int64 | object | int64 | object | int64 | object | object | float64 | object | int64 | int64 | object | object | object | int64 | int64 | int64 | int64 | int64 | int64 | object | object | object | int64 | int64 | int64 | object | object | int64 |
As colunas são dos tipos 'object', 'int64' ou 'float64'.
Para facilitar as análises, vamos separar as colunas, primeiramente, em dois tipos:
Mais a frente, analisaremos se as variáveis do tipo 'int64' podem ser, na verdade, categóricas.
var_cat =[]
var_num =[]
for col in train.drop(columns=['Id','SalePrice']).columns:
if train[col].dtypes == object:
var_cat.append(col)
else:
var_num.append(col)
print(f"Há {len(var_cat)} variáveis categóricas ('object'): \n {var_cat}\n")
print(f"Há {len(var_num)} varáveis numéricas ('int64 e float 64'): \n {var_num}")
Há 43 variáveis categóricas ('object'): ['MSZoning', 'Street', 'Alley', 'LotShape', 'LandContour', 'Utilities', 'LotConfig', 'LandSlope', 'Neighborhood', 'Condition1', 'Condition2', 'BldgType', 'HouseStyle', 'RoofStyle', 'RoofMatl', 'Exterior1st', 'Exterior2nd', 'MasVnrType', 'ExterQual', 'ExterCond', 'Foundation', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'Heating', 'HeatingQC', 'CentralAir', 'Electrical', 'KitchenQual', 'Functional', 'FireplaceQu', 'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond', 'PavedDrive', 'PoolQC', 'Fence', 'MiscFeature', 'SaleType', 'SaleCondition'] Há 36 varáveis numéricas ('int64 e float 64'): ['MSSubClass', 'LotFrontage', 'LotArea', 'OverallQual', 'OverallCond', 'YearBuilt', 'YearRemodAdd', 'MasVnrArea', 'BsmtFinSF1', 'BsmtFinSF2', 'BsmtUnfSF', 'TotalBsmtSF', '1stFlrSF', '2ndFlrSF', 'LowQualFinSF', 'GrLivArea', 'BsmtFullBath', 'BsmtHalfBath', 'FullBath', 'HalfBath', 'BedroomAbvGr', 'KitchenAbvGr', 'TotRmsAbvGrd', 'Fireplaces', 'GarageYrBlt', 'GarageCars', 'GarageArea', 'WoodDeckSF', 'OpenPorchSF', 'EnclosedPorch', '3SsnPorch', 'ScreenPorch', 'PoolArea', 'MiscVal', 'MoSold', 'YrSold']
Vamos agora verificar que tipo de informações podemos obter sobre cada tipo de dado contidas nas colunas.
Primeiramente para as variáveis categóricas:
train[var_cat].describe()
MSZoning | Street | Alley | LotShape | LandContour | Utilities | LotConfig | LandSlope | Neighborhood | Condition1 | Condition2 | BldgType | HouseStyle | RoofStyle | RoofMatl | Exterior1st | Exterior2nd | MasVnrType | ExterQual | ExterCond | Foundation | BsmtQual | BsmtCond | BsmtExposure | BsmtFinType1 | BsmtFinType2 | Heating | HeatingQC | CentralAir | Electrical | KitchenQual | Functional | FireplaceQu | GarageType | GarageFinish | GarageQual | GarageCond | PavedDrive | PoolQC | Fence | MiscFeature | SaleType | SaleCondition | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 1460 | 1460 | 91 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1460 | 1452 | 1460 | 1460 | 1460 | 1423 | 1423 | 1422 | 1423 | 1422 | 1460 | 1460 | 1460 | 1459 | 1460 | 1460 | 770 | 1379 | 1379 | 1379 | 1379 | 1460 | 7 | 281 | 54 | 1460 | 1460 |
unique | 5 | 2 | 2 | 4 | 4 | 2 | 5 | 3 | 25 | 9 | 8 | 5 | 8 | 6 | 8 | 15 | 16 | 4 | 4 | 5 | 6 | 4 | 4 | 4 | 6 | 6 | 6 | 5 | 2 | 5 | 4 | 7 | 5 | 6 | 3 | 5 | 5 | 3 | 3 | 4 | 4 | 9 | 6 |
top | RL | Pave | Grvl | Reg | Lvl | AllPub | Inside | Gtl | NAmes | Norm | Norm | 1Fam | 1Story | Gable | CompShg | VinylSd | VinylSd | None | TA | TA | PConc | TA | TA | No | Unf | Unf | GasA | Ex | Y | SBrkr | TA | Typ | Gd | Attchd | Unf | TA | TA | Y | Gd | MnPrv | Shed | WD | Normal |
freq | 1151 | 1454 | 50 | 925 | 1311 | 1459 | 1052 | 1382 | 225 | 1260 | 1445 | 1220 | 726 | 1141 | 1434 | 515 | 504 | 864 | 906 | 1282 | 647 | 649 | 1311 | 953 | 430 | 1256 | 1428 | 741 | 1365 | 1334 | 735 | 1360 | 380 | 870 | 605 | 1311 | 1326 | 1340 | 3 | 157 | 49 | 1267 | 1198 |
Podemos verificar que há algumas variáveis variáveis que apresentam apenas dois tipos de valores. São elas:
Street: Tipo de acesso rodoviário
Alley: Tipo de acesso ao beco
Utilities: Tipo de utilitários disponíveis
CentralAir: Ar condicionado central
No entanto, quando consultamos a descrição do problema, verificamos que as colunas 'Alley' e 'Utilities' apresentam 3 e 4 valores possíveis, respectivamente. Vamos armazená-las em uma nova lista::
var_bin = ['Street','Alley','Utilities','CentralAir']
Outras colunas apresentam valores únicos variando de 3 a 25:
\
MSZoning: Identifica a classificação geral do zoneamento da venda
LotShape: Forma geral da propriedade
LandContour: Planicidade da propriedade
LotConfig: Configuração do lote
LandSlope: Declive da propriedade
Neighborhood: Locais físicos dentro dos limites da cidade
Condition1: Proximidade de várias condições
Condition2: Proximidade de várias condições (se mais de uma estiver presente)
BldgType: Tipo de habitação
HouseStyle: Estilo de habitação
RoofStyle: Tipo de telhado
RoofMatl: Material do telhado
Exterior1st: Revestimento exterior da casa
Exterior2nd: Revestimento externo da casa (se houver mais de um material)
MasVnrType: Tipo folheado de alvenaria
ExterQual: Avalia a qualidade do material no exterior
ExterCond: Avalia a condição atual do material no exterior
Foundation: Tipo de fundação
BsmtQual: Avalia a altura do porão
BsmtCond: Avalia o estado geral da cave
BsmtExposure: Refere-se a paralisações ou paredes no nível do jardim
BsmtFinType1: Classificação da área finalizada do porão
BsmtFinType2: Classificação da área finalizada do porão (se vários tipos)
Heating: Tipo de aquecimento
HeatingQC: Qualidade e condição do aquecimento
Electrical: Sistema elétrico
KitchenQual: Qualidade da cozinha
Functional: Funcionalidade doméstica
FireplaceQu: Qualidade de lareira
GarageType: Localização da garagem
GarageFinish: Acabamento interior da garagem
GarageQual: Qualidade de garagem
GarageCond: Condição de garagem
PavedDrive: Estrada pavimentada
PoolQC: Qualidade da piscina
Fence: Qualidade da cerca
MiscFeature: Diversos recursos não cobertos em outras categorias
SaleType: Tipo de venda
SaleCondition: Condição de venda
Algumas das variáveis categóricas acima, claramente apresentam uma relação ordinal ou de ranking entre seus valores. São elas:
Coluna | Valores |
---|---|
ExterQual | Ex/Gd/TA/Fa/Po/ |
ExterCond | Ex/Gd/TA/Fa/Po/ |
BsmtQual | Ex/Gd/TA/Fa/Po/ |
BsmtCond | Ex/Gd/TA/Fa/Po/NA |
BsmtExposure | Gd/TA/Mn/No/NA |
BsmtFinType1 | GLQ/ALQ/BLQ/Rec/LwQ/Unf/NA |
BsmtFinType2 | GLQ/ALQ/BLQ/Rec/LwQ/Unf/NA |
BsmtCond | Ex/Gd/Av/Fa/Po/NA |
HeatingQC | Ex/Gd/Av/Fa/Po/ |
KitchenQual | Ex/Gd/Av/Fa/Po/ |
FireplaceQu | Ex/Gd/Av/Fa/Po/NA |
GarageQual | Ex/Gd/Av/Fa/Po/NA |
GarageCond | Ex/Gd/Av/Fa/Po/NA |
PoolQC | Ex/Gd/TA/Fa/No |
Legendas:
Ex Excellent (Excelente)
Gd Good (Bom)
TA Typical (Típico)
Fa Fair (Justo)
Po Poor (Pobre)
Av Average (Médio)
NA/No Nonexistent (Não existe)
Mn Minimum (Mínimo)
GLQ Good Living Quarters (Bons Alojamentos)
ALQ Average Living Quarters (Alojamentos razoáveis)
BLQ Below Average Living Quarters (Alojamentos abaixo da média)
Rec Average Rec Room (Quarto médio)
LwQ Low Quality (Baixa Qualidade)
Unf Unfinshed (Inacabado)
Vamos guardar tais variáveis em uma lista:
var_rank = ['ExterQual','ExterCond','BsmtQual','BsmtCond','BsmtExposure','BsmtFinType1','BsmtFinType2','HeatingQC','KitchenQual','FireplaceQu','GarageQual','GarageCond','PoolQC']
Analisaremos agora as variáveis numéricas:
Descrição das variáveis numéricas:
MSSubClass: Identifica o tipo de habitação envolvido na venda
LotFrontage: pés lineares de rua conectados à propriedade
LotArea: Tamanho do lote em pés quadrados
OverallQual: Classifica o material geral e o acabamento da casa
OverallCond: Classifica a condição geral da casa
YearBuilt: data de construção original
YearRemodAdd: Data de remodelação (igual à data de construção se não houver remodelação ou acréscimos)
MasVnrArea: Área de folheado de alvenaria em pés quadrados
BsmtFinSF1: Tipo 1 pés quadrados acabados
BsmtFinSF2: Tipo 2 pés quadrados acabados
BsmtUnfSF: pés quadrados inacabados da área do porão
TotalBsmtSF: pés quadrados totais da área do porão
1stFlrSF: pés quadrados do primeiro andar
2ndFlrSF: pés quadrados do segundo andar
LowQualFinSF: pés quadrados acabados de baixa qualidade (todos os andares)
GrLivArea: Área habitável acima do solo (pés quadrados)
BsmtFullBath: Banheiros completos no porão
BsmtHalfBath: lavabos no porão
FullBath: Banheiros completos acima do nível do solo
HalfBath: Meios banhos acima do grau
BedroomAbvGr: Número de quartos acima do subsolo
KitchenAbvGr: Cozinhas acima do nível
TotRmsAbvGrd: Total de quartos acima do nível (não inclui banheiros)
Lareiras: Número de lareiras
GarageYrBlt: ano em que a garagem foi construída
GarageCars: Tamanho da garagem na capacidade do carro
GarageArea: Tamanho da garagem em pés quadrados
WoodDeckSF: Área de deck de madeira em pés quadrados
OpenPorchSF: Área de varanda aberta em pés quadrados
EnclosedPorch: Área da varanda fechada em pés quadrados
3SsnPorch: Área de varanda de três estações em pés quadrados
ScreenPorch: Área da varanda de tela em pés quadrados
PoolArea: Área da piscina em metros quadrados
MiscVal: $Valor do recurso diverso
MoSold: Mês Vendido (MM)
YrSold: Ano de venda (AAAA)
train[var_num].describe()
MSSubClass | LotFrontage | LotArea | OverallQual | OverallCond | YearBuilt | YearRemodAdd | MasVnrArea | BsmtFinSF1 | BsmtFinSF2 | BsmtUnfSF | TotalBsmtSF | 1stFlrSF | 2ndFlrSF | LowQualFinSF | GrLivArea | BsmtFullBath | BsmtHalfBath | FullBath | HalfBath | BedroomAbvGr | KitchenAbvGr | TotRmsAbvGrd | Fireplaces | GarageYrBlt | GarageCars | GarageArea | WoodDeckSF | OpenPorchSF | EnclosedPorch | 3SsnPorch | ScreenPorch | PoolArea | MiscVal | MoSold | YrSold | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 1460.000000 | 1201.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1452.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1379.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 |
mean | 56.897260 | 70.049958 | 10516.828082 | 6.099315 | 5.575342 | 1971.267808 | 1984.865753 | 103.685262 | 443.639726 | 46.549315 | 567.240411 | 1057.429452 | 1162.626712 | 346.992466 | 5.844521 | 1515.463699 | 0.425342 | 0.057534 | 1.565068 | 0.382877 | 2.866438 | 1.046575 | 6.517808 | 0.613014 | 1978.506164 | 1.767123 | 472.980137 | 94.244521 | 46.660274 | 21.954110 | 3.409589 | 15.060959 | 2.758904 | 43.489041 | 6.321918 | 2007.815753 |
std | 42.300571 | 24.284752 | 9981.264932 | 1.382997 | 1.112799 | 30.202904 | 20.645407 | 181.066207 | 456.098091 | 161.319273 | 441.866955 | 438.705324 | 386.587738 | 436.528436 | 48.623081 | 525.480383 | 0.518911 | 0.238753 | 0.550916 | 0.502885 | 0.815778 | 0.220338 | 1.625393 | 0.644666 | 24.689725 | 0.747315 | 213.804841 | 125.338794 | 66.256028 | 61.119149 | 29.317331 | 55.757415 | 40.177307 | 496.123024 | 2.703626 | 1.328095 |
min | 20.000000 | 21.000000 | 1300.000000 | 1.000000 | 1.000000 | 1872.000000 | 1950.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 334.000000 | 0.000000 | 0.000000 | 334.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 2.000000 | 0.000000 | 1900.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 2006.000000 |
25% | 20.000000 | 59.000000 | 7553.500000 | 5.000000 | 5.000000 | 1954.000000 | 1967.000000 | 0.000000 | 0.000000 | 0.000000 | 223.000000 | 795.750000 | 882.000000 | 0.000000 | 0.000000 | 1129.500000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 2.000000 | 1.000000 | 5.000000 | 0.000000 | 1961.000000 | 1.000000 | 334.500000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 5.000000 | 2007.000000 |
50% | 50.000000 | 69.000000 | 9478.500000 | 6.000000 | 5.000000 | 1973.000000 | 1994.000000 | 0.000000 | 383.500000 | 0.000000 | 477.500000 | 991.500000 | 1087.000000 | 0.000000 | 0.000000 | 1464.000000 | 0.000000 | 0.000000 | 2.000000 | 0.000000 | 3.000000 | 1.000000 | 6.000000 | 1.000000 | 1980.000000 | 2.000000 | 480.000000 | 0.000000 | 25.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 6.000000 | 2008.000000 |
75% | 70.000000 | 80.000000 | 11601.500000 | 7.000000 | 6.000000 | 2000.000000 | 2004.000000 | 166.000000 | 712.250000 | 0.000000 | 808.000000 | 1298.250000 | 1391.250000 | 728.000000 | 0.000000 | 1776.750000 | 1.000000 | 0.000000 | 2.000000 | 1.000000 | 3.000000 | 1.000000 | 7.000000 | 1.000000 | 2002.000000 | 2.000000 | 576.000000 | 168.000000 | 68.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 8.000000 | 2009.000000 |
max | 190.000000 | 313.000000 | 215245.000000 | 10.000000 | 9.000000 | 2010.000000 | 2010.000000 | 1600.000000 | 5644.000000 | 1474.000000 | 2336.000000 | 6110.000000 | 4692.000000 | 2065.000000 | 572.000000 | 5642.000000 | 3.000000 | 2.000000 | 3.000000 | 2.000000 | 8.000000 | 3.000000 | 14.000000 | 3.000000 | 2010.000000 | 4.000000 | 1418.000000 | 857.000000 | 547.000000 | 552.000000 | 508.000000 | 480.000000 | 738.000000 | 15500.000000 | 12.000000 | 2010.000000 |
Podemos observar que algumas colunas, como 'PoolArea', 'MiscVal', '3SsnPorch', 'LowQualFinSF' possuem um desvio padrão muito maior que o valor médio da coluna. Isso também implica em uma alta variância, que pode ser resultado, dentre outros fatores, da quantidade de valores ausentes na coluna.
De acordo com as descrições das variáveis numéricas, vemos que as colunas 'OverallQual' e 'OverallCond' também possuem caráter de ranking, pois atribuem uma nota à qualidade geral do material e à condição geral da casa, respectivamente, possuindo os seguintes valores:
10 Very Excellent (Muito excelente)
9 Excellent (Excelente)
8 Very Good (Muito bom)
7 Good (Bom)
6 Above Average (Acima da média)
5 Average (Médio)
4 Below Average (Abaixo da média)
3 Fair (Justo)
2 Poor (Pobre)
1 Very Poor (Muito pobre)
Assim, vamos colocar essas duas variáveis também na lista 'var_rank':
var_rank.append('OverallQual')
var_rank.append('OverallCond')
Uma vez que, algumas variáveis categóricas e numéricas foram redefinidas como binárias ou de ranking, vamos redefinir também as listas de variáveis categóricas e numéricas:
for var in (var_rank+var_bin):
if var in var_cat:
var_cat.remove(var)
for var in var_rank:
if var in var_num:
var_num.remove(var)
Verificaremos agora a quantidade de valores nulos presentes em cada coluna:
miss_value=pd.DataFrame(columns=['Coluna', '%Ausente'])
for index,col in enumerate(train.columns):
value = (train[col].isna().sum()/train.shape[0])*100
if value>0:
nova_linha=pd.DataFrame([[col,value]], columns=['Coluna', '%Ausente'], index=[index])
miss_value = pd.concat([miss_value,nova_linha])
miss_value.sort_values(by='%Ausente', ascending=False).T
72 | 74 | 6 | 73 | 57 | 3 | 58 | 59 | 60 | 63 | 64 | 32 | 35 | 33 | 31 | 30 | 26 | 25 | 42 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Coluna | PoolQC | MiscFeature | Alley | Fence | FireplaceQu | LotFrontage | GarageType | GarageYrBlt | GarageFinish | GarageQual | GarageCond | BsmtExposure | BsmtFinType2 | BsmtFinType1 | BsmtCond | BsmtQual | MasVnrArea | MasVnrType | Electrical |
%Ausente | 99.520548 | 96.30137 | 93.767123 | 80.753425 | 47.260274 | 17.739726 | 5.547945 | 5.547945 | 5.547945 | 5.547945 | 5.547945 | 2.60274 | 2.60274 | 2.534247 | 2.534247 | 2.534247 | 0.547945 | 0.547945 | 0.068493 |
Vericamos que as colunas PoolQC, MiscFeature, Alley, Fence e FireplaceQu possuem alta porcentagem de valores ausentes, que nos impede de tirar conclusões mais precisas.
Vamos agora visualizar a distribuição de algumas colunas, de forma a obter alguns insights.
fig, ax = plt.subplots(1,2,figsize=(15,5))
sns.histplot(train['SalePrice'],kde=True, ax=ax[0])
sns.boxplot(x=train['SalePrice'],ax=ax[1])
plt.show()
Podemos observar que a variável target (SalePrice) não segue uma distribuição normal, tendo maior assimetria para a direita. Segundo o que podemos ver no boxplot, o valor médio das casas do dataset se encontram por volta de 17 mil, mas há muitos outliers cujos valores podem chegar a mais de 70 mil.
Vamos analisar de que forma as variáveis binárias se relacionam com os preços das casas:
plt.figure(figsize=(25,5))
for i,col in enumerate(train[var_bin],1):
plt.subplot(1,4,i)
sns.boxplot(data=train, x= col, y='SalePrice').set_title(f"Gráfico {i}")
A partir do Gráfico 1, é possível observar que as casas situadas em ruas não pavimentadas (Grvl) possuem valor médio e valor máximo inferior às casas em ruas pavimentadas.
No Gráfico 2, embora a variável 'Alley' não seja binária, pois apresenta 3 possibilidades (Grvl, Pave e NO), no dataset há apenas as os dois primeiros tipos de valores, onde podemos novamente constatar que o tipo de acesso à rua 'pavimentada' (Pave) tem valor médio e valor máximo maiores do que quando a rua não é pavimentada.
No Gráfico 3, novamente vemos que a variável 'Utilities' pode apresentar 4 tipos de valores, mas apresenta apensa 2.
Finalmente no Gráfico 4, relativo à presença ou não de central de ar condicionado, fica evidente que as casas que apresental ar condicionado possuem valor maior do que as casas que não apresentam.
Como já abordado anteriormente, as variáveis ordinais são aquelas que podem apresentar comportamento no qual há uma relação entre os valores. No caso estudado aqui, as variáveis 'ExterQual', 'ExterCond', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'HeatingQC', 'KitchenQual', 'FireplaceQu', 'GarageQual', 'GarageCond', 'PoolQC', 'OverallQual', 'OverallCond' apresentam um comportamento de ranking, onde os valores são como notas atribuídas ao quesito descrito na coluna.
Dessa forma, vamos analisar o comportamento da variável target em relação a cada uma delas. Para isso, primeiramente vamos substituir os valores categóricos contidos em cada coluna, por valores numéricos, onde 0 é a menor nota na escala.
df = train.copy()
df[['ExterQual','ExterCond','HeatingQC','KitchenQual','PoolQC']] = df[['ExterQual','ExterCond','HeatingQC','KitchenQual','PoolQC']].replace(to_replace=['Ex','Gd','TA','Fa','Po'], value=[4,3,2,1,0])
df[['BsmtQual','BsmtCond','FireplaceQu','GarageQual','GarageCond']] = df[['BsmtQual','BsmtCond','FireplaceQu','GarageQual','GarageCond']].replace(to_replace=['Ex','Gd','TA','Fa','Po','NA'], value=[5,4,3,2,1,0])
df[['BsmtExposure']] = df[['BsmtExposure']].replace(to_replace=['Gd','Av','Mn','No','NA'], value=[4,3,2,1,0])
df[['BsmtFinType1','BsmtFinType2']] = df[['BsmtFinType1','BsmtFinType2']].replace(to_replace=['GLQ','ALQ','BLQ','Rec','LwQ','Unf','NA'], value=[6,5,4,3,2,1,0])
df[var_rank]
ExterQual | ExterCond | BsmtQual | BsmtCond | BsmtExposure | BsmtFinType1 | BsmtFinType2 | HeatingQC | KitchenQual | FireplaceQu | GarageQual | GarageCond | PoolQC | OverallQual | OverallCond | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 3 | 2 | 4.0 | 3.0 | 1.0 | 6.0 | 1.0 | 4 | 3 | NaN | 3.0 | 3.0 | NaN | 7 | 5 |
1 | 2 | 2 | 4.0 | 3.0 | 4.0 | 5.0 | 1.0 | 4 | 2 | 3.0 | 3.0 | 3.0 | NaN | 6 | 8 |
2 | 3 | 2 | 4.0 | 3.0 | 2.0 | 6.0 | 1.0 | 4 | 3 | 3.0 | 3.0 | 3.0 | NaN | 7 | 5 |
3 | 2 | 2 | 3.0 | 4.0 | 1.0 | 5.0 | 1.0 | 3 | 3 | 4.0 | 3.0 | 3.0 | NaN | 7 | 5 |
4 | 3 | 2 | 4.0 | 3.0 | 3.0 | 6.0 | 1.0 | 4 | 3 | 3.0 | 3.0 | 3.0 | NaN | 8 | 5 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1455 | 2 | 2 | 4.0 | 3.0 | 1.0 | 1.0 | 1.0 | 4 | 2 | 3.0 | 3.0 | 3.0 | NaN | 6 | 5 |
1456 | 2 | 2 | 4.0 | 3.0 | 1.0 | 5.0 | 3.0 | 2 | 2 | 3.0 | 3.0 | 3.0 | NaN | 6 | 6 |
1457 | 4 | 3 | 3.0 | 4.0 | 1.0 | 6.0 | 1.0 | 4 | 3 | 4.0 | 3.0 | 3.0 | NaN | 7 | 9 |
1458 | 2 | 2 | 3.0 | 3.0 | 2.0 | 6.0 | 3.0 | 3 | 3 | NaN | 3.0 | 3.0 | NaN | 5 | 6 |
1459 | 3 | 2 | 3.0 | 3.0 | 1.0 | 4.0 | 2.0 | 3 | 2 | NaN | 3.0 | 3.0 | NaN | 5 | 6 |
1460 rows × 15 columns
plt.figure(figsize=(20,30))
for i,col in enumerate(df[var_rank],1):
plt.subplot(5,3,i)
sns.boxplot(data=df, x= col, y='SalePrice').set_title(f'Gráfico {i+4}')
Neste formato, torna-se muito mais simples analisar de que forma cada variável ordinal se relaciona com o valor das casas. De maneira geral, podemos ver que fica evidente a relação ascendente entre os valores de cada variável e a variável SalePrice, ou seja, quanto maior a nota em cada quisito, maior o valor médio da casa.
Agora analisaremos as variáveis categóricas:
plt.figure(figsize=(25,45))
for i,col in enumerate(train[var_cat],1):
plt.subplot(7,4,i)
sns.boxplot(data=train, x= col,y='SalePrice').set_title(f'Gráfico {i+19}')
Como alguns dos gráficos acima (25, 32 e 36) não apresentaram boa qualidade de visualização, vamos plotá-los separadamente abaixo:
plt.figure(figsize=(20,20))
plt.subplot(3,1,1)
sns.boxplot(data=train, x='Neighborhood', y='SalePrice').set_title(f'Gráfico 25')
plt.subplot(3,1,2)
sns.boxplot(data=train, x='Exterior1st', y='SalePrice').set_title(f'Gráfico 32')
plt.subplot(3,1,3)
sns.boxplot(data=train, x='Exterior2nd', y='SalePrice').set_title(f'Gráfico 36')
plt.show()
plt.figure(figsize=(30,50))
for i, col in enumerate(train[var_num].columns,1):
plt.subplot(9,4,i)
sns.histplot(train[col],kde=True).set_title(f'Gráfico {i+45}')
Um fator importante a ser observado antes dos processos de modelagem, pode ser a variância de cada feature. Como a quantidade de atributos é bastante alta, procuraremos analisá-las a fim de encontrar variáveis constantes ou quasi-constantes, isto é, variáveis que apresentam variância nula ou muito baixa, e que terão pouca influência sobre a modelagem.
É importante que seja feita a normalização dos dados para que seja realizada uma comparação justa, pois a variância depende também da escala em que os valores se encontram. Para isso, optaremos pordividir cada coluna pela sua média, para garantir que todas estejam na mesma escala:
mean = df[var_num].mean()
df[var_num] = df[var_num]/mean
variance = pd.DataFrame(df[var_num].var().sort_values(), columns=['Variance'])
fig, ax = plt.subplots(figsize=(13,10))
ax = sns.barplot(y=variance.index,x=variance['Variance'])
ax.set_title(f'Gráfico 91: Variância das colunas numéricas')
for index, value in enumerate (variance['Variance']):
plt.text(value, index, f'{value:.3}')
plt.show()
Podemos verificar que as variâncias vão da ordem de 10^-7 até 10^2, e há muitas features com baixa variância, que teriam sua remoção estudada em casos de modelagem.
train[['PoolArea','MiscVal','3SsnPorch','LowQualFinSF','BsmtHalfBath','ScreenPorch','BsmtFinSF2','EnclosedPorch','MasVnrArea','OpenPorchSF','WoodDeckSF','HalfBath','2ndFlrSF','BsmtFullBath','Fireplaces']].describe()
PoolArea | MiscVal | 3SsnPorch | LowQualFinSF | BsmtHalfBath | ScreenPorch | BsmtFinSF2 | EnclosedPorch | MasVnrArea | OpenPorchSF | WoodDeckSF | HalfBath | 2ndFlrSF | BsmtFullBath | Fireplaces | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1452.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 |
mean | 2.758904 | 43.489041 | 3.409589 | 5.844521 | 0.057534 | 15.060959 | 46.549315 | 21.954110 | 103.685262 | 46.660274 | 94.244521 | 0.382877 | 346.992466 | 0.425342 | 0.613014 |
std | 40.177307 | 496.123024 | 29.317331 | 48.623081 | 0.238753 | 55.757415 | 161.319273 | 61.119149 | 181.066207 | 66.256028 | 125.338794 | 0.502885 | 436.528436 | 0.518911 | 0.644666 |
min | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
25% | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
50% | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 25.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 |
75% | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 166.000000 | 68.000000 | 168.000000 | 1.000000 | 728.000000 | 1.000000 | 1.000000 |
max | 738.000000 | 15500.000000 | 508.000000 | 572.000000 | 2.000000 | 480.000000 | 1474.000000 | 552.000000 | 1600.000000 | 547.000000 | 857.000000 | 2.000000 | 2065.000000 | 3.000000 | 3.000000 |
Nesta etapa, procuraremos visualizar as possíveis correlações entre as variáveis numéricas e ordinais com a vaariável target, e também entre elas mesmas.
Para isso, utilizaremos os métodos relacionados à correlação linear de Pearson.
plt.figure(figsize=(10,15))
corr = pd.DataFrame(train[['SalePrice']+var_num+var_rank].corr()['SalePrice'].abs().sort_values(ascending = False)).drop(index=['SalePrice'])
corr.columns = ['Correlation']
bar = sns.barplot(y = corr.index, x=corr['Correlation']).set_title("Gráfico 80: Correlação de Pearson das variáveis numéricas e ordinais com a variável 'SalePrice' (em valores absolutos)")
for index, value in enumerate (corr['Correlation']):
plt.text(value, index, f'{value:.2}')
plt.show()
Observamos que as colunas 'OverallQual', 'GrLivArea', 'GarageCars','GarageArea', 'TotalBsmtSF', 'FullBath', 'TotRmsAbvGrd', 'YearBuilt' apresentam alta correlação linear com a variável 'SalePrice'.
Tais colunas se referem-se às condições, tamanho, quantidade de cômodos e ano de construção dos imóveis, fatores já esperados como influência sobre os preços.
plt.figure(figsize=(20,20))
ax = sns.heatmap(train[['SalePrice']+var_num+var_rank].corr().abs(), annot = True, fmt=".1f")
ax.set_title('Gráfico 81: Correlação de Pearson')
plt.show()
Podemos ainda destacar outras relações entre as variáveis:
Essa relação é esperada e quase redundante, uma vez que a área do 1º andar corresponde, na maioria das vezes, à área do porão.
Aqui a correlação é quase que óbvia, uma vez que na maioria das vezes a garagem do imóvel é construída simultaneamente ao imóvel.
Mais uma correlação esperada: quanto maior a área da garagem, maior a quantidade de vagas disponíveis.
Essa relação mostrou que, com o passar dos anos, as áreas dos terrenos também aumentaram.
Abaixo, vejamos de que forma a variável independente 'SalePrice' se distribui em função das 9 variáveis dependentes com maior correlação de Pearson.
plt.figure(figsize=(20,17))
for i, col in enumerate(corr.head(9).index,1):
plt.subplot(3,3,i)
sns.regplot(data=train, x=col, y='SalePrice').set_title(f'Gráfico {i+81}')
Nesta etapa, vamos analisar os outliers, ou seja, as linhas do dataset, no qual o valor do preço foge da normalidade, ou seja, são discrepantes. Existem vários métodos para calcular qual valor de preço define o que é ou não um outlier. Em nosso trabalho, vamos utilizar o método estatístico de calcular todos os quartis, em seguida o Intervalo Interquartil e finalmente o limite máximo, a partir do qual, um valor é considerado outlier.
Vamos iniciar pelo cálculo do segundo quartil (denominado de Q2), que é a mediana. A partir daí, calculamos o primeiro quartil (Q1) é a mediana entre o menor valor e Q2 (mediana do conjunto), Q3, que é a mediana entre o maior valor e Q2.
Q2 = np.median(train['SalePrice'])
Q1 = np.median(train[train['SalePrice']<=Q2]['SalePrice'])
Q3 = np.median(train[train['SalePrice']>=Q2]['SalePrice'])
print(f'Q1 = {Q1} \nQ2 = {Q2} \nQ3 = {Q3}')
Q1 = 130000.0 Q2 = 163000.0 Q3 = 214000.0
Calculamos agora o IQR (Interquartil Range) ou Intervalo Interquartil, que é a diferença entre Q3 e Q1:
IQR = Q3 - Q1
IQR
84000.0
Poderíamos também ter usado o pacote Scipy:
from scipy import stats
# Interquartile range (IQR)
IQR = stats.iqr(train['SalePrice'], interpolation = 'nearest')
print(IQR)
84000
São considerados outliers todos os valores maiores que Q3 + 1.5xIQR:
Outliers = Q3+ 1.5*IQR
Outliers
340000.0
Ou seja, vamos analisar as características dos imóveis cujo valor ultrapassa 340.000.
plt.figure(figsize=(5,6))
box = sns.boxplot(data=train, y ='SalePrice')
box.set_title('Gráfico 91: Boxplot da variável Saleprice, com identificação dos quartis')
box.text(0.4,Q1,f'------> Q1={Q1}')
box.text(0.4,Q2,f'------> Q2={Q2}')
box.text(0.4,Q3,f'------> Q3={Q3}')
box.text(0.4,Outliers,f'------> Outliers acima de {Outliers}')
plt.show()
train_outliers = train[train['SalePrice']>Outliers] #dataframe para outliers
train_no_outliers = train[train['SalePrice']<Outliers] #dtaframe para não outliers
print(f'Há {train_outliers.shape[0]} outliers.')
Há 61 outliers.
Faremos uma análise breve, para tentar achar algum padrão presente nessas casas.
print(f"Área mínima das casas outliers: {train_outliers['GrLivArea'].min()}")
print(f"Área máxima das casas comuns: {train_no_outliers['GrLivArea'].min()}")
Área mínima das casas outliers: 1419 Área máxima das casas comuns: 334
A área mínima das casas mais caras é de 1.419 pés², que é cerca de 5 vezes menor que a menor área das casas que não são outliers (5.642).
train_outliers['Street'].value_counts()
Pave 61 Name: Street, dtype: int64
Todas as ruas são pavimentadas.
print(f"Total de bairros: {len(train['Neighborhood'].unique())}")
print(f"Total de bairros outliers: {len(train_outliers['Neighborhood'].unique())}")
Total de bairros: 25 Total de bairros outliers: 11
Há 25 bairros no dataset, mas as casas mais caras estão situados em apenas 11.
print(f"Total de tipos de domicílio: {len(train['BldgType'].unique())} \n")
print(f"Tipos de domicílios outliers:\n")
print('Tipo Quantidade')
print(train_outliers['BldgType'].value_counts())
Total de tipos de domicílio: 5 Tipos de domicílios outliers: Tipo Quantidade 1Fam 59 TwnhsE 2 Name: BldgType, dtype: int64
Há 5 tipos de habitação, mas apenas 2 estão entre as mais caras: 'Single-family Detached' e 'TwnhsE'.
print('Nota Quantidade')
train_outliers['OverallQual'].value_counts()
Nota Quantidade
9 23 8 22 10 13 7 3 Name: OverallQual, dtype: int64
A maioria das casas apresentam no mínimo nota 7 para a qualidade do acabamento.
train_outliers['TotRmsAbvGrd'].value_counts()
10 15 7 12 9 10 8 10 11 7 12 3 5 2 6 2 Name: TotRmsAbvGrd, dtype: int64
As casas consideradas outliers tem pelo menos 5 cômodos, e a maioria tem mais de 8 cômodos.
train_outliers['Fireplaces'].value_counts()
1 43 2 15 3 2 0 1 Name: Fireplaces, dtype: int64
Apenas uma casa não possui lareira, todas as outras têm pelo menos 1.
train_outliers['FullBath'].value_counts()
2 44 3 13 1 3 0 1 Name: FullBath, dtype: int64
A grande maioria das casas possuem pelo menos 2 banheiros.
train_outliers['PoolArea'].value_counts()
0 60 555 1 Name: PoolArea, dtype: int64
Diferente do que usualmente alguém imaginaria, apenas 1 casa dos outilers possui piscina.
train_outliers['CentralAir'].value_counts()
Y 61 Name: CentralAir, dtype: int64
Todas as casas outliers possuem ar condicionado.
train_outliers['GarageCars'].value_counts()
3 55 2 6 Name: GarageCars, dtype: int64
As casas possuem vagas para pelo menos 2 carros, e 55 das 61 casas possuem vagas para 3 carros.
Neste trabalho, procurou-se realizar uma Análise Exploratória do dataset de competição do Kaggle, entitulado "House Prices - Advanced Regression Techniques".
Alguns pontos importantes: