Neste notebook, comparamos diferentes modelos de regressão utilizando dados reais. O objetivo é analisar a performance preditiva de cada modelo, utilizando métricas como RMSE e \(R^2\). Considerando os dados reais de imóveis anunciados para venda na cidade de João Pessoa - PB, com mais de 27 mil observações obtidas via web scraping de sites de anúncios imobiliários e referem-se à anúncios do primeiro semestre de 2023.A partir dele realiza-se uma análise preditiva do valor dos imóveis, baseada em suas características, considerando uma abordagem clara e completa para a análise de dados e modelagem preditiva. Utilizaremos uma variedade de modelos de regressão e uma análise detalhada para comparar o desempenho de cada modelo.
library(tidymodels)
library(vetiver)
library(iml)
library(cowplot)
library(ggplot2)
library(randomForest)
library(workflowsets)
library(glmnet)
library(parallelly)
library(parallel)
library(recipes)
library(imager)
library(kknn)
library(GGally)
dados <- read.csv("C:/Users/gleyc/Downloads/joao_pessoa_gleyce.csv")
view(dados)
str(dados)
## 'data.frame': 27038 obs. of 30 variables:
## $ id : num 2.62e+09 2.63e+09 2.63e+09 2.63e+09 2.44e+09 ...
## $ endereco : chr "Rua Professora Nair Paiva dos Santos" "Altiplano Cabo Branco" "Rua Doutor Pedro Narciso Castanheira" "Rua Elisio Lopes de Oliveira" ...
## $ valor : int 1450000 1950000 350000 360000 650000 699600 740000 1450000 1599000 700000 ...
## $ area : int 221 295 525 191 300 200 130 228 228 200 ...
## $ quarto : int 4 5 2 3 5 4 3 5 4 4 ...
## $ vaga : int 3 2 NA 3 2 2 3 4 4 2 ...
## $ banheiro : int 4 7 1 3 5 5 3 5 4 4 ...
## $ url : chr "https://www.zapimoveis.com.br/venda/casas/pb+joao-pessoa++altiplano-cabo-branco/?pagina=1" "https://www.zapimoveis.com.br/venda/casas/pb+joao-pessoa++altiplano-cabo-branco/?pagina=1" "https://www.zapimoveis.com.br/venda/casas/pb+joao-pessoa++altiplano-cabo-branco/?pagina=1" "https://www.zapimoveis.com.br/venda/casas/pb+joao-pessoa++altiplano-cabo-branco/?pagina=1" ...
## $ bairro : chr "altiplano_cabo_branco" "altiplano_cabo_branco" "altiplano_cabo_branco" "altiplano_cabo_branco" ...
## $ zona : chr "leste" "leste" "leste" "leste" ...
## $ tipo : chr "casas" "casas" "casas" "casas" ...
## $ comercio : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ area_servico : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ espaco_gourmet : logi TRUE TRUE FALSE FALSE FALSE FALSE ...
## $ piscina : logi TRUE TRUE FALSE TRUE FALSE FALSE ...
## $ elevador : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ salao_de_festa : logi TRUE FALSE FALSE FALSE FALSE FALSE ...
## $ academia : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ playground : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ quadra_de_esporte: logi TRUE FALSE FALSE FALSE FALSE FALSE ...
## $ portaria_24_horas: logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ varanda_gourmet : logi TRUE FALSE FALSE FALSE FALSE FALSE ...
## $ sauna : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ spa : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ iptu : int 700 NA NA 900 NA NA NA NA 1 NA ...
## $ condominio : int 680 NA NA NA NA NA NA NA 1 NA ...
## $ latitude : num -7.14 -7.13 -7.14 -7.13 -7.14 ...
## $ longitude : num -34.8 -34.8 -34.8 -34.8 -34.8 ...
## $ z_lat : num -0.03221 -0.00477 -0.02302 -0.01207 -0.01603 ...
## $ z_lon : num 0.1164 0.1127 0.0974 0.1006 0.0996 ...
Pré- Processamento dos Dados
# Verificar os nomes das colunas
colnames(dados)
## [1] "id" "endereco" "valor"
## [4] "area" "quarto" "vaga"
## [7] "banheiro" "url" "bairro"
## [10] "zona" "tipo" "comercio"
## [13] "area_servico" "espaco_gourmet" "piscina"
## [16] "elevador" "salao_de_festa" "academia"
## [19] "playground" "quadra_de_esporte" "portaria_24_horas"
## [22] "varanda_gourmet" "sauna" "spa"
## [25] "iptu" "condominio" "latitude"
## [28] "longitude" "z_lat" "z_lon"
# Remover colunas desnecessárias apenas se existirem
cols_to_remove <- c("endereco", "bairro", "iptu","id", "condominio")
dados <- dados %>%
select(-one_of(cols_to_remove))
# Transformar a variável tipo em variáveis dummy
dados <- dados %>%
mutate(
tipo_casa = ifelse(grepl("casa", tipo, ignore.case = TRUE), 1, 0),
tipo_apartamento = ifelse(grepl("apartamento", tipo, ignore.case = TRUE), 1, 0),
tipo_terreno = ifelse(grepl("terreno", tipo, ignore.case = TRUE), 1, 0)
)
# Criar receita para imputação de dados faltantes
recipe_dados <- recipe(~ ., data = dados) %>%
step_impute_knn(all_predictors(), neighbors = 5)
# Ajustar a receita aos dados
dados_imputados <- prep(recipe_dados, training = dados) %>%
bake(new_data = NULL)
# Remover a coluna tipo original
dados_imputados <- dados_imputados %>%
select(-tipo)
# Verificar se há mais valores faltantes
sum(is.na(dados_imputados))
## [1] 0
# Calcular a matriz de correlação
cor_matrix <- cor(dados_imputados %>% select_if(is.numeric))
# Visualizar a matriz de correlação
library(reshape2)
##
## Anexando pacote: 'reshape2'
## O seguinte objeto é mascarado por 'package:tidyr':
##
## smiths
library(ggplot2)
cor_matrix_melted <- melt(cor_matrix)
ggplot(cor_matrix_melted, aes(Var1, Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = "red", high = "blue", mid = "white", midpoint = 0, limit = c(-1, 1), space = "Lab", name="Correlação") +
theme_minimal() +
labs(title = "Matriz de Correlação")
# Modelo de regressão linear
modelo_lm <- lm(valor ~ area + quarto + banheiro + tipo_casa + tipo_apartamento + tipo_terreno, data = dados_imputados)
# Resumo do modelo
summary(modelo_lm)
##
## Call:
## lm(formula = valor ~ area + quarto + banheiro + tipo_casa + tipo_apartamento +
## tipo_terreno, data = dados_imputados)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3881952 -271388 -103294 111890 149727357
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.371e+04 5.314e+04 -1.011 0.312166
## area -6.873e-03 1.872e-02 -0.367 0.713515
## quarto 1.832e+05 1.744e+04 10.500 < 2e-16 ***
## banheiro 1.987e+05 1.190e+04 16.698 < 2e-16 ***
## tipo_casa -2.470e+05 6.938e+04 -3.559 0.000373 ***
## tipo_apartamento -2.387e+05 5.610e+04 -4.255 2.1e-05 ***
## tipo_terreno 1.612e+06 9.550e+04 16.883 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1893000 on 27031 degrees of freedom
## Multiple R-squared: 0.04024, Adjusted R-squared: 0.04003
## F-statistic: 188.9 on 6 and 27031 DF, p-value: < 2.2e-16
# Previsões e cálculo do erro quadrático médio (RMSE)
dados_imputados$predicoes_lm <- predict(modelo_lm, newdata = dados_imputados)
rmse_lm <- sqrt(mean((dados_imputados$valor - dados_imputados$predicoes_lm)^2))
# Preparar os dados para a regressão Ridge
x <- model.matrix(valor ~ area + quarto + banheiro + tipo_casa + tipo_apartamento + tipo_terreno, data = dados_imputados)[, -1]
y <- dados_imputados$valor
# Ajustar o modelo de regressão Ridge
modelo_ridge <- cv.glmnet(x, y, alpha = 0)
# Previsões e cálculo do RMSE
predicoes_ridge <- predict(modelo_ridge, newx = x)
rmse_ridge <- sqrt(mean((y - predicoes_ridge)^2))
# Ajustar o modelo de regressão Lasso
modelo_lasso <- cv.glmnet(x, y, alpha = 1)
# Previsões e cálculo do RMSE
predicoes_lasso <- predict(modelo_lasso, newx = x)
rmse_lasso <- sqrt(mean((y - predicoes_lasso)^2))
# Ajustar o modelo de Elastic Net
modelo_elastic_net <- cv.glmnet(x, y, alpha = 0.5)
# Previsões e cálculo do RMSE
predicoes_elastic_net <- predict(modelo_elastic_net, newx = x)
rmse_elastic_net <- sqrt(mean((y - predicoes_elastic_net)^2))
# Exibir RMSE do modelo Elastic Net
cat("RMSE do modelo Elastic Net:", rmse_elastic_net, "\n")
## RMSE do modelo Elastic Net: 1931771
# Comparar e classificar a performance dos modelos
resultados <- data.frame(
Modelo = c("Linear", "Ridge", "Lasso", "Elastic Net"),
RMSE = c(rmse_lm, rmse_ridge, rmse_lasso, rmse_elastic_net)
)
resultados <- resultados %>%
arrange(RMSE)
print(resultados)
## Modelo RMSE
## 1 Linear 1892506
## 2 Ridge 1931771
## 3 Lasso 1931771
## 4 Elastic Net 1931771
Fazendo as análises e comparando os quatro modelos de regressão — Linear, Ridge, Lasso e Elastic Net — para prever o valor de venda de imóveis em João Pessoa. O desempenho foi avaliado usando o RMSE, com a regressão linear simples obtendo o melhor resultado (RMSE = 1892506). Os modelos Ridge, Lasso e Elastic Net apresentaram RMSEs muito semelhantes (1931771), indicando que a regularização não trouxe uma melhoria significativa. Isso sugere que as features não se beneficiaram muito da regularização, ou que os parâmetros de regularização poderiam ser otimizados. A regressão linear simples mostrou-se eficaz, possivelmente porque as variáveis explicativas têm uma relação linear direta com o valor dos imóveis.