O documento consiste em uma Análise Exploratória de Dados (EDA), tratamento e preparação de dados (Data Wrangling), avaliação e seleção dos principais parâmetros (Feature Engineering) e modelagem de um algoritmo preditivo para estimativa de preço de venda de imóveis a partir dos algoritmos regressores por regularização Lasso e Gradient Boosting (XGBOOST).
O conjunto de dados utilizado é referente à cidade de Ames, em Iowa nos Estados Unidos. O estudo foi compilado por Dean De Cock e está disponível na plataforma Kaggle, bem como o notebook do autor Erik Bruin, utilizado como referência. O conjunto conta com 2919 residências, descritas por 79 características que serão ordenadas por sua importância no preço de venda do imóvel e manipuladas para modelagem do algoritmo preditivo.
Este tipo de análise visa não somente a criação de um modelo matemático para previsão como também a descoberta de insights a respeito das variáveis que envolvem o mercado imobiliário estudado. Desta forma, entende-se que o estudo possa ser reproduzido para conjuntos de dados brasileiros e servir de direcionamento para ivestimentos de recursos e esforços de incorporadoras, construtores e imobiliárias que buscam aliar eficiência operacional, retorno financeiro e satisfação dos clientes.
Os detalhes sobre as características coletadas dos imóveis, bem como seus parâmetros de preenchimento podem ser consultadas na página do Kaggle (https://www.kaggle.com/c/house-prices-advanced-regression-techniques/data). Vale ressaltar que algumas nomenclaturas como: cômodos acabados, acima da rua, meio-banheiro, dentre outros são traduções livres de termos utilizados no mercado imobiliário estadunidense.
O conjunto de dados é fornecido já dividido entre treinamento e teste, sendo que o conjunto de teste não possui os valores de venda. Para a modelagem do algoritmo é utilizado somente o conjunto de treinamento, o conjunto de teste (sem preço de venda) é utilizado para teste do algoritmo gerado.
train <- read.csv("train.csv", stringsAsFactors = F)
test <- read.csv("test.csv", stringsAsFactors = F)Para melhor entendimento, os parâmetros foram traduzidos e criada uma tabela com o nome original do parâmetro em inglês e a tradução utlizada a fim de faciliar a consulta nas documentações originais do estudo.
train <- read.csv("train.csv", stringsAsFactors = F)
test <- read.csv("test.csv", stringsAsFactors = F)
test$SalePrice <- NA
nomes_orig <- names(read.csv("train.csv", stringsAsFactors = F))
nomes_portugues <- c("Id","Classe", "Zona", "DimFrontal", "AreaLote", "TipoEstrada", "TipoRua", "RelevoLote", "GreideLote", "Instalacoes", "ImplantacaoLote", "Declive", "Bairro", "Proximidade1", "Proximidade2", "TipoHabitacao", "Pavimentos", "QualidadeTotal", "CondicaoTotal", "AnoConstrucao", "AnoRetrofit", "TipoCobertura", "MaterialCobertura", "Fachada1", "Fachada2", "TipoAlvenaria", "AreaAlvenaria", "QualidadeFachada", "CondicaoFachada", "Fundacao", "AlturaPorao", "CondicaoPorao", "ExposicaoPorao", "RevestimentoPorao1", "AreaPoraoAcabado1", "RevestimentoPorao2", "AreaPoraoAcabado2", "AreaPoraoInacab", "AreaTotalPorao", "Aquecimento", "CondicaoAquecimento", "ArCentral", "SistemaEletrico", "AreaTerreo", "Area1Pav", "AreaAcabBaixaQualTotal", "AreaVivenciaAcimaRua", "BanheirosPorao", "LavaboPorao", "BanheirosAcimaRua", "LavaboAcimaRua", "QuartosAcimaRua", "CozinhasAcimaRua", "QualidadeCozinha", "ComodosAcimarua", "Descontos", "Lareiras", "QualidadeLareira", "TipoGaragem", "AnoGaragem", "AcabamentoGaragem", "VagasGaragem", "AreaGaragem", "QualiGaragem", "CondicaoGaragem", "PavimEntrada", "AreaDeck", "AreaVarandaAberta", "AreaVarandaFechada", "AreaVaranda3Sea", "AreaVarandaScreen", "AreaPiscina", "QualiPiscina", "QualiCerca", "OutrosItens", "ValorItens", "MesVenda", "AnoVenda", "TipoVenda", "CondicaoVenda", "PrecoVenda")
names(train) <- nomes_portugues
names(test) <- nomes_portugues
nomes <- cbind(nomes_orig,nomes_portugues)## Rows: 1,460
## Columns: 81
## $ Id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1...
## $ Classe <int> 60, 20, 60, 70, 60, 50, 20, 60, 50, 190, 20,...
## $ Zona <chr> "RL", "RL", "RL", "RL", "RL", "RL", "RL", "R...
## $ DimFrontal <int> 65, 80, 68, 60, 84, 85, 75, NA, 51, 50, 70, ...
## $ AreaLote <int> 8450, 9600, 11250, 9550, 14260, 14115, 10084...
## $ TipoEstrada <chr> "Pave", "Pave", "Pave", "Pave", "Pave", "Pav...
## $ TipoRua <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ RelevoLote <chr> "Reg", "Reg", "IR1", "IR1", "IR1", "IR1", "R...
## $ GreideLote <chr> "Lvl", "Lvl", "Lvl", "Lvl", "Lvl", "Lvl", "L...
## $ Instalacoes <chr> "AllPub", "AllPub", "AllPub", "AllPub", "All...
## $ ImplantacaoLote <chr> "Inside", "FR2", "Inside", "Corner", "FR2", ...
## $ Declive <chr> "Gtl", "Gtl", "Gtl", "Gtl", "Gtl", "Gtl", "G...
## $ Bairro <chr> "CollgCr", "Veenker", "CollgCr", "Crawfor", ...
## $ Proximidade1 <chr> "Norm", "Feedr", "Norm", "Norm", "Norm", "No...
## $ Proximidade2 <chr> "Norm", "Norm", "Norm", "Norm", "Norm", "Nor...
## $ TipoHabitacao <chr> "1Fam", "1Fam", "1Fam", "1Fam", "1Fam", "1Fa...
## $ Pavimentos <chr> "2Story", "1Story", "2Story", "2Story", "2St...
## $ QualidadeTotal <int> 7, 6, 7, 7, 8, 5, 8, 7, 7, 5, 5, 9, 5, 7, 6,...
## $ CondicaoTotal <int> 5, 8, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 6, 5, 5,...
## $ AnoConstrucao <int> 2003, 1976, 2001, 1915, 2000, 1993, 2004, 19...
## $ AnoRetrofit <int> 2003, 1976, 2002, 1970, 2000, 1995, 2005, 19...
## $ TipoCobertura <chr> "Gable", "Gable", "Gable", "Gable", "Gable",...
## $ MaterialCobertura <chr> "CompShg", "CompShg", "CompShg", "CompShg", ...
## $ Fachada1 <chr> "VinylSd", "MetalSd", "VinylSd", "Wd Sdng", ...
## $ Fachada2 <chr> "VinylSd", "MetalSd", "VinylSd", "Wd Shng", ...
## $ TipoAlvenaria <chr> "BrkFace", "None", "BrkFace", "None", "BrkFa...
## $ AreaAlvenaria <int> 196, 0, 162, 0, 350, 0, 186, 240, 0, 0, 0, 2...
## $ QualidadeFachada <chr> "Gd", "TA", "Gd", "TA", "Gd", "TA", "Gd", "T...
## $ CondicaoFachada <chr> "TA", "TA", "TA", "TA", "TA", "TA", "TA", "T...
## $ Fundacao <chr> "PConc", "CBlock", "PConc", "BrkTil", "PConc...
## $ AlturaPorao <chr> "Gd", "Gd", "Gd", "TA", "Gd", "Gd", "Ex", "G...
## $ CondicaoPorao <chr> "TA", "TA", "TA", "Gd", "TA", "TA", "TA", "T...
## $ ExposicaoPorao <chr> "No", "Gd", "Mn", "No", "Av", "No", "Av", "M...
## $ RevestimentoPorao1 <chr> "GLQ", "ALQ", "GLQ", "ALQ", "GLQ", "GLQ", "G...
## $ AreaPoraoAcabado1 <int> 706, 978, 486, 216, 655, 732, 1369, 859, 0, ...
## $ RevestimentoPorao2 <chr> "Unf", "Unf", "Unf", "Unf", "Unf", "Unf", "U...
## $ AreaPoraoAcabado2 <int> 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0...
## $ AreaPoraoInacab <int> 150, 284, 434, 540, 490, 64, 317, 216, 952, ...
## $ AreaTotalPorao <int> 856, 1262, 920, 756, 1145, 796, 1686, 1107, ...
## $ Aquecimento <chr> "GasA", "GasA", "GasA", "GasA", "GasA", "Gas...
## $ CondicaoAquecimento <chr> "Ex", "Ex", "Ex", "Gd", "Ex", "Ex", "Ex", "E...
## $ ArCentral <chr> "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y",...
## $ SistemaEletrico <chr> "SBrkr", "SBrkr", "SBrkr", "SBrkr", "SBrkr",...
## $ AreaTerreo <int> 856, 1262, 920, 961, 1145, 796, 1694, 1107, ...
## $ Area1Pav <int> 854, 0, 866, 756, 1053, 566, 0, 983, 752, 0,...
## $ AreaAcabBaixaQualTotal <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ AreaVivenciaAcimaRua <int> 1710, 1262, 1786, 1717, 2198, 1362, 1694, 20...
## $ BanheirosPorao <int> 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,...
## $ LavaboPorao <int> 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ BanheirosAcimaRua <int> 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 1, 3, 1, 2, 1,...
## $ LavaboAcimaRua <int> 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1,...
## $ QuartosAcimaRua <int> 3, 3, 3, 3, 4, 1, 3, 3, 2, 2, 3, 4, 2, 3, 2,...
## $ CozinhasAcimaRua <int> 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1,...
## $ QualidadeCozinha <chr> "Gd", "TA", "Gd", "Gd", "Gd", "TA", "Gd", "T...
## $ ComodosAcimarua <int> 8, 6, 6, 7, 9, 5, 7, 7, 8, 5, 5, 11, 4, 7, 5...
## $ Descontos <chr> "Typ", "Typ", "Typ", "Typ", "Typ", "Typ", "T...
## $ Lareiras <int> 0, 1, 1, 1, 1, 0, 1, 2, 2, 2, 0, 2, 0, 1, 1,...
## $ QualidadeLareira <chr> NA, "TA", "TA", "Gd", "TA", NA, "Gd", "TA", ...
## $ TipoGaragem <chr> "Attchd", "Attchd", "Attchd", "Detchd", "Att...
## $ AnoGaragem <int> 2003, 1976, 2001, 1998, 2000, 1993, 2004, 19...
## $ AcabamentoGaragem <chr> "RFn", "RFn", "RFn", "Unf", "RFn", "Unf", "R...
## $ VagasGaragem <int> 2, 2, 2, 3, 3, 2, 2, 2, 2, 1, 1, 3, 1, 3, 1,...
## $ AreaGaragem <int> 548, 460, 608, 642, 836, 480, 636, 484, 468,...
## $ QualiGaragem <chr> "TA", "TA", "TA", "TA", "TA", "TA", "TA", "T...
## $ CondicaoGaragem <chr> "TA", "TA", "TA", "TA", "TA", "TA", "TA", "T...
## $ PavimEntrada <chr> "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y",...
## $ AreaDeck <int> 0, 298, 0, 0, 192, 40, 255, 235, 90, 0, 0, 1...
## $ AreaVarandaAberta <int> 61, 0, 42, 35, 84, 30, 57, 204, 0, 4, 0, 21,...
## $ AreaVarandaFechada <int> 0, 0, 0, 272, 0, 0, 0, 228, 205, 0, 0, 0, 0,...
## $ AreaVaranda3Sea <int> 0, 0, 0, 0, 0, 320, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ AreaVarandaScreen <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 0, ...
## $ AreaPiscina <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ QualiPiscina <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ QualiCerca <chr> NA, NA, NA, NA, NA, "MnPrv", NA, NA, NA, NA,...
## $ OutrosItens <chr> NA, NA, NA, NA, NA, "Shed", NA, "Shed", NA, ...
## $ ValorItens <int> 0, 0, 0, 0, 0, 700, 0, 350, 0, 0, 0, 0, 0, 0...
## $ MesVenda <int> 2, 5, 9, 2, 12, 10, 8, 11, 4, 1, 2, 7, 9, 8,...
## $ AnoVenda <int> 2008, 2007, 2008, 2006, 2008, 2009, 2007, 20...
## $ TipoVenda <chr> "WD", "WD", "WD", "WD", "WD", "WD", "WD", "W...
## $ CondicaoVenda <chr> "Normal", "Normal", "Normal", "Abnorml", "No...
## $ PrecoVenda <int> 208500, 181500, 223500, 140000, 250000, 1430...
## [1] 1460 81
O conjunto de treinamento conta com 1460 observações e 81 variáveis, entre inteiros e caracteres. Ao longo do estudo as variáveis de texto serão convertidas em fatores (categorias), ordinais ou não para poderem ser analisadas.
## Rows: 1,459
## Columns: 81
## $ Id <int> 1461, 1462, 1463, 1464, 1465, 1466, 1467, 14...
## $ Classe <int> 20, 20, 60, 60, 120, 60, 20, 60, 20, 20, 120...
## $ Zona <chr> "RH", "RL", "RL", "RL", "RL", "RL", "RL", "R...
## $ DimFrontal <int> 80, 81, 74, 78, 43, 75, NA, 63, 85, 70, 26, ...
## $ AreaLote <int> 11622, 14267, 13830, 9978, 5005, 10000, 7980...
## $ TipoEstrada <chr> "Pave", "Pave", "Pave", "Pave", "Pave", "Pav...
## $ TipoRua <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ RelevoLote <chr> "Reg", "IR1", "IR1", "IR1", "IR1", "IR1", "I...
## $ GreideLote <chr> "Lvl", "Lvl", "Lvl", "Lvl", "HLS", "Lvl", "L...
## $ Instalacoes <chr> "AllPub", "AllPub", "AllPub", "AllPub", "All...
## $ ImplantacaoLote <chr> "Inside", "Corner", "Inside", "Inside", "Ins...
## $ Declive <chr> "Gtl", "Gtl", "Gtl", "Gtl", "Gtl", "Gtl", "G...
## $ Bairro <chr> "NAmes", "NAmes", "Gilbert", "Gilbert", "Sto...
## $ Proximidade1 <chr> "Feedr", "Norm", "Norm", "Norm", "Norm", "No...
## $ Proximidade2 <chr> "Norm", "Norm", "Norm", "Norm", "Norm", "Nor...
## $ TipoHabitacao <chr> "1Fam", "1Fam", "1Fam", "1Fam", "TwnhsE", "1...
## $ Pavimentos <chr> "1Story", "1Story", "2Story", "2Story", "1St...
## $ QualidadeTotal <int> 5, 6, 5, 6, 8, 6, 6, 6, 7, 4, 7, 6, 5, 6, 7,...
## $ CondicaoTotal <int> 6, 6, 5, 6, 5, 5, 7, 5, 5, 5, 5, 5, 5, 6, 6,...
## $ AnoConstrucao <int> 1961, 1958, 1997, 1998, 1992, 1993, 1992, 19...
## $ AnoRetrofit <int> 1961, 1958, 1998, 1998, 1992, 1994, 2007, 19...
## $ TipoCobertura <chr> "Gable", "Hip", "Gable", "Gable", "Gable", "...
## $ MaterialCobertura <chr> "CompShg", "CompShg", "CompShg", "CompShg", ...
## $ Fachada1 <chr> "VinylSd", "Wd Sdng", "VinylSd", "VinylSd", ...
## $ Fachada2 <chr> "VinylSd", "Wd Sdng", "VinylSd", "VinylSd", ...
## $ TipoAlvenaria <chr> "None", "BrkFace", "None", "BrkFace", "None"...
## $ AreaAlvenaria <int> 0, 108, 0, 20, 0, 0, 0, 0, 0, 0, 0, 504, 492...
## $ QualidadeFachada <chr> "TA", "TA", "TA", "TA", "Gd", "TA", "TA", "T...
## $ CondicaoFachada <chr> "TA", "TA", "TA", "TA", "TA", "TA", "Gd", "T...
## $ Fundacao <chr> "CBlock", "CBlock", "PConc", "PConc", "PConc...
## $ AlturaPorao <chr> "TA", "TA", "Gd", "TA", "Gd", "Gd", "Gd", "G...
## $ CondicaoPorao <chr> "TA", "TA", "TA", "TA", "TA", "TA", "TA", "T...
## $ ExposicaoPorao <chr> "No", "No", "No", "No", "No", "No", "No", "N...
## $ RevestimentoPorao1 <chr> "Rec", "ALQ", "GLQ", "GLQ", "ALQ", "Unf", "A...
## $ AreaPoraoAcabado1 <int> 468, 923, 791, 602, 263, 0, 935, 0, 637, 804...
## $ RevestimentoPorao2 <chr> "LwQ", "Unf", "Unf", "Unf", "Unf", "Unf", "U...
## $ AreaPoraoAcabado2 <int> 144, 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0,...
## $ AreaPoraoInacab <int> 270, 406, 137, 324, 1017, 763, 233, 789, 663...
## $ AreaTotalPorao <int> 882, 1329, 928, 926, 1280, 763, 1168, 789, 1...
## $ Aquecimento <chr> "GasA", "GasA", "GasA", "GasA", "GasA", "Gas...
## $ CondicaoAquecimento <chr> "TA", "TA", "Gd", "Ex", "Ex", "Gd", "Ex", "G...
## $ ArCentral <chr> "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y",...
## $ SistemaEletrico <chr> "SBrkr", "SBrkr", "SBrkr", "SBrkr", "SBrkr",...
## $ AreaTerreo <int> 896, 1329, 928, 926, 1280, 763, 1187, 789, 1...
## $ Area1Pav <int> 0, 0, 701, 678, 0, 892, 0, 676, 0, 0, 0, 504...
## $ AreaAcabBaixaQualTotal <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ AreaVivenciaAcimaRua <int> 896, 1329, 1629, 1604, 1280, 1655, 1187, 146...
## $ BanheirosPorao <int> 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0,...
## $ LavaboPorao <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ BanheirosAcimaRua <int> 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1,...
## $ LavaboAcimaRua <int> 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0,...
## $ QuartosAcimaRua <int> 2, 3, 3, 3, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3, 2,...
## $ CozinhasAcimaRua <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
## $ QualidadeCozinha <chr> "TA", "Gd", "TA", "Gd", "Gd", "TA", "TA", "T...
## $ ComodosAcimarua <int> 5, 6, 6, 7, 5, 7, 6, 7, 5, 4, 5, 5, 6, 6, 4,...
## $ Descontos <chr> "Typ", "Typ", "Typ", "Typ", "Typ", "Typ", "T...
## $ Lareiras <int> 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0,...
## $ QualidadeLareira <chr> NA, NA, "TA", "Gd", NA, "TA", NA, "Gd", "Po"...
## $ TipoGaragem <chr> "Attchd", "Attchd", "Attchd", "Attchd", "Att...
## $ AnoGaragem <int> 1961, 1958, 1997, 1998, 1992, 1993, 1992, 19...
## $ AcabamentoGaragem <chr> "Unf", "Unf", "Fin", "Fin", "RFn", "Fin", "F...
## $ VagasGaragem <int> 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1,...
## $ AreaGaragem <int> 730, 312, 482, 470, 506, 440, 420, 393, 506,...
## $ QualiGaragem <chr> "TA", "TA", "TA", "TA", "TA", "TA", "TA", "T...
## $ CondicaoGaragem <chr> "TA", "TA", "TA", "TA", "TA", "TA", "TA", "T...
## $ PavimEntrada <chr> "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y",...
## $ AreaDeck <int> 140, 393, 212, 360, 0, 157, 483, 0, 192, 240...
## $ AreaVarandaAberta <int> 0, 36, 34, 36, 82, 84, 21, 75, 0, 0, 68, 0, ...
## $ AreaVarandaFechada <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ AreaVaranda3Sea <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ AreaVarandaScreen <int> 120, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ AreaPiscina <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ QualiPiscina <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ QualiCerca <chr> "MnPrv", NA, "MnPrv", NA, NA, NA, "GdPrv", N...
## $ OutrosItens <chr> NA, "Gar2", NA, NA, NA, NA, "Shed", NA, NA, ...
## $ ValorItens <int> 0, 12500, 0, 0, 0, 0, 500, 0, 0, 0, 0, 0, 0,...
## $ MesVenda <int> 6, 6, 3, 6, 1, 4, 3, 5, 2, 4, 6, 2, 3, 6, 6,...
## $ AnoVenda <int> 2010, 2010, 2010, 2010, 2010, 2010, 2010, 20...
## $ TipoVenda <chr> "WD", "WD", "WD", "WD", "WD", "WD", "WD", "W...
## $ CondicaoVenda <chr> "Normal", "Normal", "Normal", "Normal", "Nor...
## $ PrecoVenda <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## [1] 1459 81
O conjunto de treinamento conta com 1459 observações e 80 variáveis, entre inteiros e caracteres. Vale ressaltar que a coluna “PrecoVenda” foi inserida no começo do estudo para equalizar a quantidade de variáveis e possibilitar a união dos conjuntos objetivando o tratamento uniforme, bem como a visualização dos dados.
O resumo estatístico - mínimo, máximo, média, mediana, 1o e 3o quartis - das características (colunas) é apresentado a seguir
## Id Classe Zona DimFrontal
## Min. : 1.0 Min. : 20.00 Length:2919 Min. : 21.00
## 1st Qu.: 730.5 1st Qu.: 20.00 Class :character 1st Qu.: 59.00
## Median :1460.0 Median : 50.00 Mode :character Median : 68.00
## Mean :1460.0 Mean : 57.14 Mean : 69.31
## 3rd Qu.:2189.5 3rd Qu.: 70.00 3rd Qu.: 80.00
## Max. :2919.0 Max. :190.00 Max. :313.00
## NA's :486
## AreaLote TipoEstrada TipoRua RelevoLote
## Min. : 1300 Length:2919 Length:2919 Length:2919
## 1st Qu.: 7478 Class :character Class :character Class :character
## Median : 9453 Mode :character Mode :character Mode :character
## Mean : 10168
## 3rd Qu.: 11570
## Max. :215245
##
## GreideLote Instalacoes ImplantacaoLote Declive
## Length:2919 Length:2919 Length:2919 Length:2919
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## Bairro Proximidade1 Proximidade2 TipoHabitacao
## Length:2919 Length:2919 Length:2919 Length:2919
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## Pavimentos QualidadeTotal CondicaoTotal AnoConstrucao
## Length:2919 Min. : 1.000 Min. :1.000 Min. :1872
## Class :character 1st Qu.: 5.000 1st Qu.:5.000 1st Qu.:1954
## Mode :character Median : 6.000 Median :5.000 Median :1973
## Mean : 6.089 Mean :5.565 Mean :1971
## 3rd Qu.: 7.000 3rd Qu.:6.000 3rd Qu.:2001
## Max. :10.000 Max. :9.000 Max. :2010
##
## AnoRetrofit TipoCobertura MaterialCobertura Fachada1
## Min. :1950 Length:2919 Length:2919 Length:2919
## 1st Qu.:1965 Class :character Class :character Class :character
## Median :1993 Mode :character Mode :character Mode :character
## Mean :1984
## 3rd Qu.:2004
## Max. :2010
##
## Fachada2 TipoAlvenaria AreaAlvenaria QualidadeFachada
## Length:2919 Length:2919 Min. : 0.0 Length:2919
## Class :character Class :character 1st Qu.: 0.0 Class :character
## Mode :character Mode :character Median : 0.0 Mode :character
## Mean : 102.2
## 3rd Qu.: 164.0
## Max. :1600.0
## NA's :23
## CondicaoFachada Fundacao AlturaPorao CondicaoPorao
## Length:2919 Length:2919 Length:2919 Length:2919
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## ExposicaoPorao RevestimentoPorao1 AreaPoraoAcabado1 RevestimentoPorao2
## Length:2919 Length:2919 Min. : 0.0 Length:2919
## Class :character Class :character 1st Qu.: 0.0 Class :character
## Mode :character Mode :character Median : 368.5 Mode :character
## Mean : 441.4
## 3rd Qu.: 733.0
## Max. :5644.0
## NA's :1
## AreaPoraoAcabado2 AreaPoraoInacab AreaTotalPorao Aquecimento
## Min. : 0.00 Min. : 0.0 Min. : 0.0 Length:2919
## 1st Qu.: 0.00 1st Qu.: 220.0 1st Qu.: 793.0 Class :character
## Median : 0.00 Median : 467.0 Median : 989.5 Mode :character
## Mean : 49.58 Mean : 560.8 Mean :1051.8
## 3rd Qu.: 0.00 3rd Qu.: 805.5 3rd Qu.:1302.0
## Max. :1526.00 Max. :2336.0 Max. :6110.0
## NA's :1 NA's :1 NA's :1
## CondicaoAquecimento ArCentral SistemaEletrico AreaTerreo
## Length:2919 Length:2919 Length:2919 Min. : 334
## Class :character Class :character Class :character 1st Qu.: 876
## Mode :character Mode :character Mode :character Median :1082
## Mean :1160
## 3rd Qu.:1388
## Max. :5095
##
## Area1Pav AreaAcabBaixaQualTotal AreaVivenciaAcimaRua BanheirosPorao
## Min. : 0.0 Min. : 0.000 Min. : 334 Min. :0.0000
## 1st Qu.: 0.0 1st Qu.: 0.000 1st Qu.:1126 1st Qu.:0.0000
## Median : 0.0 Median : 0.000 Median :1444 Median :0.0000
## Mean : 336.5 Mean : 4.694 Mean :1501 Mean :0.4299
## 3rd Qu.: 704.0 3rd Qu.: 0.000 3rd Qu.:1744 3rd Qu.:1.0000
## Max. :2065.0 Max. :1064.000 Max. :5642 Max. :3.0000
## NA's :2
## LavaboPorao BanheirosAcimaRua LavaboAcimaRua QuartosAcimaRua
## Min. :0.00000 Min. :0.000 Min. :0.0000 Min. :0.00
## 1st Qu.:0.00000 1st Qu.:1.000 1st Qu.:0.0000 1st Qu.:2.00
## Median :0.00000 Median :2.000 Median :0.0000 Median :3.00
## Mean :0.06136 Mean :1.568 Mean :0.3803 Mean :2.86
## 3rd Qu.:0.00000 3rd Qu.:2.000 3rd Qu.:1.0000 3rd Qu.:3.00
## Max. :2.00000 Max. :4.000 Max. :2.0000 Max. :8.00
## NA's :2
## CozinhasAcimaRua QualidadeCozinha ComodosAcimarua Descontos
## Min. :0.000 Length:2919 Min. : 2.000 Length:2919
## 1st Qu.:1.000 Class :character 1st Qu.: 5.000 Class :character
## Median :1.000 Mode :character Median : 6.000 Mode :character
## Mean :1.045 Mean : 6.452
## 3rd Qu.:1.000 3rd Qu.: 7.000
## Max. :3.000 Max. :15.000
##
## Lareiras QualidadeLareira TipoGaragem AnoGaragem
## Min. :0.0000 Length:2919 Length:2919 Min. :1895
## 1st Qu.:0.0000 Class :character Class :character 1st Qu.:1960
## Median :1.0000 Mode :character Mode :character Median :1979
## Mean :0.5971 Mean :1978
## 3rd Qu.:1.0000 3rd Qu.:2002
## Max. :4.0000 Max. :2207
## NA's :159
## AcabamentoGaragem VagasGaragem AreaGaragem QualiGaragem
## Length:2919 Min. :0.000 Min. : 0.0 Length:2919
## Class :character 1st Qu.:1.000 1st Qu.: 320.0 Class :character
## Mode :character Median :2.000 Median : 480.0 Mode :character
## Mean :1.767 Mean : 472.9
## 3rd Qu.:2.000 3rd Qu.: 576.0
## Max. :5.000 Max. :1488.0
## NA's :1 NA's :1
## CondicaoGaragem PavimEntrada AreaDeck AreaVarandaAberta
## Length:2919 Length:2919 Min. : 0.00 Min. : 0.00
## Class :character Class :character 1st Qu.: 0.00 1st Qu.: 0.00
## Mode :character Mode :character Median : 0.00 Median : 26.00
## Mean : 93.71 Mean : 47.49
## 3rd Qu.: 168.00 3rd Qu.: 70.00
## Max. :1424.00 Max. :742.00
##
## AreaVarandaFechada AreaVaranda3Sea AreaVarandaScreen AreaPiscina
## Min. : 0.0 Min. : 0.000 Min. : 0.00 Min. : 0.000
## 1st Qu.: 0.0 1st Qu.: 0.000 1st Qu.: 0.00 1st Qu.: 0.000
## Median : 0.0 Median : 0.000 Median : 0.00 Median : 0.000
## Mean : 23.1 Mean : 2.602 Mean : 16.06 Mean : 2.252
## 3rd Qu.: 0.0 3rd Qu.: 0.000 3rd Qu.: 0.00 3rd Qu.: 0.000
## Max. :1012.0 Max. :508.000 Max. :576.00 Max. :800.000
##
## QualiPiscina QualiCerca OutrosItens ValorItens
## Length:2919 Length:2919 Length:2919 Min. : 0.00
## Class :character Class :character Class :character 1st Qu.: 0.00
## Mode :character Mode :character Mode :character Median : 0.00
## Mean : 50.83
## 3rd Qu.: 0.00
## Max. :17000.00
##
## MesVenda AnoVenda TipoVenda CondicaoVenda
## Min. : 1.000 Min. :2006 Length:2919 Length:2919
## 1st Qu.: 4.000 1st Qu.:2007 Class :character Class :character
## Median : 6.000 Median :2008 Mode :character Mode :character
## Mean : 6.213 Mean :2008
## 3rd Qu.: 8.000 3rd Qu.:2009
## Max. :12.000 Max. :2010
##
## PrecoVenda
## Min. : 34900
## 1st Qu.:129975
## Median :163000
## Mean :180921
## 3rd Qu.:214000
## Max. :755000
## NA's :1459
A linha tracejada representa a média e a linha contínua a mediana.
ggplot(data=todas[!is.na(todas$PrecoVenda),], aes(x=PrecoVenda)) +
geom_histogram(color="navy", fill="chartreuse3", binwidth = 10000) +
scale_x_continuous(breaks= seq(0, 800000, by=100000), labels = comma) +
geom_vline(aes(xintercept=mean(PrecoVenda)), color="navy", linetype="dashed", size=1)+
geom_vline(aes(xintercept=median(PrecoVenda)), color="navy", size=1)## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 34900 129975 163000 180921 214000 755000 1459
Percebe-se claramente uma distribuição não-uniforme com assimetria > 0 (cauda direita). Será necessario normalização.
Nesta etapa foram separadas as variáveis numéricas, calculadas suas correlações com a variável alvo (Coeficiente de correlação de Pearson) e plotadas somente as variáveis que possuem correlação maior que 0,5 (positiva ou negativa).
+1 ou -1 representam correlações perfeitas, seja diretamente proporcional (+) ou inversamente proporcional (-1)
numericVars <- which(sapply(todas, is.numeric))
numericVarNames <- names(numericVars) # salvando os titulos como vetor
all_numericas <- todas[, numericVars] # subset somente das numéricas
cor_numericas <- cor(all_numericas, use="pairwise.complete.obs") # correlações entre as numericas
cor_ordenada <- as.matrix(sort(cor_numericas[,'PrecoVenda'], decreasing = TRUE)) #ordenando de forma decrescente
# Selecionando as altas, retornando para a matriz e plotado
cor_alta <- names(which(apply(cor_ordenada, 1, function(x) abs(x)>0.5)))
cor_principaisnum <- cor_numericas[cor_alta, cor_alta]
corrplot.mixed(cor_principaisnum, tl.col="black", tl.pos = "lt")A priori, entre as variáveis numéricas, observa-se que as variáveis com maior correlação com o preço de venda são: Qualidade Total (acabamentos), Área Privativa (em pés quadrados) e quantiade de vagas na garagem. Contudo, neste momento é importante observar a altissima correlação de algumas variáveis entre si.
Pode-se perceber a alta correlação entre a Área da Garagam e a Quantiade de vagas, bem como Área Privativa (AreaVivenciaAcimaRua) e Quantiade de Cômodos. Estas relações são óbvias, porém dever haver uma atenção especial para evitar a multicolinearidade e consequentemente o comprometimento do algoritmo preditivo. Tais variáveis serão tratadas com mais detalhes na etapa de Feature Engineering.
Esta matriz é apenas uma visualização preliminar, após transformar algumas variáveis categóricas em numéricas a matriz será recalculada para mais variáveis. Além disso, como forma de determinar a importância de cada característica, a matriz é relativamente limitada. Mais à frente o estudo irá aplicar algoritmos avançados que consideram permutações aleatórias e erros associados para criar um ranking de importância. Logo, estas informações são apenas para se familiarizar com as informações fornecidas.
ggplot(data=todas[!is.na(todas$PrecoVenda),], aes(x=factor(QualidadeTotal), y=PrecoVenda))+
geom_boxplot(col='navy') + labs(x='Qualidade Total') +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)Percebe-se claramente a relação entre qualidade e preço de venda no que se aproxima de uma curva. Observa-se também que a distância ente o primeiro e o terceiro quartil aumenta para as casas com maior qualidade total, provavelmente influência de outras variáveis inexistentes nos demais imóveis.
ggplot(data=todas[!is.na(todas$PrecoVenda),], aes(x=AreaVivenciaAcimaRua, y=PrecoVenda))+
geom_point(col='navy') + geom_smooth(method = "lm", color="chartreuse3", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)Dois pontos se destacam com uma área privativa grande e preço muito baixo, bem como dois pontos também possuem área grande e valores muito altos. Uma opção é rotular estes pontos para recuperação dos dados.
ggplot(data=todas[!is.na(todas$PrecoVenda),], aes(x=AreaVivenciaAcimaRua, y=PrecoVenda))+
geom_point(col='navy') + geom_smooth(method = "lm", color="chartreuse3", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)+
geom_text_repel(aes(label = ifelse(todas$AreaVivenciaAcimaRua[!is.na(todas$PrecoVenda)]>4000, rownames(todas), '')))Assim, pode-se recuperar estes 4 imóveis e proceder uma avaliação isolada pra investigação desta variação:
kable(todas[c(524,692,1183,1299),]) %>%
kableExtra::kable_styling() %>%
kableExtra::scroll_box(width = "100%")| Id | Classe | Zona | DimFrontal | AreaLote | TipoEstrada | TipoRua | RelevoLote | GreideLote | Instalacoes | ImplantacaoLote | Declive | Bairro | Proximidade1 | Proximidade2 | TipoHabitacao | Pavimentos | QualidadeTotal | CondicaoTotal | AnoConstrucao | AnoRetrofit | TipoCobertura | MaterialCobertura | Fachada1 | Fachada2 | TipoAlvenaria | AreaAlvenaria | QualidadeFachada | CondicaoFachada | Fundacao | AlturaPorao | CondicaoPorao | ExposicaoPorao | RevestimentoPorao1 | AreaPoraoAcabado1 | RevestimentoPorao2 | AreaPoraoAcabado2 | AreaPoraoInacab | AreaTotalPorao | Aquecimento | CondicaoAquecimento | ArCentral | SistemaEletrico | AreaTerreo | Area1Pav | AreaAcabBaixaQualTotal | AreaVivenciaAcimaRua | BanheirosPorao | LavaboPorao | BanheirosAcimaRua | LavaboAcimaRua | QuartosAcimaRua | CozinhasAcimaRua | QualidadeCozinha | ComodosAcimarua | Descontos | Lareiras | QualidadeLareira | TipoGaragem | AnoGaragem | AcabamentoGaragem | VagasGaragem | AreaGaragem | QualiGaragem | CondicaoGaragem | PavimEntrada | AreaDeck | AreaVarandaAberta | AreaVarandaFechada | AreaVaranda3Sea | AreaVarandaScreen | AreaPiscina | QualiPiscina | QualiCerca | OutrosItens | ValorItens | MesVenda | AnoVenda | TipoVenda | CondicaoVenda | PrecoVenda | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 524 | 524 | 60 | RL | 130 | 40094 | Pave | NA | IR1 | Bnk | AllPub | Inside | Gtl | Edwards | PosN | PosN | 1Fam | 2Story | 10 | 5 | 2007 | 2008 | Hip | CompShg | CemntBd | CmentBd | Stone | 762 | Ex | TA | PConc | Ex | TA | Gd | GLQ | 2260 | Unf | 0 | 878 | 3138 | GasA | Ex | Y | SBrkr | 3138 | 1538 | 0 | 4676 | 1 | 0 | 3 | 1 | 3 | 1 | Ex | 11 | Typ | 1 | Gd | BuiltIn | 2007 | Fin | 3 | 884 | TA | TA | Y | 208 | 406 | 0 | 0 | 0 | 0 | NA | NA | NA | 0 | 10 | 2007 | New | Partial | 184750 |
| 692 | 692 | 60 | RL | 104 | 21535 | Pave | NA | IR1 | Lvl | AllPub | Corner | Gtl | NoRidge | Norm | Norm | 1Fam | 2Story | 10 | 6 | 1994 | 1995 | Gable | WdShngl | HdBoard | HdBoard | BrkFace | 1170 | Ex | TA | PConc | Ex | TA | Gd | GLQ | 1455 | Unf | 0 | 989 | 2444 | GasA | Ex | Y | SBrkr | 2444 | 1872 | 0 | 4316 | 0 | 1 | 3 | 1 | 4 | 1 | Ex | 10 | Typ | 2 | Ex | Attchd | 1994 | Fin | 3 | 832 | TA | TA | Y | 382 | 50 | 0 | 0 | 0 | 0 | NA | NA | NA | 0 | 1 | 2007 | WD | Normal | 755000 |
| 1183 | 1183 | 60 | RL | 160 | 15623 | Pave | NA | IR1 | Lvl | AllPub | Corner | Gtl | NoRidge | Norm | Norm | 1Fam | 2Story | 10 | 5 | 1996 | 1996 | Hip | CompShg | Wd Sdng | ImStucc | None | 0 | Gd | TA | PConc | Ex | TA | Av | GLQ | 2096 | Unf | 0 | 300 | 2396 | GasA | Ex | Y | SBrkr | 2411 | 2065 | 0 | 4476 | 1 | 0 | 3 | 1 | 4 | 1 | Ex | 10 | Typ | 2 | TA | Attchd | 1996 | Fin | 3 | 813 | TA | TA | Y | 171 | 78 | 0 | 0 | 0 | 555 | Ex | MnPrv | NA | 0 | 7 | 2007 | WD | Abnorml | 745000 |
| 1299 | 1299 | 60 | RL | 313 | 63887 | Pave | NA | IR3 | Bnk | AllPub | Corner | Gtl | Edwards | Feedr | Norm | 1Fam | 2Story | 10 | 5 | 2008 | 2008 | Hip | ClyTile | Stucco | Stucco | Stone | 796 | Ex | TA | PConc | Ex | TA | Gd | GLQ | 5644 | Unf | 0 | 466 | 6110 | GasA | Ex | Y | SBrkr | 4692 | 950 | 0 | 5642 | 2 | 0 | 2 | 1 | 3 | 1 | Ex | 12 | Typ | 3 | Gd | Attchd | 2008 | Fin | 2 | 1418 | TA | TA | Y | 214 | 292 | 0 | 0 | 0 | 480 | Gd | NA | NA | 0 | 1 | 2008 | New | Partial | 160000 |
Este estudo não se aprofundará neste tipo de análise (diagnóstica). Caso estas variáveis impactem como outliers, serão descartadas na etapa de Feature Engineering. Já visualização das demais variáveis será feita na próxima etapa, em conjunto com o tratamento dos dados missing e de forma mais detalhada também na etapa de Feature Engineering.
O tratamento de dados missing é uma etapa fundamental para não comprometer análises futuras, além de obrigatória para a modelagem do algoritmo preditivo. Para tal, existem considerações importante a se fazer e diferentes decisões que vão variar de acordo com quem está tratando os dados.
Importante lembrar que o valor NA não é propriamente um valor, e sim uma sintaxe da linguagem que representa um dado faltante. Por conta da expressão em português Não Aplicável existe essa confusão, mas para o software NA indica Not Available. Por isso, precisam ser substituido por alguma informação, nem que seja não possui, 0, Não Aplicável, etc.
Eventualmente, vão existir colunas no conjunto de dados que a presença do NA é esperada, pois é assim que os dados saem da ferramenta transacional (geralmente um campo não-obrigatório que não foi preenchido). E no caso deste conjunto, na própria documentação são informados os significados do valor NA de algumas variáveis categóricas. Geralmente “não possui”.
Contudo, em variáveis numéricas onde o valor zero significa não possui, o valor NA deve ser tratado com mais cautela. E isto precisa ocorrer caso a caso, podendo substituí-los por zero quando houver evidências (geralmente em outras variáveis correlatas), pela média das outras observações, mediana, valor mais comum, proporção de outra variável, eliminação da observação entre outras opções. Por este motivo esta análise é a mais extensa e criteriosa do estudo.
Vale ressaltar que as 1459 linhas do conjunto de teste estão com valor NA na coluna PrecoVenda que foi criada para poder unir os dois conjuntos, estão é esperado que a coluna PrecoVenda tenha, pelo menos, 1459 NAs. Esta coluna não precisa de tratamento pois os conjuntos serão separados novamente no momento da modelagem.
NAcol <- which(colSums(is.na(todas)) > 0) # quais colunas tem NA
sort(colSums(sapply(todas[NAcol], is.na)), decreasing = TRUE) # somando quantidade de NA e ordenando## QualiPiscina OutrosItens TipoRua QualiCerca
## 2909 2814 2721 2348
## PrecoVenda QualidadeLareira DimFrontal AnoGaragem
## 1459 1420 486 159
## AcabamentoGaragem QualiGaragem CondicaoGaragem TipoGaragem
## 159 159 159 157
## CondicaoPorao ExposicaoPorao AlturaPorao RevestimentoPorao2
## 82 82 81 80
## RevestimentoPorao1 TipoAlvenaria AreaAlvenaria Zona
## 79 24 23 4
## Instalacoes BanheirosPorao LavaboPorao Descontos
## 2 2 2 2
## Fachada1 Fachada2 AreaPoraoAcabado1 AreaPoraoAcabado2
## 1 1 1 1
## AreaPoraoInacab AreaTotalPorao SistemaEletrico QualidadeCozinha
## 1 1 1 1
## VagasGaragem AreaGaragem TipoVenda
## 1 1 1
## Existem 35 colunas com valores missing
Como esperado, 1459 NAs na coluna PrecoVenda, o que é ótimo, pois não existem NAs onde era para ter valor (conjunto de treinamento).
Algumas colunas chamam a atençao, como o tipo de garagem de possui 157 NAs enquanto as outras relacionadas à garagem possuem 159, mas serão avaliados um a um.
Esta etapa aproveita para converter algumas variáveis em texto (char) em categorias (factors). Neste sentido, quando existir ordinalidade entre as categorias como: péssimo, ruim, regular etc serão atribuídos valores numéricos, possibilitando cálculos.
Segundo a documentação, para esta variável, os valores NA signifcam "None" ou "Não existe".
As categorias da variável são claramente ordinais: de péssimo a excelente. Como esta classificação é repetida para outras variáveis, será criado um vetor Qualidades, relacionando o texto a um número e facilitando as transformações futuras.
Qualidades <- c('None' = 0, 'Po' = 1, 'Fa' = 2, 'TA' = 3, 'Gd' = 4, 'Ex' = 5) # criação do vetor Qualidades
todas$QualiPiscina <- as.integer(revalue(todas$QualiPiscina, Qualidades)) # atribuição de valores
table(todas$QualiPiscina) # contagem##
## 0 2 4 5
## 2909 2 4 4
Nesta etapa é importante avaliar a relação com outras variáveis, por exemplo: área da piscina para encontrar inconsistências, pois não pode haver piscinas com zero na variável Qualidade da Piscina e ao mesmo tempo área da piscina diferente de zero. Para verificar estas condições será puxado os imóveis com Área Piscina > 0 e suas respectivas Qualidades atribuidas:
## Id AreaPiscina QualiPiscina
## 1 2421 368 0
## 2 2504 444 0
## 3 2600 561 0
## 4 811 648 2
## 5 1387 519 2
## 6 1171 576 4
## 7 1299 480 4
## 8 1424 738 4
## 9 2711 800 4
## 10 198 512 5
## 11 1183 555 5
## 12 1975 144 5
## 13 2574 228 5
Observa-se que três casas possuem QualiPiscina = 0 e possuem Área de piscina > 0, certamente eram valores que vieram NA mas eram pra estar preenchidos com a qualidade. Para substituição dos valores uma opção é econtrar uma relação (ainda que visual) com outras variáveis. Será testado com a variável Qualidade Total.
## Id AreaPiscina QualiPiscina QualidadeTotal
## 1 2421 368 0 4
## 2 2504 444 0 6
## 3 2600 561 0 3
## 4 811 648 2 6
## 5 1387 519 2 7
## 6 1171 576 4 6
## 7 1299 480 4 10
## 8 1424 738 4 6
## 9 2711 800 4 7
## 10 198 512 5 8
## 11 1183 555 5 10
## 12 1975 144 5 10
## 13 2574 228 5 8
É perceptível uma relação sutil entre a qualidade da piscina e a qualidade total. Portanto, serão atribuidos valores estimados intuitivamente para a qualidade da piscina nas duas casas observadas (2421, 2504 e 2600). Devido ao baixo número de observações, não se faz necessário interpolar ou estudar regressões para estimativa dos valores.
A variável Outros Itens diz respeito a demais sistemas do imóvel não contabilizados como elevadores, quadra de tenis e outros. Tal qual QualiPiscina, segundo a documentação, valores NA significam None e significa que o imóvel não possui estes outros itens.
Como não existe ordinalidade evidente entre as categorias (como péssimo, ruim, regular, etc), será observado a relação com o Preço de Venda.
obs.: o gráfico plota uma barra com a mediana no Preco de Venda para cada categoria da variável, um ponto com a média do Preço de Venda e uma contagem numérica dos imóveis de cada categoria.
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=OutrosItens, y=PrecoVenda)) +
geom_bar(stat="summary", fun="median", fill='chartreuse3') +
stat_summary(fun="mean")+
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..))Como não existe uma ordem clara entre as categorias, não há como relacioná-las à variáveis numéricas e será apenas transformada em fator, que é o tipo de sintaxe referente a categorias.
##
## Gar2 None Othr Shed TenC
## 5 2814 4 95 1
Similar aos anteriores, o valor NA significa None.
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=TipoRua, y=PrecoVenda)) +
geom_bar(stat="summary", fun="median", fill='navyblue') +
stat_summary(fun="mean", color= "chartreuse3")+
scale_y_continuous(breaks= seq(0, 200000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..))Também não será transformada em variável numérica.
##
## Grvl None Pave
## 120 2721 78
Similar aos anteriores, o valor NA significa None.
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=QualiCerca, y=PrecoVenda)) +
geom_bar(stat="summary", fun="median", fill='chartreuse3') +
stat_summary(fun="mean", color="navy")+
scale_y_continuous(breaks= seq(0, 200000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..))Talvez, mas não óbvio.
todas[!is.na(todas$PrecoVenda),] %>% group_by(QualiCerca) %>%
summarise(mediana = median(PrecoVenda), media = mean(PrecoVenda), counts=n())## # A tibble: 5 x 4
## QualiCerca mediana media counts
## <chr> <dbl> <dbl> <int>
## 1 GdPrv 167500 178927. 59
## 2 GdWo 138750 140379. 54
## 3 MnPrv 137450 148751. 157
## 4 MnWw 130000 134286. 11
## 5 None 173000 187597. 1179
Não há variações claras de acordo com a categoria. Portanto, não serão transformadas em numéricas.
##
## GdPrv GdWo MnPrv MnWw None
## 118 112 329 12 2348
Similar aos anteriores, o valor NA significa None.
##
## Ex Fa Gd None Po TA
## 43 74 744 1420 46 592
As categorias são as mesmas já tratadas para qualidade da piscina e, desta forma, serão tranformadas em numéricas.
todas$QualidadeLareira <- as.integer(revalue(todas$QualidadeLareira, Qualidades))
table(todas$QualidadeLareira)##
## 0 1 2 3 4 5
## 1420 46 74 592 744 43
Esta é uma variável numérica, o que significa não que existe uma definição para o valor NA, é apenas um valor não preenchido. Assim, foi decidido substituir os valores NA pela mediana dos valores de Dimensão Frontal no mesmo bairro daquele imóvel.
A plotagem abaixo mostra que os valores de dimensão frontal varia consideravelmente para cada bairro.
ggplot(todas[!is.na(todas$DimFrontal),], aes(x=as.factor(Bairro), y=DimFrontal)) +
geom_bar(stat='summary', fun = "median", fill='navyblue') +
stat_summary(fun="mean", color="chartreuse3")+
theme(axis.text.x = element_text(angle = 45, hjust = 1))for (i in 1:nrow(todas)){
if(is.na(todas$DimFrontal[i])){
todas$DimFrontal[i] <- as.integer(median(todas$DimFrontal[todas$Bairro==todas$Bairro[i]], na.rm=TRUE))
}
}
summary(todas$DimFrontal)## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 21.00 60.00 70.00 69.54 80.00 313.00
As classes de relevo, apesar de não possuirem NAs, são ordinárias e serão transformadas em numéricas.
todas$RelevoLote <- as.integer(revalue(todas$RelevoLote, c('IR3'=0,'IR2'=1, 'IR1'=2,'Reg'=3)))
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=RelevoLote, y=PrecoVenda)) +
geom_bar(stat="summary", fun="median", fill='chartreuse3') +
stat_summary(fun="mean", color="navyblue")+
scale_y_continuous(breaks= seq(0, 500000, by=50000), labels = comma) +
scale_x_continuous(breaks= seq(0, 500000, by=1)) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..))##
## 0 1 2 3
## 16 76 968 1859
A implantação não parece ordinal, nem pelas classes nem pela distribuição. Portanto, só sera convertido em fator
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(ImplantacaoLote), y=PrecoVenda)) +
geom_bar(stat="summary", fun="median", fill='navyblue') +
stat_summary(fun="mean",color="chartreuse3")+
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..))##
## Corner CulDSac FR2 FR3 Inside
## 511 176 85 14 2133
Os NAs serão substítuidos pelo ano de construção do imóvel
Conforme a documentação do conjunto de dados, NA significa “sem garagem”. Contudo, existem 159 casas sem garagens em 3 variáveis e 157 casas sem garagem na variável . Estes 2 casos precisam ser investigados mais próximos.
kable(todas[!is.na(todas$TipoGaragem) & is.na(todas$CondicaoGaragem),
c('AnoGaragem', 'AcabamentoGaragem', 'TipoGaragem', 'QualiGaragem', 'CondicaoGaragem', 'AreaGaragem', 'VagasGaragem')])| AnoGaragem | AcabamentoGaragem | TipoGaragem | QualiGaragem | CondicaoGaragem | AreaGaragem | VagasGaragem | |
|---|---|---|---|---|---|---|---|
| 2127 | 1910 | NA | Detchd | NA | NA | 360 | 1 |
| 2577 | 1923 | NA | Detchd | NA | NA | NA | NA |
Aparentemente o imóvel 2127 possui garagem, uma vez que tem área e vagas preenchidas. Estão faltando , e . Tais valores serão substituidos pelo valor mais comum.
todas$CondicaoGaragem[2127] <- names(sort(-table(todas$CondicaoGaragem)))[1]
todas$QualiGaragem[2127] <- names(sort(-table(todas$QualiGaragem)))[1]
todas$AcabamentoGaragem[2127] <- names(sort(-table(todas$AcabamentoGaragem)))[1]Ja o imóvel 2577 aparentemente não possui garagem, e o tipo está preenchido incorretamente. Será atribuído NA ao Tipo e 0 à área e às vagas.
O tipo de garagem não parece ser ordinário, não será convertido em variável numérica.
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(TipoGaragem), y=PrecoVenda)) +
geom_bar(stat="summary", fun="median", fill='chartreuse3') +
stat_summary(fun="mean", color="navyblue")+
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..))todas$TipoGaragem[is.na(todas$TipoGaragem)] <- 'No Garage'
todas$TipoGaragem <- as.factor(todas$TipoGaragem)
table(todas$TipoGaragem)##
## 2Types Attchd Basment BuiltIn CarPort Detchd No Garage
## 23 1723 36 186 15 778 158
As três variáveis funcionam da mesma forma: NA = "None" e os valores podem ser convertidos em numéricos.
Acabamento
todas$AcabamentoGaragem[is.na(todas$AcabamentoGaragem)] <- 'No Garage'
acabamentos <- c('No Garage'=0,'Unf'=1,'RFn'=2,'Fin'=3)
todas$AcabamentoGaragem <- as.integer(revalue(todas$AcabamentoGaragem, acabamentos))
table(todas$AcabamentoGaragem)##
## 0 1 2 3
## 158 1231 811 719
Qualidade
todas$QualiGaragem[is.na(todas$QualiGaragem)] <- 'None'
todas$QualiGaragem <- as.integer(revalue(todas$QualiGaragem, Qualidades))
table(todas$QualiGaragem)##
## 0 1 2 3 4 5
## 158 5 124 2605 24 3
Condição
todas$CondicaoGaragem[is.na(todas$CondicaoGaragem)] <- 'None'
todas$CondicaoGaragem <- as.integer(revalue(todas$CondicaoGaragem, Qualidades))
table(todas$CondicaoGaragem)##
## 0 1 2 3 4 5
## 158 14 74 2655 15 3
Aqui observa-se que existem 5 variáveis com quantidades próximas de valores NA (entre 79 e 82) e 5 variáveis com poucos NAs, entre 1 e 2.
NAcol <- which(colSums(is.na(todas)) > 0) # quais colunas tem NA
sort(colSums(sapply(todas[NAcol], is.na)), decreasing = TRUE) # somando quantidade de NA e ordenando## PrecoVenda CondicaoPorao ExposicaoPorao AlturaPorao
## 1459 82 82 81
## RevestimentoPorao2 RevestimentoPorao1 TipoAlvenaria AreaAlvenaria
## 80 79 24 23
## Zona Instalacoes BanheirosPorao LavaboPorao
## 4 2 2 2
## Descontos Fachada1 Fachada2 AreaPoraoAcabado1
## 2 1 1 1
## AreaPoraoAcabado2 AreaPoraoInacab AreaTotalPorao SistemaEletrico
## 1 1 1 1
## QualidadeCozinha TipoVenda
## 1 1
Primeiro, será verificado se os 79 NAs da variável RevestimentoPorao1 também são NAs nas outras 4 variáveis. A linha de código a seguir informa a quantidade de valores que são NA, simultaneamente, nas 5 variáveis listadas (CondicaoPorao, ExposicaoPorao, AlturaPorao, RevestimentoPorao1 e RevestimentoPorao2):
length(which(is.na(todas$CondicaoPorao) & is.na(todas$ExposicaoPorao) & is.na(todas$AlturaPorao) &
is.na(todas$RevestimentoPorao1) & is.na(todas$RevestimentoPorao2)))## [1] 79
Isto indica que, provavelmente, existam 79 imóveis sem porão acabado e nas demais variáveis 1, 2 ou 3 NAs a serem corrigidos com investigação mais detalhada.
kable(todas[!is.na(todas$RevestimentoPorao1) &
(is.na(todas$CondicaoPorao)|is.na(todas$ExposicaoPorao)|is.na(todas$AlturaPorao)|is.na(todas$RevestimentoPorao2)),
c('CondicaoPorao', 'ExposicaoPorao', 'AlturaPorao', 'RevestimentoPorao2', 'RevestimentoPorao1')]) %>%
kableExtra::kable_styling() %>%
kableExtra::scroll_box(width = "100%")| CondicaoPorao | ExposicaoPorao | AlturaPorao | RevestimentoPorao2 | RevestimentoPorao1 | |
|---|---|---|---|---|---|
| 333 | TA | No | Gd | NA | GLQ |
| 949 | TA | NA | Gd | Unf | Unf |
| 1488 | TA | NA | Gd | Unf | Unf |
| 2041 | NA | Mn | Gd | Rec | GLQ |
| 2186 | NA | No | TA | Unf | BLQ |
| 2218 | Fa | No | NA | Unf | Unf |
| 2219 | TA | No | NA | Unf | Unf |
| 2349 | TA | NA | Gd | Unf | Unf |
| 2525 | NA | Av | TA | Unf | ALQ |
Aqui vemos que os NAs das outras 4 variáveis estão espalhados e não são no mesmo imóvel. Caso estivessem, provavelmente a variável RevestimentoPorao1 estaria preenchida quando era para ser NA (sem porão).
Neste caso, cada variável sera substituida pelo valor mais comum (moda) do seu respectivo bairro.
getmode <- function(v) {
uniqv <- unique(v)
uniqv[which.max(tabulate(match(v, uniqv)))]
}
todas$RevestimentoPorao2[333] <- getmode(todas$RevestimentoPorao2[todas$Bairro==todas$Bairro[333]])
todas$AlturaPorao[2218] <- getmode(todas$AlturaPorao[todas$Bairro==todas$Bairro[2218]])
todas$AlturaPorao[2219] <- getmode(todas$AlturaPorao[todas$Bairro==todas$Bairro[2219]])
todas$ExposicaoPorao[949] <- getmode(todas$ExposicaoPorao[todas$Bairro==todas$Bairro[949]])
todas$ExposicaoPorao[1488] <- getmode(todas$ExposicaoPorao[todas$Bairro==todas$Bairro[1488]])
todas$ExposicaoPorao[2349] <- getmode(todas$ExposicaoPorao[todas$Bairro==todas$Bairro[2349]])
todas$CondicaoPorao[2041] <- getmode(todas$CondicaoPorao[todas$Bairro==todas$Bairro[2041]])
todas$CondicaoPorao[2186] <- getmode(todas$CondicaoPorao[todas$Bairro==todas$Bairro[2186]])
todas$CondicaoPorao[2525] <- getmode(todas$CondicaoPorao[todas$Bairro==todas$Bairro[2525]])Para conferir, será atualizada a tabela acima. O esperado e que não encontre linhas com valores NA em nenhuma das 5 variáveis:
todas[!is.na(todas$RevestimentoPorao1) &
(is.na(todas$CondicaoPorao)|is.na(todas$ExposicaoPorao)|is.na(todas$AlturaPorao)|is.na(todas$RevestimentoPorao2)),
c('CondicaoPorao', 'ExposicaoPorao', 'AlturaPorao', 'RevestimentoPorao2', 'RevestimentoPorao1')]## [1] CondicaoPorao ExposicaoPorao AlturaPorao RevestimentoPorao2
## [5] RevestimentoPorao1
## <0 rows> (or 0-length row.names)
Todas as variáeis acima, os NAs significam None conforme a documentação do conjunto de dados além de possuírem ordinalidade nas suas categorias, sendo assim transformadas em variáveis numéricas.
##
## Ex Fa Gd None TA
## 258 88 1209 79 1285
todas$AlturaPorao <- as.integer(revalue(todas$AlturaPorao, Qualidades))
todas$CondicaoPorao[is.na(todas$CondicaoPorao)] <- 'None'
table(todas$CondicaoPorao)##
## Fa Gd None Po TA
## 104 122 79 5 2609
todas$CondicaoPorao <- as.integer(revalue(todas$CondicaoPorao, Qualidades))
todas$ExposicaoPorao[is.na(todas$ExposicaoPorao)] <- 'None'
table(todas$ExposicaoPorao)##
## Av Gd Mn No None
## 418 276 239 1907 79
todas$ExposicaoPorao <- as.integer(revalue(todas$ExposicaoPorao, c('None'=0, 'No'=1, 'Mn'=2, 'Av'=3, 'Gd'=4)))
todas$RevestimentoPorao1[is.na(todas$RevestimentoPorao1)] <- 'None'
table(todas$RevestimentoPorao1)##
## ALQ BLQ GLQ LwQ None Rec Unf
## 429 269 849 154 79 288 851
todas$RevestimentoPorao1 <- as.integer(revalue(todas$RevestimentoPorao1,
c('None'=0, 'Unf'=1, 'LwQ'=2, 'Rec'=3, 'BLQ'=4, 'ALQ'=5, 'GLQ'=6)))
todas$RevestimentoPorao2[is.na(todas$RevestimentoPorao2)] <- 'None'
table(todas$RevestimentoPorao2)##
## ALQ BLQ GLQ LwQ None Rec Unf
## 52 68 34 87 79 105 2494
Percebe-se que todos os NAs estão apenas em 2 imóveis, e que as demais áreas são 0. Sendo assim, por lógica, os NAs também eram para ser 0.
todas[is.na(todas$BanheirosPorao)|is.na(todas$LavaboPorao)|is.na(todas$AreaPoraoAcabado1)|is.na(todas$AreaPoraoAcabado2)
|is.na(todas$AreaPoraoInacab)|is.na(todas$AreaTotalPorao) & todas$AlturaPorao,
c('BanheirosPorao', 'LavaboPorao', 'AreaPoraoAcabado1', 'AreaPoraoAcabado2', 'AreaPoraoInacab',
'AreaTotalPorao', 'AlturaPorao')]## BanheirosPorao LavaboPorao AreaPoraoAcabado1 AreaPoraoAcabado2
## 2121 NA NA NA NA
## 2189 NA NA 0 0
## AreaPoraoInacab AreaTotalPorao AlturaPorao
## 2121 NA NA 0
## 2189 0 0 0
##
## 0 1 2 3
## 1705 1172 38 2
##
## 0 1 2
## 2742 171 4
Da mesma forma, será verificado se os 23 NAs da variável Area também são NAs na variável Tipo.
## [1] 23
Sim. Portanto, o valor NA “excedente” do tipo será puxado
todas[!is.na(todas$AreaAlvenaria) & (is.na(todas$TipoAlvenaria)),
c('TipoAlvenaria', 'AreaAlvenaria')]## TipoAlvenaria AreaAlvenaria
## 2611 <NA> 198
O valor tem área preenchida normalmente e tipo NA, assim o tipo será substituido pelo segundo valor mais comum, pois o primeiro é none.
Investigando os imóveis que possuem área de alvenaria acabada mas possui tipo None:
todas[!is.na(todas$AreaAlvenaria) & todas$TipoAlvenaria=='None' & todas$AreaAlvenaria>0,
c('TipoAlvenaria', 'AreaAlvenaria')]## TipoAlvenaria AreaAlvenaria
## 625 None 288
## 774 None 1
## 1231 None 1
## 1301 None 344
## 1335 None 312
## 1670 None 285
## 2453 None 1
Substituindo pelo segundo valor mais comum:
for (i in 1:nrow(todas)){
if(!is.na(todas$AreaAlvenaria[i]) & todas$TipoAlvenaria[i]=='None' & todas$AreaAlvenaria[i]>0){
todas$TipoAlvenaria[i] <- names(sort(-table(todas$TipoAlvenaria)))[2]
}
}Aqui vale ressaltar que None é uma categoria da variável e ja veio no conjunto original de dados, os valores NA ainda continuam NA. Nas variáveis anteriores o valor que era para ser None vinha como NA.
Os 23 NA são casas que não possuem área de alvenaria acabada (dentro das opções apresentadas) e precisam ser transformados em None.
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(TipoAlvenaria), y=PrecoVenda)) +
geom_bar(stat="summary", fun="median", fill='navyblue') +
stat_summary(fun="mean", color= "chartreuse3")+
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..))##
## BrkCmn BrkFace None Stone
## 25 887 1758 249
Atribuindo ordinalidade
todas[!is.na(todas$PrecoVenda),] %>% group_by(TipoAlvenaria) %>%
summarise(mediana = median(PrecoVenda), media = mean(PrecoVenda), counts=n())## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 4 x 4
## TipoAlvenaria mediana media counts
## <chr> <dbl> <dbl> <int>
## 1 BrkCmn 139000 146318. 15
## 2 BrkFace 181000 204239. 450
## 3 None 143000 156918. 867
## 4 Stone 246839 265584. 128
Será atribuida a zona mais comum no respectivo bairro
for (i in 1:nrow(todas)){
if(is.na(todas$Zona[i])){
todas$Zona[i] <- getmode(todas$Zona[todas$Bairro==todas$Bairro[i]])
}
}
todas$Zona<- as.factor(todas$Zona)
table(todas$Zona)##
## C (all) FV RH RL RM
## 25 139 26 2266 463
Atribuído valor mais comum e transformado em variável numérica.
todas$QualidadeCozinha[is.na(todas$QualidadeCozinha)] <- names(sort(-table(todas$QualidadeCozinha)))[1]
table(todas$QualidadeCozinha)##
## Ex Fa Gd TA
## 205 70 1151 1493
todas$QualidadeCozinha <- as.integer(revalue(todas$QualidadeCozinha, Qualidades))
table(todas$QualidadeCozinha)##
## 2 3 4 5
## 70 1493 1151 205
##
## AllPub NoSeWa
## 2916 1
Observa-se que somente um imóvel não é AllPub. Logo, a variável não é significativa para análise nem para o algoritmo regressor e será descartada.
Atribuído valor mais comum e transformado em variável numérica.
todas$Descontos[is.na(todas$Descontos)] <- names(sort(-table(todas$Descontos)))[1]
table(todas$Descontos)##
## Maj1 Maj2 Min1 Min2 Mod Sev Typ
## 19 9 65 70 35 2 2719
todas$Descontos <- as.integer(revalue(todas$Descontos,
c('Sal'=0, 'Sev'=1, 'Maj2'=2, 'Maj1'=3, 'Mod'=4, 'Min2'=5, 'Min1'=6, 'Typ'=7)))
table(todas$Descontos)##
## 1 2 3 4 5 6 7
## 2 9 19 35 70 65 2719
Verificando de os NAs da Fachada1 e Fachada2 estão na mesma observação.
todas[is.na(todas$Fachada1) & (is.na(todas$Fachada2)),
c('Fachada1', 'Fachada2', 'QualidadeFachada')]## Fachada1 Fachada2 QualidadeFachada
## 2152 <NA> <NA> TA
Como possui qualidade, será atribuído o valor mais comum e a variável Qualidade Fachada convertida em numérico.
todas$Fachada1[is.na(todas$Fachada1)] <- names(sort(-table(todas$Fachada1)))[1]
todas$Fachada2[is.na(todas$Fachada2)] <- names(sort(-table(todas$Fachada2)))[1]
todas$Fachada1 <- as.factor(todas$Fachada1)
todas$Fachada2 <- as.factor(todas$Fachada2)
todas$QualidadeFachada <- as.integer(revalue(todas$QualidadeFachada, Qualidades))## The following `from` values were not present in `x`: None, Po
##
## 2 3 4 5
## 35 1798 979 107
## The following `from` values were not present in `x`: None
##
## 1 2 3 4 5
## 3 67 2538 299 12
Atribuído o valor mais comum
todas$SistemaEletrico[is.na(todas$SistemaEletrico)] <- names(sort(-table(todas$SistemaEletrico)))[1]
todas$SistemaEletrico <- as.factor(todas$SistemaEletrico)
table(todas$SistemaEletrico)##
## FuseA FuseF FuseP Mix SBrkr
## 188 50 8 1 2672
Atribuído o valor mais comum
todas$TipoVenda[is.na(todas$TipoVenda)] <- names(sort(-table(todas$TipoVenda)))[1]
todas$TipoVenda <- as.factor(todas$TipoVenda)
table(todas$TipoVenda)##
## COD Con ConLD ConLI ConLw CWD New Oth WD
## 87 5 26 9 8 12 239 7 2526
##
## Abnorml AdjLand Alloca Family Normal Partial
## 190 12 24 46 2402 245
Todos os valores NA foram investigados e substituídos.
NAcol <- which(colSums(is.na(todas)) > 0) # quais colunas tem NA
sort(colSums(sapply(todas[NAcol], is.na)), decreasing = TRUE) # somando quantidade de NA e ordenando## PrecoVenda
## 1459
## Existem 1 colunas com valores missing
categoricas <- names(todas[,sapply(todas,is.character)])
cat('Existem', length(categoricas), 'colunas com valor char')## Existem 15 colunas com valor char
As variáveis a seguir foram investigadas e nenhum tipo de ordinalidade foi evidenciada. Portanto será transformada apenas de texto (char) para categoria (fator).
##
## BrkTil CBlock PConc Slab Stone Wood
## 311 1235 1308 49 11 5
##
## Floor GasA GasW Grav OthW Wall
## 1 2874 27 9 2 6
##
## Flat Gable Gambrel Hip Mansard Shed
## 20 2310 22 551 11 5
##
## ClyTile CompShg Membran Metal Roll Tar&Grv WdShake WdShngl
## 1 2876 1 1 1 23 9 7
##
## Bnk HLS Low Lvl
## 117 120 60 2622
##
## 1Fam 2fmCon Duplex Twnhs TwnhsE
## 2425 62 109 96 227
##
## 1.5Fin 1.5Unf 1Story 2.5Fin 2.5Unf 2Story SFoyer SLvl
## 314 19 1471 8 24 872 83 128
##
## Blmngtn Blueste BrDale BrkSide ClearCr CollgCr Crawfor Edwards Gilbert IDOTRR
## 28 10 30 108 44 267 103 194 165 93
## MeadowV Mitchel NAmes NoRidge NPkVill NridgHt NWAmes OldTown Sawyer SawyerW
## 37 114 443 71 23 166 131 239 151 125
## Somerst StoneBr SWISU Timber Veenker
## 182 51 48 72 24
##
## Artery Feedr Norm PosA PosN RRAe RRAn RRNe RRNn
## 92 164 2511 20 39 28 50 6 9
##
## Artery Feedr Norm PosA PosN RRAe RRAn RRNn
## 5 13 2889 4 4 1 1 2
As seguintes variáveis possuem ordinalidade, ou informada na documentação ou evidenciada ao investigar o impacto no Preço de Venda e o seu significado. Todas foram transformadas em numéricas por atribuição de valores.
todas$CondicaoAquecimento <- as.integer(revalue(todas$CondicaoAquecimento, Qualidades))
table(todas$CondicaoAquecimento)##
## 1 2 3 4 5
## 3 92 857 474 1493
##
## 0 1
## 196 2723
todas$Declive <- as.integer(revalue(todas$Declive, c('Sev'=0, 'Mod'=1, 'Gtl'=2)))
table(todas$Declive)##
## 0 1 2
## 16 125 2778
todas$TipoEstrada <- as.integer(revalue(todas$TipoEstrada, c('Grvl'=0, 'Pave'=1)))
table(todas$TipoEstrada)##
## 0 1
## 12 2907
todas$PavimEntrada <- as.integer(revalue(todas$PavimEntrada, c('N'=0, 'P'=1, 'Y'=2)))
table(todas$PavimEntrada)##
## 0 1 2
## 216 62 2641
Verificando se algumas variáveis numéricas (num ou int) na verdade são categorias (fator).
## Rows: 2,919
## Columns: 80
## $ Id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1...
## $ Classe <int> 60, 20, 60, 70, 60, 50, 20, 60, 50, 190, 20,...
## $ Zona <fct> RL, RL, RL, RL, RL, RL, RL, RL, RM, RL, RL, ...
## $ DimFrontal <int> 65, 80, 68, 60, 84, 85, 75, 80, 51, 50, 70, ...
## $ AreaLote <int> 8450, 9600, 11250, 9550, 14260, 14115, 10084...
## $ TipoEstrada <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
## $ TipoRua <fct> None, None, None, None, None, None, None, No...
## $ RelevoLote <int> 3, 3, 2, 2, 2, 2, 3, 2, 3, 3, 3, 2, 1, 2, 2,...
## $ GreideLote <fct> Lvl, Lvl, Lvl, Lvl, Lvl, Lvl, Lvl, Lvl, Lvl,...
## $ ImplantacaoLote <fct> Inside, FR2, Inside, Corner, FR2, Inside, In...
## $ Declive <int> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ Bairro <fct> CollgCr, Veenker, CollgCr, Crawfor, NoRidge,...
## $ Proximidade1 <fct> Norm, Feedr, Norm, Norm, Norm, Norm, Norm, P...
## $ Proximidade2 <fct> Norm, Norm, Norm, Norm, Norm, Norm, Norm, No...
## $ TipoHabitacao <fct> 1Fam, 1Fam, 1Fam, 1Fam, 1Fam, 1Fam, 1Fam, 1F...
## $ Pavimentos <fct> 2Story, 1Story, 2Story, 2Story, 2Story, 1.5F...
## $ QualidadeTotal <int> 7, 6, 7, 7, 8, 5, 8, 7, 7, 5, 5, 9, 5, 7, 6,...
## $ CondicaoTotal <int> 5, 8, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 6, 5, 5,...
## $ AnoConstrucao <int> 2003, 1976, 2001, 1915, 2000, 1993, 2004, 19...
## $ AnoRetrofit <int> 2003, 1976, 2002, 1970, 2000, 1995, 2005, 19...
## $ TipoCobertura <fct> Gable, Gable, Gable, Gable, Gable, Gable, Ga...
## $ MaterialCobertura <fct> CompShg, CompShg, CompShg, CompShg, CompShg,...
## $ Fachada1 <fct> VinylSd, MetalSd, VinylSd, Wd Sdng, VinylSd,...
## $ Fachada2 <fct> VinylSd, MetalSd, VinylSd, Wd Shng, VinylSd,...
## $ TipoAlvenaria <int> 1, 0, 1, 0, 1, 0, 2, 2, 0, 0, 0, 2, 0, 2, 1,...
## $ AreaAlvenaria <dbl> 196, 0, 162, 0, 350, 0, 186, 240, 0, 0, 0, 2...
## $ QualidadeFachada <int> 4, 3, 4, 3, 4, 3, 4, 3, 3, 3, 3, 5, 3, 4, 3,...
## $ CondicaoFachada <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,...
## $ Fundacao <fct> PConc, CBlock, PConc, BrkTil, PConc, Wood, P...
## $ AlturaPorao <int> 4, 4, 4, 3, 4, 4, 5, 4, 3, 3, 3, 5, 3, 4, 3,...
## $ CondicaoPorao <int> 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,...
## $ ExposicaoPorao <int> 1, 4, 2, 1, 3, 1, 3, 2, 1, 1, 1, 1, 1, 3, 1,...
## $ RevestimentoPorao1 <int> 6, 5, 6, 5, 6, 6, 6, 5, 1, 6, 3, 6, 5, 1, 4,...
## $ AreaPoraoAcabado1 <dbl> 706, 978, 486, 216, 655, 732, 1369, 859, 0, ...
## $ RevestimentoPorao2 <int> 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,...
## $ AreaPoraoAcabado2 <dbl> 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0...
## $ AreaPoraoInacab <dbl> 150, 284, 434, 540, 490, 64, 317, 216, 952, ...
## $ AreaTotalPorao <dbl> 856, 1262, 920, 756, 1145, 796, 1686, 1107, ...
## $ Aquecimento <fct> GasA, GasA, GasA, GasA, GasA, GasA, GasA, Ga...
## $ CondicaoAquecimento <int> 5, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 3, 5, 3,...
## $ ArCentral <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
## $ SistemaEletrico <fct> SBrkr, SBrkr, SBrkr, SBrkr, SBrkr, SBrkr, SB...
## $ AreaTerreo <int> 856, 1262, 920, 961, 1145, 796, 1694, 1107, ...
## $ Area1Pav <int> 854, 0, 866, 756, 1053, 566, 0, 983, 752, 0,...
## $ AreaAcabBaixaQualTotal <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ AreaVivenciaAcimaRua <int> 1710, 1262, 1786, 1717, 2198, 1362, 1694, 20...
## $ BanheirosPorao <dbl> 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,...
## $ LavaboPorao <dbl> 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ BanheirosAcimaRua <int> 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 1, 3, 1, 2, 1,...
## $ LavaboAcimaRua <int> 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1,...
## $ QuartosAcimaRua <int> 3, 3, 3, 3, 4, 1, 3, 3, 2, 2, 3, 4, 2, 3, 2,...
## $ CozinhasAcimaRua <int> 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1,...
## $ QualidadeCozinha <int> 4, 3, 4, 4, 4, 3, 4, 3, 3, 3, 3, 5, 3, 4, 3,...
## $ ComodosAcimarua <int> 8, 6, 6, 7, 9, 5, 7, 7, 8, 5, 5, 11, 4, 7, 5...
## $ Descontos <int> 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7,...
## $ Lareiras <int> 0, 1, 1, 1, 1, 0, 1, 2, 2, 2, 0, 2, 0, 1, 1,...
## $ QualidadeLareira <int> 0, 3, 3, 4, 3, 0, 4, 3, 3, 3, 0, 4, 0, 4, 2,...
## $ TipoGaragem <fct> Attchd, Attchd, Attchd, Detchd, Attchd, Attc...
## $ AnoGaragem <int> 2003, 1976, 2001, 1998, 2000, 1993, 2004, 19...
## $ AcabamentoGaragem <int> 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 3, 1, 2, 2,...
## $ VagasGaragem <dbl> 2, 2, 2, 3, 3, 2, 2, 2, 2, 1, 1, 3, 1, 3, 1,...
## $ AreaGaragem <dbl> 548, 460, 608, 642, 836, 480, 636, 484, 468,...
## $ QualiGaragem <int> 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 3, 3, 3, 3, 3,...
## $ CondicaoGaragem <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,...
## $ PavimEntrada <int> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ AreaDeck <int> 0, 298, 0, 0, 192, 40, 255, 235, 90, 0, 0, 1...
## $ AreaVarandaAberta <int> 61, 0, 42, 35, 84, 30, 57, 204, 0, 4, 0, 21,...
## $ AreaVarandaFechada <int> 0, 0, 0, 272, 0, 0, 0, 228, 205, 0, 0, 0, 0,...
## $ AreaVaranda3Sea <int> 0, 0, 0, 0, 0, 320, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ AreaVarandaScreen <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 0, ...
## $ AreaPiscina <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ QualiPiscina <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ QualiCerca <fct> None, None, None, None, None, MnPrv, None, N...
## $ OutrosItens <fct> None, None, None, None, None, Shed, None, Sh...
## $ ValorItens <int> 0, 0, 0, 0, 0, 700, 0, 350, 0, 0, 0, 0, 0, 0...
## $ MesVenda <int> 2, 5, 9, 2, 12, 10, 8, 11, 4, 1, 2, 7, 9, 8,...
## $ AnoVenda <int> 2008, 2007, 2008, 2006, 2008, 2009, 2007, 20...
## $ TipoVenda <fct> WD, WD, WD, WD, WD, WD, WD, WD, WD, WD, WD, ...
## $ CondicaoVenda <fct> Normal, Normal, Normal, Abnorml, Normal, Nor...
## $ PrecoVenda <int> 208500, 181500, 223500, 140000, 250000, 1430...
Pode ser observado duas incongruências: o ano faz sentido ser numérico (inteiro), contudo o ano é melhor que seja categórico, pois dezembro não é maior que novembro, por exemplo.
ys <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(AnoVenda), y=PrecoVenda)) +
geom_bar(stat='summary', fun = "median", fill='chartreuse3')+
scale_y_continuous(breaks= seq(0, 800000, by=25000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..)) +
coord_cartesian(ylim = c(0, 200000)) +
stat_summary(fun="mean", color="navyblue")+
geom_hline(yintercept=163000, linetype="dashed", color = "red") #linha tracejada é a mediana do preço de venda
ms <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(MesVenda), y=PrecoVenda)) +
geom_bar(stat='summary', fun = "median", fill='chartreuse3')+
scale_y_continuous(breaks= seq(0, 800000, by=25000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..)) +
coord_cartesian(ylim = c(0, 200000)) +
stat_summary(fun="mean", color="navyblue")+
geom_hline(yintercept=163000, linetype="dashed", color = "red") #linha tracejada é a mediana do preço de venda
grid.arrange(ys, ms, widths=c(1,2))Da mesma forma, a variável classe veio como numérica, mas na verdade cada número significa uma categoria.
##
## 20 30 40 45 50 60 70 75 80 85 90 120 150 160 180 190
## 1079 139 6 18 287 575 128 23 118 48 109 182 1 128 17 61
todas$Classe <- revalue(todas$Classe, c('20'='1 story 1946+', '30'='1 story 1945-', '40'='1 story unf attic',
'45'='1,5 story unf', '50'='1,5 story fin', '60'='2 story 1946+',
'70'='2 story 1945-', '75'='2,5 story all ages', '80'='split/multi level',
'85'='split foyer', '90'='duplex all style/age', '120'='1 story PUD 1946+',
'150'='1,5 story PUD all', '160'='2 story PUD 1946+', '180'='PUD multilevel',
'190'='2 family conversion'))
table(todas$Classe)##
## 1 story 1946+ 1 story 1945- 1 story unf attic
## 1079 139 6
## 1,5 story unf 1,5 story fin 2 story 1946+
## 18 287 575
## 2 story 1945- 2,5 story all ages split/multi level
## 128 23 118
## split foyer duplex all style/age 1 story PUD 1946+
## 48 109 182
## 1,5 story PUD all 2 story PUD 1946+ PUD multilevel
## 1 128 17
## 2 family conversion
## 61
Realizando a mesma análise da secão 3, com as novas variáveis numéricas.
numericVarsFin <- which(sapply(todas, is.numeric))
numericVarNamesFin <- names(numericVarsFin) # salvando os titulos como vetor
all_numericasFin <- todas[, numericVarsFin] # subset somente das numéricas
cor_numericasFin <- cor(all_numericasFin, use="pairwise.complete.obs") # correlações entre as numericas
cor_ordenadaFin <- as.matrix(sort(cor_numericasFin[,'PrecoVenda'], decreasing = TRUE)) #ordenando de forma decrescente
# Selecionando as altas, retornando para a matriz e plotado
cor_altaFin<- names(which(apply(cor_ordenadaFin, 1, function(x) abs(x)>0.5)))
cor_principaisnumFin <- cor_numericasFin[cor_altaFin, cor_altaFin]
corrplot.mixed(cor_principaisnumFin, tl.col="black", tl.pos = "lt")A primeira matriz tinha 10 variáveis com correlação maior que 0,5 com o Preço de Venda. Agora, existem 16 variáveis com este nível de correlação
Para uma análise mais profunda, será executado um algoritmo de classificação Random Forest com apenas 100 árvores para avaliar a importância de cada variável preditora no Preço de Venda.
O algoritmo entre 2 valores de imporância: o erro médio quadrado ao permutar aleatoriamente as variáveis e a pureza que aquela variável fornece ao conjunto. Com isso é possível criar um ranking de importância.
set.seed(2020)
RF_rapido <- randomForest(x=todas[1:1460,-80], y=todas$PrecoVenda[1:1460], ntree=100,importance=TRUE)
imp_RF <- importance(RF_rapido)
imp_DF <- data.frame(Variables = row.names(imp_RF), MSE = imp_RF[,1])
imp_DF2 <- data.frame(Variables = row.names(imp_RF), nodepurity = imp_RF[,2])
imp_DF <- imp_DF[order(imp_DF$MSE, decreasing = TRUE),]
imp_DF2 <- imp_DF2[order(imp_DF2$nodepurity, decreasing = TRUE),]
imp1 <- ggplot(imp_DF[1:20,], aes(x=reorder(Variables, MSE), y=MSE, fill=MSE)) + geom_bar(stat = 'identity') +
labs(x = 'Variáveis', y= '% de aumento no MSE se as variáveis forem permutadas randomicamente') + coord_flip() +
theme(legend.position="none")
imp2 <- ggplot(imp_DF2[1:20,], aes(x=reorder(Variables, nodepurity), y=nodepurity, fill=nodepurity)) + geom_bar(stat = 'identity') +
labs(x = 'Variáveis', y= 'Node Purity') + coord_flip() +
theme(legend.position="none")
grid.arrange(imp1, imp2, widths=c(1,1))Iremos considerar a importância com base no erro médio quadrático (MSE). Com isso, percebemos ligeiras diferenças entre a ordem vista na matriz de correlação. Este dado é de extrema importância para conhecimento organizacional do produto ou serviço, pois pode orientar e otimizar investimento de recursos e tempo nas variáveis mais importantes para uma variável-alvo escolhida (neste caso o Preço de Venda).
Tendo isso em vista, será realizada uma Análise Exploratória de Dados superficial para verificar se existe alguma relação clara entre as variáveis.
s1 <- ggplot(todas, aes(x=AreaVivenciaAcimaRua)) +
geom_density(fill='#418fde', size=0) + labs(x='Área privativa acima do nível da rua')
s2 <- ggplot(todas, aes(x=as.factor(ComodosAcimarua))) +
geom_histogram(stat='count', fill='#418fde') + labs(x='Cômodos acima do nível da rua')
s3 <- ggplot(todas, aes(x=AreaTerreo)) +
geom_density(fill='#418fde', size=0) + labs(x='Área Primeiro Pavimento')
s4 <- ggplot(todas, aes(x=Area1Pav)) +
geom_density(fill='#418fde', size=0) + labs(x='Área Segundo Pavimento')
s5 <- ggplot(todas, aes(x=AreaTotalPorao)) +
geom_density(fill='#418fde', size=0) + labs(x='Área Porão')
s6 <- ggplot(todas, aes(x=AreaLote)) +
geom_density(fill='#418fde', size=0) + labs(x='Área do Lote')
s7 <- ggplot(todas, aes(x=DimFrontal)) +
geom_density(fill='#418fde', size=0) + labs(x='Dimensão frontal do lote')
s8 <- ggplot(todas, aes(x=AreaAcabBaixaQualTotal)) +
geom_histogram(fill='#418fde', size=0) + labs(x='Área total com acabamento de baixa qualidade')
layout <- matrix(c(1,2,5,3,4,8,6,7),4,2,byrow=TRUE)
multiplot(s1, s2, s3, s4, s5, s6, s7, s8, layout=layout)##
## 0 53 80 120 144 156 205 232 234 360 371 384 390 392 397 420
## 1434 1 3 1 1 1 1 1 1 2 1 1 1 1 1 1
## 473 479 481 513 514 515 528 572
## 1 1 1 1 1 1 1 1
Observa-se que a Área privativa acima do nível da rua AreaVivenciaAcimaRua é - provavelmente - uma combinação das variáveis: AreaTérreo, Area1Pav e AreaAcabBaixaQualTotal (que pouquissimas casas possuem).
Para confirmar esta hipótese, será calculada a correlação da variável AreaVivenciaAcimaRua com a soma das outras 3 variáveis.
## [1] 1
1 representa uma correlação perfeita. Esta informação será útil para a etapa de Feature Engineering, onde descartaremos as 3 variáveis já contempladas em AreaVivenciaAcimaRua evitando a multicolinearidade de parâmetros.
bairros1 <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=Bairro, y=PrecoVenda)) +
geom_bar(stat='summary', fun = "median", fill='navyblue') +
stat_summary(fun="mean", color="chartreuse3")+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..), size=3) +
geom_hline(yintercept=163000, linetype="dashed", color = "red") #mediana todal do precovenda
bairros2 <- ggplot(todas, aes(x=Bairro)) +
geom_histogram(stat='count', fill='navyblue')+
geom_label(stat = "count", aes(label = ..count.., y = ..count..), size=3)+
theme(axis.text.x = element_text(angle = 45, hjust = 1))
grid.arrange(bairros1, bairros2)q1 <- ggplot(todas, aes(x=as.factor(QualidadeTotal))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade Total')
q2 <- ggplot(todas, aes(x=as.factor(QualidadeFachada))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade Fachada')
q3 <- ggplot(todas, aes(x=as.factor(AlturaPorao))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade Porão')
q4 <- ggplot(todas, aes(x=as.factor(QualidadeCozinha))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade Cozinha')
q5 <- ggplot(todas, aes(x=as.factor(QualiGaragem))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade Garagem')
q6 <- ggplot(todas, aes(x=as.factor(QualidadeLareira))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade Lareira')
q7 <- ggplot(todas, aes(x=as.factor(QualiPiscina))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade Piscina')
layout <- matrix(c(1,2,8,3,4,8,5,6,7),3,3,byrow=TRUE)
multiplot(q1, q2, q3, q4, q5, q6, q7, layout=layout)classes1 <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=Classe, y=PrecoVenda)) +
geom_bar(stat='summary', fun = "median", fill='chartreuse3') +
stat_summary(fun="mean", color= "navy")+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..), size=3) +
geom_hline(yintercept=163000, linetype="dashed", color = "red") #mediana todal do precovenda
classes2 <- ggplot(todas, aes(x=Classe)) +
geom_histogram(stat='count', fill='chartreuse3')+
geom_label(stat = "count", aes(label = ..count.., y = ..count..), size=3)+
theme(axis.text.x = element_text(angle = 45, hjust = 1))
grid.arrange(classes1, classes2)g1 <- ggplot(todas[todas$VagasGaragem!=0,], aes(x=AnoGaragem)) +
geom_histogram(fill='#418fde') + labs(x='Ano de construção')
g2 <- ggplot(todas, aes(x=as.factor(VagasGaragem))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Quantidade de vagas')
g3 <- ggplot(todas, aes(x=AreaGaragem)) +
geom_density(fill='#418fde', size=0) + labs(x='Area da garagem')
g4 <- ggplot(todas, aes(x=as.factor(CondicaoGaragem))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Condição')
g5 <- ggplot(todas, aes(x=TipoGaragem)) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Tipo da Garagem')
g6 <- ggplot(todas, aes(x=as.factor(QualiGaragem))) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Qualidade da garagem')
g7 <- ggplot(todas, aes(x=AcabamentoGaragem)) +
geom_histogram(stat='count', fill='#418fde', size=0) + labs(x='Acabamento da garagem')
layout <- matrix(c(1,5,5,2,3,8,6,4,7),3,3,byrow=TRUE)
multiplot(g1, g2, g3, g4, g5, g6, g7, layout=layout)Existem muitas variáveis relacionadas à garagem, inclusive com alta correlação entre si. Pode ser interessante elimitar algumas.
Outro fator interessante é a escala do histograma do ano de construção da garagem. Provavelmente há algum erro de digitação em um dado puxando o eixo X gráfico para volta do ano 2200 mas que nao da pra ver na escala.
## Id AnoGaragem AnoConstrucao
## 2593 2593 2207 2006
Considerando o ano de construção, o ano da garagem foi corrigido para 2007.
b1 <- ggplot(todas, aes(x=AreaPoraoAcabado1)) +
geom_histogram(fill='#418fde') + labs(x='Area acabada com revest 1')
b2 <- ggplot(todas, aes(x=AreaPoraoAcabado2)) +
geom_histogram(fill='#418fde') + labs(x='Area acabada com revest 2')
b3 <- ggplot(todas, aes(x=AreaPoraoInacab)) +
geom_histogram(fill='#418fde') + labs(x='Area sem revestimento')
b4 <- ggplot(todas, aes(x=RevestimentoPorao1)) +
geom_histogram(stat='count', fill='#418fde') + labs(x='Tipo de revestimento 1')+
scale_x_continuous(breaks=c(0,1,2,3,4,5))
b5 <- ggplot(todas, aes(x=RevestimentoPorao2)) +
geom_histogram(stat='count', fill='#418fde') + labs(x='Tipo de revestimento 2')+
scale_x_continuous(breaks=c(0,1,2,3,4,5))
b6 <- ggplot(todas, aes(x=as.factor(AlturaPorao))) +
geom_histogram(stat='count', fill='#418fde') + labs(x='Altura do Porão')
b7 <- ggplot(todas, aes(x=as.factor(CondicaoPorao))) +
geom_histogram(stat='count', fill='#418fde') + labs(x='Condição do Porão')
b8 <- ggplot(todas, aes(x=as.factor(ExposicaoPorao))) +
geom_histogram(stat='count', fill='#418fde') + labs(x='Exposição do porão')
layout <- matrix(c(1,2,3,4,5,9,6,7,8),3,3,byrow=TRUE)
multiplot(b1, b2, b3, b4, b5, b6, b7, b8, layout=layout)Tal qual as variáveis de área, suspeita-se que a variável de área total do porão (já plotada na seçao de áreas) seja a soma das áreas AreaPoraoAcabado1, AreaPoraoAcabado2 e AreaPoraoInacab.
## [1] 1
A correlação perfeita confirma a hipótese.
Nesta etapa serão avaliadas a inserção, substituição e descarte de algumas variáveis no modelo preditivo.
É valido lembrar que até aqui toda a etapa de Análise Exploratória de Dados (EDA) é fundamental para análises descritivas e diagnósticas, gerando conhecimento organizacional para a empresa. Deste momento em diante, o intuito é preparar os dados para uma melhor modelarem matemática da realidade por meio dos algoritmos de inteligência artificial.
Portanto, pode-se considerar um segundo produto com diferentes objetivos: prever o preço de venda de imóveis a partir dos parâmetros selecionados por esta etapa.
Existe uma grande quantidade de variáveis relacionadas a banheiros e que não apresentam importância isoladas. Desta forma, serão unidas em uma única variável para avaliar sua relevância.
Cada lavabo será considerado meio banheiro (conceito estadunidense de half-bathroom, onde existe apenas 3 itens - geralmente sem o chuveiro) e cada banheiro um “full bathroom”. Assim, será criada a variável TotalBanheiros e plotada em relação ao Preço de Venda.
todas$TotalBanheiros <- todas$BanheirosAcimaRua + todas$BanheirosPorao + (todas$LavaboPorao*0.5) + (todas$LavaboAcimaRua*0.5)
tb1 <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(TotalBanheiros), y=PrecoVenda))+
geom_point(col='navy') + geom_smooth(method = "lm", color="chartreuse3", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)
tb2 <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(TotalBanheiros), y=PrecoVenda))+
geom_point(col='navy') + geom_smooth(method = "loess", color="chartreuse3", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)
tb3 <- ggplot(todas, aes(x=as.factor(TotalBanheiros))) +
geom_histogram(stat='count', fill='#418fde')
grid.arrange(tb1, tb2, tb3)Tratando-se de variáveis temporais, uma que chama atenção é a variável Retrofit (Remodel no conjunto original). Para avaliar sua relação, será criado uma variavel binária para casos em que houve retrofit ou não (0-não houve, 1-houve).
Também será avaliado a idade todal da edificação, sendo (ano da venda - ano do retrofit). Nos casos em que não há retrofit, o ano preenchido para o retrofit é o mesmo da construção, o que não gerará problemas.
# criando novas colunas / variáveis
todas$Retrofit <- ifelse(todas$AnoConstrucao==todas$AnoRetrofit, 0, 1)
todas$idade <- as.numeric(todas$AnoVenda)-todas$AnoRetrofitggplot(todas[!is.na(todas$PrecoVenda),], aes(x=idade, y=PrecoVenda))+
geom_point(col='chartreuse3') + geom_smooth(method = "lm", color="navy", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)## `geom_smooth()` using formula 'y ~ x'
## [1] -0.5090787
Como esperado, há uma correlação negativa entre a idade do imóvel e seu preço de venda
Avaliando se o retrofit impacta no preço:
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(Retrofit), y=PrecoVenda)) +
geom_bar(stat='summary', fun = "median", fill='navyblue') +
geom_label(stat = "count", aes(label = ..count.., y = ..count..), size=6) +
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
theme_grey(base_size = 18) +
geom_hline(yintercept=163000, linetype="dashed")+
stat_summary(fun="mean", color='chartreuse3')Sim, impacta negativamente. Lembrando que a linha tracejada é a mediana dos preços de venda, o ponto verde a média do preço de venda de cada categoria e a altura da barra a mediana.
Será criada uma nova variável binária: se a cara foi vendida nova:
todas$vendidanova <- ifelse(todas$AnoVenda==todas$AnoConstrucao, 1, 0)
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=as.factor(vendidanova), y=PrecoVenda)) +
geom_bar(stat='summary', fun = "median", fill='chartreuse3') +
geom_label(stat = "count", aes(label = ..count.., y = ..count..), size=6) +
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
theme_grey(base_size = 18) +
geom_hline(yintercept=163000, linetype="dashed")+
stat_summary(fun="mean", color= "navy")Observa-se, como esperado, um impacto significativo no preço de venda.
Como já observado, existe uma grande variação do preço de venda de acordo com o bairro. Apesar de não existir ordinalidade, esta relação não pode ser descartada.
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=reorder(Bairro, PrecoVenda, FUN=median), y=PrecoVenda)) +
geom_bar(stat='summary', fun = "median", fill='navy') + labs(x='Bairro', y='Mediana Preço de Venda') +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_y_continuous(breaks= seq(0, 800000, by=50000), labels = comma) +
geom_label(stat = "count", aes(label = ..count.., y = ..count..), size=3) +
stat_summary(fun="mean", color= "chartreuse3") +
geom_hline(yintercept=163000, linetype="dashed", color = "red")Para isso, será considerado 3 diferentes categorias: 0, 1 e 2 onde a mediana sofre alterações mais visíveis.
Serão descartadas as variáveis relacionadas às áreas multicolineares e consideradas apenas a AreaVivenciaAcimaRua e AreaTotalPorão, que serão somadas em uma única variável AreaTotal.
todas$areatotal <- todas$AreaVivenciaAcimaRua + todas$AreaTotalPorao
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=areatotal, y=PrecoVenda))+
geom_point(col='chartreuse3') + geom_smooth(method = "lm", color="navy", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma) +
geom_text_repel(aes(label = ifelse(todas$AreaVivenciaAcimaRua[!is.na(todas$PrecoVenda)]>4000, rownames(todas), '')))## [1] 0.7789588
A relação, como esperado, é ainda mais acentuada que a análise preliminar realizada apenas com AreaVivenciaAcimaRua.
A correlaçào será reavaliada sem os 2 ouliers abaixo da regressão.
## [1] 0.829042
todas <- todas[-c(524,1299),]
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=areatotal, y=PrecoVenda))+
geom_point(col='navy') + geom_smooth(method = "lm", color="chartreuse3", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma) +
geom_text_repel(aes(label = ifelse(todas$AreaVivenciaAcimaRua[!is.na(todas$PrecoVenda)]>4000, rownames(todas), '')))## `geom_smooth()` using formula 'y ~ x'
Bem melhor, a correlação aumentou de 0,79 para 0,83.
Por definição dos parâmetros, existem 4 variáveis para área de varanda que sozinhas não imactam de forma significativa no preço de venda. As áreas serão somadas em uma nova variável para avaliar a correlação conjunta.
todas$areatotalvaranda <- (todas$AreaVarandaAberta + todas$AreaVarandaFechada + todas$AreaVarandaScreen + todas$AreaVaranda3Sea)
v1 <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=AreaVarandaAberta, y=PrecoVenda))+
geom_point(col='chartreuse3') + geom_smooth(method = "lm", color="navy", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)
cor(todas$PrecoVenda, todas$AreaVarandaAberta, use= "pairwise.complete.obs")## [1] 0.3211424
v2 <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=AreaVarandaFechada , y=PrecoVenda))+
geom_point(col='chartreuse3') + geom_smooth(method = "lm", color="navy", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)
cor(todas$PrecoVenda, todas$AreaVarandaFechada, use= "pairwise.complete.obs")## [1] -0.1286456
v3 <- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=AreaVarandaScreen, y=PrecoVenda))+
geom_point(col='chartreuse3') + geom_smooth(method = "lm", color="navy", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)
cor(todas$PrecoVenda, todas$AreaVarandaScreen, use= "pairwise.complete.obs")## [1] 0.111415
v4<- ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=AreaVaranda3Sea, y=PrecoVenda))+
geom_point(col='chartreuse3') + geom_smooth(method = "lm", color="navy", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)
cor(todas$PrecoVenda, todas$AreaVaranda3Sea, use= "pairwise.complete.obs")## [1] 0.044568
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'
ggplot(todas[!is.na(todas$PrecoVenda),], aes(x=areatotalvaranda, y=PrecoVenda))+
geom_point(col='navy') + geom_smooth(method = "lm", color="chartreuse3", aes(group=1)) +
scale_y_continuous(breaks= seq(0, 800000, by=100000), labels = comma)## `geom_smooth()` using formula 'y ~ x'
## [1] 0.196875
Apesar de tudo, correlação não significativa.
Nesta etapa serão descartadas as variáveis escolhidas e divididas entre numéricas e fatores. As variáveis descartadas foram: AnoRetrofit, AnoGaragem, ÁreaGaragem, CondicaoGaragem,AreaTotalPorao, ComodosAcimarua, AreaPoraoAcabado1.
variaveisdescartadas <- c('AnoRetrofit','AnoGaragem', 'AreaGaragem', 'CondicaoGaragem', 'AreaTotalPorao', 'ComodosAcimarua', 'AreaPoraoAcabado1')
todas <- todas[,!(names(todas) %in% variaveisdescartadas)]
numericVarNames<- numericVarNames[!(numericVarNames %in% c('Classe', 'MesVenda', 'AnoVenda', 'PrecoVenda', 'QualidadeTotal', 'CondicaoTotal'))] #numericVarNames was created before having done anything
numericVarNames <- append(numericVarNames, c('idade', 'areatotalvaranda', 'TotalBanheiros', 'areatotal'))
glimpse(todas)## Rows: 2,917
## Columns: 80
## $ Id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1...
## $ Classe <fct> "2 story 1946+", "1 story 1946+", "2 story 1...
## $ Zona <fct> RL, RL, RL, RL, RL, RL, RL, RL, RM, RL, RL, ...
## $ DimFrontal <int> 65, 80, 68, 60, 84, 85, 75, 80, 51, 50, 70, ...
## $ AreaLote <int> 8450, 9600, 11250, 9550, 14260, 14115, 10084...
## $ TipoEstrada <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
## $ TipoRua <fct> None, None, None, None, None, None, None, No...
## $ RelevoLote <int> 3, 3, 2, 2, 2, 2, 3, 2, 3, 3, 3, 2, 1, 2, 2,...
## $ GreideLote <fct> Lvl, Lvl, Lvl, Lvl, Lvl, Lvl, Lvl, Lvl, Lvl,...
## $ ImplantacaoLote <fct> Inside, FR2, Inside, Corner, FR2, Inside, In...
## $ Declive <int> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ Bairro <fct> CollgCr, Veenker, CollgCr, Crawfor, NoRidge,...
## $ Proximidade1 <fct> Norm, Feedr, Norm, Norm, Norm, Norm, Norm, P...
## $ Proximidade2 <fct> Norm, Norm, Norm, Norm, Norm, Norm, Norm, No...
## $ TipoHabitacao <fct> 1Fam, 1Fam, 1Fam, 1Fam, 1Fam, 1Fam, 1Fam, 1F...
## $ Pavimentos <fct> 2Story, 1Story, 2Story, 2Story, 2Story, 1.5F...
## $ QualidadeTotal <int> 7, 6, 7, 7, 8, 5, 8, 7, 7, 5, 5, 9, 5, 7, 6,...
## $ CondicaoTotal <int> 5, 8, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 6, 5, 5,...
## $ AnoConstrucao <int> 2003, 1976, 2001, 1915, 2000, 1993, 2004, 19...
## $ TipoCobertura <fct> Gable, Gable, Gable, Gable, Gable, Gable, Ga...
## $ MaterialCobertura <fct> CompShg, CompShg, CompShg, CompShg, CompShg,...
## $ Fachada1 <fct> VinylSd, MetalSd, VinylSd, Wd Sdng, VinylSd,...
## $ Fachada2 <fct> VinylSd, MetalSd, VinylSd, Wd Shng, VinylSd,...
## $ TipoAlvenaria <int> 1, 0, 1, 0, 1, 0, 2, 2, 0, 0, 0, 2, 0, 2, 1,...
## $ AreaAlvenaria <dbl> 196, 0, 162, 0, 350, 0, 186, 240, 0, 0, 0, 2...
## $ QualidadeFachada <int> 4, 3, 4, 3, 4, 3, 4, 3, 3, 3, 3, 5, 3, 4, 3,...
## $ CondicaoFachada <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,...
## $ Fundacao <fct> PConc, CBlock, PConc, BrkTil, PConc, Wood, P...
## $ AlturaPorao <int> 4, 4, 4, 3, 4, 4, 5, 4, 3, 3, 3, 5, 3, 4, 3,...
## $ CondicaoPorao <int> 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,...
## $ ExposicaoPorao <int> 1, 4, 2, 1, 3, 1, 3, 2, 1, 1, 1, 1, 1, 3, 1,...
## $ RevestimentoPorao1 <int> 6, 5, 6, 5, 6, 6, 6, 5, 1, 6, 3, 6, 5, 1, 4,...
## $ RevestimentoPorao2 <int> 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,...
## $ AreaPoraoAcabado2 <dbl> 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0...
## $ AreaPoraoInacab <dbl> 150, 284, 434, 540, 490, 64, 317, 216, 952, ...
## $ Aquecimento <fct> GasA, GasA, GasA, GasA, GasA, GasA, GasA, Ga...
## $ CondicaoAquecimento <int> 5, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 3, 5, 3,...
## $ ArCentral <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
## $ SistemaEletrico <fct> SBrkr, SBrkr, SBrkr, SBrkr, SBrkr, SBrkr, SB...
## $ AreaTerreo <int> 856, 1262, 920, 961, 1145, 796, 1694, 1107, ...
## $ Area1Pav <int> 854, 0, 866, 756, 1053, 566, 0, 983, 752, 0,...
## $ AreaAcabBaixaQualTotal <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ AreaVivenciaAcimaRua <int> 1710, 1262, 1786, 1717, 2198, 1362, 1694, 20...
## $ BanheirosPorao <dbl> 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,...
## $ LavaboPorao <dbl> 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ BanheirosAcimaRua <int> 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 1, 3, 1, 2, 1,...
## $ LavaboAcimaRua <int> 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1,...
## $ QuartosAcimaRua <int> 3, 3, 3, 3, 4, 1, 3, 3, 2, 2, 3, 4, 2, 3, 2,...
## $ CozinhasAcimaRua <int> 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1,...
## $ QualidadeCozinha <int> 4, 3, 4, 4, 4, 3, 4, 3, 3, 3, 3, 5, 3, 4, 3,...
## $ Descontos <int> 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7,...
## $ Lareiras <int> 0, 1, 1, 1, 1, 0, 1, 2, 2, 2, 0, 2, 0, 1, 1,...
## $ QualidadeLareira <int> 0, 3, 3, 4, 3, 0, 4, 3, 3, 3, 0, 4, 0, 4, 2,...
## $ TipoGaragem <fct> Attchd, Attchd, Attchd, Detchd, Attchd, Attc...
## $ AcabamentoGaragem <int> 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 3, 1, 2, 2,...
## $ VagasGaragem <dbl> 2, 2, 2, 3, 3, 2, 2, 2, 2, 1, 1, 3, 1, 3, 1,...
## $ QualiGaragem <int> 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 3, 3, 3, 3, 3,...
## $ PavimEntrada <int> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ AreaDeck <int> 0, 298, 0, 0, 192, 40, 255, 235, 90, 0, 0, 1...
## $ AreaVarandaAberta <int> 61, 0, 42, 35, 84, 30, 57, 204, 0, 4, 0, 21,...
## $ AreaVarandaFechada <int> 0, 0, 0, 272, 0, 0, 0, 228, 205, 0, 0, 0, 0,...
## $ AreaVaranda3Sea <int> 0, 0, 0, 0, 0, 320, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ AreaVarandaScreen <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 0, ...
## $ AreaPiscina <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ QualiPiscina <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ QualiCerca <fct> None, None, None, None, None, MnPrv, None, N...
## $ OutrosItens <fct> None, None, None, None, None, Shed, None, Sh...
## $ ValorItens <int> 0, 0, 0, 0, 0, 700, 0, 350, 0, 0, 0, 0, 0, 0...
## $ MesVenda <fct> 2, 5, 9, 2, 12, 10, 8, 11, 4, 1, 2, 7, 9, 8,...
## $ AnoVenda <fct> 2008, 2007, 2008, 2006, 2008, 2009, 2007, 20...
## $ TipoVenda <fct> WD, WD, WD, WD, WD, WD, WD, WD, WD, WD, WD, ...
## $ CondicaoVenda <fct> Normal, Normal, Normal, Abnorml, Normal, Nor...
## $ PrecoVenda <int> 208500, 181500, 223500, 140000, 250000, 1430...
## $ TotalBanheiros <dbl> 3.5, 2.5, 3.5, 2.0, 3.5, 2.5, 3.0, 3.5, 2.0,...
## $ Retrofit <dbl> 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0,...
## $ idade <dbl> 5, 31, 6, 36, 8, 14, 2, 36, 58, 58, 43, 0, 4...
## $ vendidanova <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ bairrosricos <dbl> 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,...
## $ areatotal <dbl> 2566, 2524, 2706, 2473, 3343, 2158, 3380, 31...
## $ areatotalvaranda <int> 61, 0, 42, 307, 84, 350, 57, 432, 205, 4, 0,...
DFnumeric <- todas[, names(todas) %in% numericVarNames]
DFfactors <- todas[, !(names(todas) %in% numericVarNames)]
DFfactors <- DFfactors[, names(DFfactors) != 'PrecoVenda']
DFnumeric$Id <- NULL
cat('Existem', length(DFnumeric), 'variáveis numéricas e', length(DFfactors), 'variáveis categóricas')## Existem 29 variáveis numéricas e 49 variáveis categóricas
Será aplicado o log+1 para variáveis com assimetria maior que 0,8.
Normalização das variáveis.
## Created from 2917 samples and 29 variables
##
## Pre-processing:
## - centered (29)
## - ignored (0)
## - scaled (29)
## [1] 2917 29
Este processo consiste em transformar variáveis categóricas em numéricas a partir da criação de uma coluna para cada categoria. Assim os valores presentes são somente 0 e 1.
## [1] 2917 201
Serão eliminadas as colunas de categorias que possuem zero ou poucas (<10) observações
colunaszeradasteste <- which(colSums(DFdummies[(nrow(todas[!is.na(todas$PrecoVenda),])+1):nrow(todas),])==0)
colnames(DFdummies[colunaszeradasteste])## [1] "Proximidade2RRAe" "Proximidade2RRAn"
## [3] "Proximidade2RRNn" "Pavimentos2.5Fin"
## [5] "MaterialCoberturaMembran" "MaterialCoberturaMetal"
## [7] "MaterialCoberturaRoll" "Fachada1ImStucc"
## [9] "Fachada1Stone" "Fachada2Other"
## [11] "AquecimentoOthW" "SistemaEletricoMix"
## [13] "OutrosItensTenC"
colunaszeradastrain <- which(colSums(DFdummies[1:nrow(todas[!is.na(todas$PrecoVenda),]),])==0)
colnames(DFdummies[colunaszeradastrain])## [1] "Classe1,5 story PUD all"
colunaspoucastrain <- which(colSums(DFdummies[1:nrow(todas[!is.na(todas$PrecoVenda),]),])<10)
colnames(DFdummies[colunaspoucastrain])## [1] "Classe1 story unf attic" "ImplantacaoLoteFR3"
## [3] "BairroBlueste" "BairroNPkVill"
## [5] "Proximidade1PosA" "Proximidade1RRNe"
## [7] "Proximidade1RRNn" "Proximidade2Feedr"
## [9] "Proximidade2PosA" "Proximidade2PosN"
## [11] "TipoCoberturaMansard" "TipoCoberturaShed"
## [13] "MaterialCoberturaWdShake" "MaterialCoberturaWdShngl"
## [15] "Fachada1AsphShn" "Fachada1BrkComm"
## [17] "Fachada1CBlock" "Fachada2AsphShn"
## [19] "Fachada2Brk Cmn" "Fachada2CBlock"
## [21] "Fachada2Stone" "FundacaoStone"
## [23] "FundacaoWood" "AquecimentoGrav"
## [25] "AquecimentoWall" "SistemaEletricoFuseP"
## [27] "TipoGaragemCarPort" "OutrosItensOthr"
## [29] "TipoVendaCon" "TipoVendaConLD"
## [31] "TipoVendaConLI" "TipoVendaConLw"
## [33] "TipoVendaCWD" "TipoVendaOth"
## [35] "CondicaoVendaAdjLand"
## [1] 2917 152
## [1] 2917 181
Verificando a assimetria da variável-alvo (PrecoVenda)
## [1] 1.877427
Assimetria significativa e maior que zero, demonstrando cauda direita (como visto no histograma do início). Assim, será aplicado o log (não precisa +1 pois não há zeros).
## [1] 0.1213182
Bem melhor.
train1 <- combined[!is.na(todas$PrecoVenda),]
test1 <- combined[is.na(todas$PrecoVenda),]
dim(train1)## [1] 1458 181
## [1] 1459 181
Comparado a outros algoritmos de penalização (ridge e elatic net), o método Lasso possui a vantagem de zerar algumas variáveis pouco importantes para o modelo. Como este conjunto apresentou alguns casos de multicolinearidade e algumas correlações muito baixas, o Lasso aparenta ser uma boa opção para ligeiramente aumentar o viés em troca de uma melhor variância.
O melhor valor para lambda será testado por validação cruzada de 10 dobras para um alpha de 1.
set.seed(15102020)
my_control <-trainControl(method="cv", number=10)
lassoGrid <- expand.grid(alpha = 1, lambda = seq(0.001,0.1,by = 0.0005))
lasso_mod <- train(x=train1, y=todas$PrecoVenda[!is.na(todas$PrecoVenda)], method='glmnet', trControl= my_control, tuneGrid=lassoGrid)
lasso_mod$bestTune## alpha lambda
## 5 1 0.003
RMSE: Raiz quadrada do erro médio - medida de erro residual:
## [1] 0.1125066
Quantas variáveis o modelo ignorou:
lassoVarImp <- varImp(lasso_mod,scale=F)
lassoImportance <- lassoVarImp$importance
varsSelected <- length(which(lassoImportance$Overall!=0))
varsNotSelected <- length(which(lassoImportance$Overall==0))
cat('Lasso usou', varsSelected, 'variáveis no modelo, não selecionou', varsNotSelected, 'variáveis.')## Lasso usou 87 variáveis no modelo, não selecionou 94 variáveis.
Aplicando o algoritmo no conjunto de teste:
LassoPred <- predict(lasso_mod, test1)
predictions_lasso <- exp(LassoPred) # revertendo o log para ficar em valores real (dolares)
head(predictions_lasso)## 1461 1462 1463 1464 1465 1466
## 113940.4 161820.2 179729.7 197559.1 205773.8 170131.6