Maria comenzó como agente de bienes raíces en Cali hace 10 años. Después de laborar dos años para una empresa nacional, se traslado a Bogotá y trabajó para otra agencia de bienes raíces. Sus amigos y familiares la convencieron de que con su experiencia y conocimientos del negocio debía abrir su propia agencia. Terminó por adquirir la licencia de intermediario y al poco tiempo fundó su propia compañía, C&A (Casas y Apartamentos) en Cali. Santiago y Lina, dos vendedores de la empresa anterior aceptaron trabajar en la nueva compaña. En la actualidad ocho agentes de bienes raíces colaboran con ella en C&A.
Actualmente las ventas de bienes raíces en Cali se han visto disminuidas de manera significativa en lo corrido del año. Durante este periodo muchas instituciones bancarias de ahorro y vivienda están prestando grandes sumas de dinero para la industria y la construcción comercial y residencial. Cuando el efecto producto de las tensiones políticas y sociales disminuya, se espera que la actividad económica de este sector se reactive.
Hace dos días, María recibió una carta solicitando asesoría para la compra de dos viviendas por parte de una compañía internacional que desea ubicar a dos de sus empleados con sus familias en la ciudad. Las solicitudes incluyen las siguientes condiciones:
| Características | Vivienda 1 | Vivienda 2 |
|---|---|---|
| Tipo | Casa | Apartamento |
| área construida | 200 | 300 |
| parqueaderos | 1 | 3 |
| baños | 2 | 3 |
| habitaciones | 4 | 5 |
| estrato | 4 o 5 | 5 o 6 |
| zona | Norte | Sur |
| crédito preaprobado | 350 millones | 850 millones |
Ayude a María a responder la solicitud, mediante técnicas modelación que usted conoce. Ella requiere le envíe un informe ejecutivo donde analice los dos casos y sus recomendaciones (Informe). Como soporte del informe debe anexar las estimaciones, validaciones y comparación de modelos requeridos (Anexos).
#install.packages("devtools") # solo la primera vez
#devtools::install_github("dgonxalex80/paqueteMODELOS", force =TRUE)
library(paqueteMODELOS)
## Loading required package: boot
##
## Attaching package: 'boot'
## The following object is masked from 'package:psych':
##
## logit
## The following object is masked from 'package:car':
##
## logit
## Loading required package: broom
library(dplyr)
data(vivienda)
datavivienda <- vivienda
# Calcula el número de datos faltantes por variable
datos_faltantes <- datavivienda %>% summarise_all(~sum(is.na(.)))
kable(datos_faltantes, format = "markdown")
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3 | 3 | 2638 | 3 | 2 | 3 | 1605 | 3 | 3 | 3 | 3 | 3 | 3 |
# Filtra los registros donde id no es nulo de esta forma ya tendriamos el data set sin los 3 registros nulos
datavivienda <- datavivienda %>%
filter(!is.na(id))
# Pasar todos los caracteres a minuscula
datavivienda$barrio = tolower(datavivienda$barrio)
# Quitar las tildes:
#viviendasF$barrio = iconv(viviendasF$barrio, to = "ASCII//TRANSLIT")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"á", "a")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"é", "e")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"í", "i")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"ó", "o")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"ú", "u")
# Quitar caracteres especiales
#viviendasF$barrio = str_replace_all(viviendasF$barrio,"[^[0-9a-zA-Z ]]", "")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"é", "e")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"√∫", "u")
# Corregir otros problemas de calidad
datavivienda$barrio = ifelse(datavivienda$barrio == "agua blanca","aguablanca",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "alfonso lopez i","alfonso lopez",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "calibella","cali bella",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ciudadela paso ancho","ciudadela pasoancho",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ingenio i","el ingenio i",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ingenio ii","el ingenio ii",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "la rivera i","la rivera",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "las vegas de","las vegas",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "pampa linda","pampalinda",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ponce","pance",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "tequendema","tequendama",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "valle de lili","valle del lili",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "zona norte los","zona norte",datavivienda$barrio)
tipoapto <- unique(datavivienda$tipo)
print(tipoapto)
## [1] "Casa" "Apartamento"
library(tidyverse)
# Separa las observaciones con valores completos y los faltantes en `parqueaderos`
data_completa <- datavivienda %>% filter(!is.na(parqueaderos))
data_faltantes <- datavivienda %>% filter(is.na(parqueaderos))
# Ajusta un modelo de regresión lineal usando las observaciones completas
modelo <- lm(parqueaderos ~ estrato + preciom + areaconst + banios + habitaciones + tipo , data = data_completa)
# Predice los valores faltantes usando el modelo ajustado
data_faltantes$parqueaderos <- predict(modelo, newdata = data_faltantes)
# Combina las predicciones con el dataframe original
viviendas_imputadas <- datavivienda %>%
mutate(parqueaderos = ifelse(is.na(parqueaderos), predict(modelo, newdata = .), parqueaderos))
viviendas_imputadas$parqueaderos <- trunc(viviendas_imputadas$parqueaderos)
# Verifica los cambios
summary(viviendas_imputadas)
## id zona piso estrato
## Min. : 1 Length:8319 Length:8319 Min. :3.000
## 1st Qu.:2080 Class :character Class :character 1st Qu.:4.000
## Median :4160 Mode :character Mode :character Median :5.000
## Mean :4160 Mean :4.634
## 3rd Qu.:6240 3rd Qu.:5.000
## Max. :8319 Max. :6.000
## preciom areaconst parqueaderos banios
## Min. : 58.0 Min. : 30.0 Min. : 0.000 Min. : 0.000
## 1st Qu.: 220.0 1st Qu.: 80.0 1st Qu.: 1.000 1st Qu.: 2.000
## Median : 330.0 Median : 123.0 Median : 1.000 Median : 3.000
## Mean : 433.9 Mean : 174.9 Mean : 1.636 Mean : 3.111
## 3rd Qu.: 540.0 3rd Qu.: 229.0 3rd Qu.: 2.000 3rd Qu.: 4.000
## Max. :1999.0 Max. :1745.0 Max. :10.000 Max. :10.000
## habitaciones tipo barrio longitud
## Min. : 0.000 Length:8319 Length:8319 Min. :-76.59
## 1st Qu.: 3.000 Class :character Class :character 1st Qu.:-76.54
## Median : 3.000 Mode :character Mode :character Median :-76.53
## Mean : 3.605 Mean :-76.53
## 3rd Qu.: 4.000 3rd Qu.:-76.52
## Max. :10.000 Max. :-76.46
## latitud
## Min. :3.333
## 1st Qu.:3.381
## Median :3.416
## Mean :3.418
## 3rd Qu.:3.452
## Max. :3.498
# Calcula el número de datos faltantes por variable
datos_faltantes <- viviendas_imputadas %>% summarise_all(~sum(is.na(.)))
kable(datos_faltantes, format = "markdown")
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 2635 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
datavivienda <- viviendas_imputadas
Se crea una variable nueva para tener las zonas en tipo categorica
datavivienda$zona_numeric <- as.numeric(factor(datavivienda$zona,
levels = c("Zona Norte", "Zona Sur", "Zona Oriente", "Zona Oeste","Zona Centro"),
labels = c(1, 2, 3, 4,5)))
Para poder ejecutar este punto , es necesario primero filtrar la zona y el tipo y estandarizar los datos de longitud y latitud, en este caso toca dividir el valor puesto entre 1000.
Inicialmente realizamos el filtro de las viviendas tipo Casa de la zona Norte de la ciudad de Cali
base1 <- datavivienda %>%
filter(tipo=="Casa",zona=="Zona Norte")
dim(base1)
## [1] 722 14
head(base1,3)
## # A tibble: 3 × 14
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1209 Zona N… 02 5 320 150 2 4 6
## 2 1592 Zona N… 02 5 780 380 2 3 3
## 3 4057 Zona N… 02 6 750 445 3 7 6
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # zona_numeric <dbl>
Y aqui comoo podemos evidenciar el proceso fue efectivo y ya contamos con la base 1 lista para trabajar.
Es necesario estandarizar los datos de longitud y latitud, en este caso toca dividir el valor puesto entre 1000
# Crea un mapa
map <- leaflet(base1) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Tipo:", tipo, "<br>",
"Latitud:", latitud, "<br>",
"Longitud:", longitud, "<br>",
"Precio:", preciom) # Puedes personalizar el contenido del popup aquí
)
map # Muestra el mapa
Existen 253 Casas ubicadas en la zona norte , en su gran mayoría corresponden a esta , aunque hay algunos casos en los que esta marcados pero su latitud y longitud da por fuera de la zona , en su mayoría los que estan asignados al barrio acopi
cor(x=base1$areaconst,y=base1$preciom)
## [1] 0.731348
scatter_price_area <- plot_ly(data = base1, x = ~areaconst, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
text = ~paste("Zona:", zona),
colors = ~zona)
scatter_price_area <- scatter_price_area %>%
layout(title = "Relación entre Precio y Área Construida",
xaxis = list(title = "Área Construida"),
yaxis = list(title = "Precio"))
scatter_price_area
modelo_1_areaconst <- lm(preciom ~ areaconst, data = base1)
# Resumen del modelo
summary(modelo_1_areaconst)
##
## Call:
## lm(formula = preciom ~ areaconst, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1455.63 -93.96 -30.63 56.17 953.92
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 134.9491 12.7768 10.56 <2e-16 ***
## areaconst 1.1741 0.0408 28.77 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 183.2 on 720 degrees of freedom
## Multiple R-squared: 0.5349, Adjusted R-squared: 0.5342
## F-statistic: 828 on 1 and 720 DF, p-value: < 2.2e-16
Correlación : El valor de 0.7313 sugiere una correlación moderada aportando un 53.5% de variabilidad lo que significa que este procentaje de area construida explica el precio de la vivienda, teniendo en cuneta esto se peude concluir, que hay una relación positiva significativa entre estas dos variables, pero no es extremadamente fuerte, lo que nos lleva a concluir que si el área construida es mayor, es más probable que el precio de la vivienda aumente.
cor(x=base1$areaconst,y=base1$estrato)
## [1] 0.4573818
scatter_price_nse <- plot_ly(data = base1, x = ~areaconst, y = ~estrato,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
text = ~paste("Zona:", zona),
colors = ~zona)
scatter_price_nse <- scatter_price_nse %>%
layout(title = "Relación entre Precio y Estrato",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio"))
scatter_price_nse
modelo_1_nse <- lm(preciom ~ estrato, data = base1)
# Resumen del modelo
summary(modelo_1_nse)
##
## Call:
## lm(formula = preciom ~ estrato, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -454.3 -124.9 -44.6 70.7 1387.9
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -256.710 34.718 -7.394 3.96e-13 ***
## estrato 167.201 8.045 20.783 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 212.3 on 720 degrees of freedom
## Multiple R-squared: 0.375, Adjusted R-squared: 0.3741
## F-statistic: 432 on 1 and 720 DF, p-value: < 2.2e-16
Correlación: El valor es 0,46 lo cual indica que el precio con la variable estrati tiene cierta relación pero muy debil y adicional a esto solo el 37.5% de la variabilida de los precios esta representada por la variable estrato, al final de esto podemos concluir que no hay una relación directa entre el precio y el estrato
cor(x=base1$banios,y=base1$preciom)
## [1] 0.5233357
scatter_price_bathrooms <- plot_ly(data = base1, x = ~banios, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
text = ~paste("Zona:", zona),
colors = ~zona)
scatter_price_bathrooms <- scatter_price_bathrooms %>%
layout(title = "Relación entre Precio y Número de Baños",
xaxis = list(title = "Número de Baños"),
yaxis = list(title = "Precio"))
scatter_price_bathrooms
modelo_1_banios<- lm(preciom ~ banios, data = base1)
# Resumen del modelo
summary(modelo_1_banios)
##
## Call:
## lm(formula = preciom ~ banios, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -455.54 -142.55 -59.38 71.57 1313.12
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 118.228 21.631 5.466 6.36e-08 ***
## banios 92.163 5.593 16.479 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 228.8 on 720 degrees of freedom
## Multiple R-squared: 0.2739, Adjusted R-squared: 0.2729
## F-statistic: 271.6 on 1 and 720 DF, p-value: < 2.2e-16
Correlación: El valor es 0,52 lo cual indica que el precio con la variable numero de baños tiene cierta relación pero muy debil y adicional a esto solo el 27.39% de la variabilida de los precios esta representada por la variable numero de baños, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de baños.
cor(x=base1$habitaciones,y=base1$preciom)
## [1] 0.3227096
scatter_price_rooms <- plot_ly(data = base1, x = ~habitaciones, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
colors = ~zona)
scatter_price_rooms <- scatter_price_rooms %>%
layout(title = "Relación entre Precio y Número de habitaciones",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio"))
scatter_price_rooms
modelo_1_rooms<- lm(preciom ~ habitaciones, data = base1)
# Resumen del modelo
summary(modelo_1_rooms)
##
## Call:
## lm(formula = preciom ~ habitaciones, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -413.81 -174.50 -53.19 105.50 1233.81
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 232.348 25.187 9.225 <2e-16 ***
## habitaciones 47.384 5.179 9.149 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 254.2 on 720 degrees of freedom
## Multiple R-squared: 0.1041, Adjusted R-squared: 0.1029
## F-statistic: 83.7 on 1 and 720 DF, p-value: < 2.2e-16
Correlación: El valor es 0,32 lo cual indica que el precio con la variable numero de habitaciones tiene baja relación y adicional a esto solo el 10.41% de la variabilida de los precios esta representada por la variable numero de habitaciones, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de habitaciones.
En este caso como la zona esta filtrada lo mas seguro es no salga logico el ejercicio, de igual manera se realizara para comprobar esto, pero posteriormente se relizara con la base de datos completa e identifiar la correlación.
cor(x=base1$habitaciones,y=base1$zona_numeric)
## [1] NA
scatter_price_zone <- plot_ly(data = base1, x = ~zona_numeric, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
colors = ~zona_numeric)
scatter_price_zone <- scatter_price_zone %>%
layout(title = "Relación entre Precio y Número de habitaciones",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio"))
scatter_price_zone
modelo_1_zone<- lm(preciom ~ zona_numeric, data = base1)
# Resumen del modelo
summary(modelo_1_zone)
##
## Call:
## lm(formula = preciom ~ zona_numeric, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -356.91 -184.66 -55.91 104.09 1494.09
##
## Coefficients: (1 not defined because of singularities)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 445.906 9.987 44.65 <2e-16 ***
## zona_numeric NA NA NA NA
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 268.4 on 721 degrees of freedom
cor(x=datavivienda$habitaciones,y=datavivienda$zona_numeric)
## [1] 0.02696498
scatter_price_zone2 <- plot_ly(data = datavivienda, x = ~zona_numeric, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
colors = ~zona_numeric)
scatter_price_zone2 <- scatter_price_zone2 %>%
layout(title = "Relación entre Precio y Número de habitaciones",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio"))
scatter_price_zone2
modelo_1_zone2<- lm(preciom ~ zona_numeric, data = datavivienda)
# Resumen del modelo
summary(modelo_1_zone2)
##
## Call:
## lm(formula = preciom ~ zona_numeric, data = datavivienda)
##
## Residuals:
## Min 1Q Median 3Q Max
## -560.44 -203.15 -93.15 101.85 1596.85
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 263.824 8.415 31.35 <2e-16 ***
## zona_numeric 79.324 3.569 22.23 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 319.3 on 8317 degrees of freedom
## Multiple R-squared: 0.05607, Adjusted R-squared: 0.05595
## F-statistic: 494 on 1 and 8317 DF, p-value: < 2.2e-16
Correlación: El valor es 0,026 lo cual indica que el precio con la variable Zona tiene baja relación, casi inexistente a esto solo el 5.61% de la variabilida de los precios esta representada por la variable zona, al final de esto podemos concluir que no hay una relación directa entre el precio y la zona.
Primero se evaluara de manera conjunta todas las variabes solicitadas.
cor_1 <-base1[,c("preciom","areaconst","estrato","banios","habitaciones","parqueaderos")]
#cor_1
library(GGally)
ggpairs(cor_1, title=" ")
Ahora si realizaremos el modelo:
modelo_in<- lm(preciom ~ 1, data=base1)
modelo_all <- lm(preciom ~ habitaciones + banios + areaconst + parqueaderos+ estrato, data = base1)
summary(modelo_all)
##
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos +
## estrato, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -881.35 -77.16 -15.60 44.54 1028.87
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -219.36885 29.26709 -7.495 1.96e-13 ***
## habitaciones 0.53353 4.05051 0.132 0.895
## banios 21.26676 5.32894 3.991 7.26e-05 ***
## areaconst 0.77619 0.04362 17.796 < 2e-16 ***
## parqueaderos 29.95492 5.59289 5.356 1.15e-07 ***
## estrato 77.54993 7.23291 10.722 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 156.1 on 716 degrees of freedom
## Multiple R-squared: 0.6642, Adjusted R-squared: 0.6618
## F-statistic: 283.2 on 5 and 716 DF, p-value: < 2.2e-16
2.habitaciones: El coeficiente estimado para el número de habitaciones (habitac) es 0.53. Esto significa que, manteniendo todas las demás variables constantes, un aumento de una unidad en el número de habitaciones se asocia con un aumento estimado de $530 mil pesos en el precio de la vivienda, adicional a esto, este coeficiente no es estadísticamente significativo un p-value = 0.89.
3.banios: El coeficiente estimado para el número de baños (banios) es 21.26. Esto implica que, manteniendo constantes las demás variables, un aumento de una unidad en el número de baños se asocia con un aumento estimado de $21.93 millones de pesos de en el precio de la vivienda, adicional a esto, este cofeciente es estadísticamente significativo un p-value = 7.26e-05.
4.areaconst: El coeficiente para el área construida (areaconst) es 0.77. Esto significa que un aumento de una unidad en el área construida se relaciona con un aumento estimado de $776 mil pesos en el precio de la vivienda, adicional a esto, este coeficiente es estadísticamente significativo (alto) un p-value < 2e-16.
5.parqueaderos: El coeficiente estimado para el número de parqueaderos (parquea) es 29.95. Esto sugiere que un aumento de una unidad en el número de parqueaderos se asocia con un aumento estimado de $29.95 millones en el precio de la vivienda, y este coeficiente es estadísticamente significativo (alto) un p-value = 1.15e-07.
6.estrato: El coeficiente para el estrato es 77.54. Esto indica que un aumento de una unidad en el estrato se relaciona con un aumento estimado de $77.54 millones en el precio de la vivienda, y este coeficiente es estadísticamente significativo (alto) un p-value < 2e-16.
7.R-cuadrado (Multiple R-squared): El R-cuadrado es 0.66, lo que significa que aproximadamente el 66.4% de la variabilidad en el precio de la vivienda se explica por las variables independientes incluidas en el modelo.
####Steppwise
# Se aplica el proceso forward stepwise regression
forward <- step(modelo_in, direction='forward', scope=formula(modelo_all), trace=0)
# Visualización de los resultados
forward$anova
## Step Df Deviance Resid. Df Resid. Dev AIC
## 1 NA NA 721 51926104 8076.348
## 2 + areaconst -1 27773709.6 720 24152394 7525.701
## 3 + estrato -1 5069011.9 719 19083382 7357.623
## 4 + parqueaderos -1 1102855.8 718 17980526 7316.643
## 5 + banios -1 542097.1 717 17438429 7296.541
#resultado final del modelo
summary(forward)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios,
## data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -880.26 -77.15 -15.62 44.25 1030.06
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -217.6489 26.1749 -8.315 4.59e-16 ***
## areaconst 0.7774 0.0426 18.247 < 2e-16 ***
## estrato 77.3230 7.0200 11.015 < 2e-16 ***
## parqueaderos 29.9787 5.5862 5.367 1.08e-07 ***
## banios 21.6248 4.5804 4.721 2.82e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 156 on 717 degrees of freedom
## Multiple R-squared: 0.6642, Adjusted R-squared: 0.6623
## F-statistic: 354.5 on 4 and 717 DF, p-value: < 2.2e-16
Este resultado lo que nos indica es que debemos realizar de nuevo el modelo de regresión lienal teniendo en cuenta las variables areaconst, estrato, paruqeaderos y banios.
plot(modelo_all$fitted.values, resid(modelo_all), xlab = "Valores Ajustados", ylab = "Residuos", main = "Gráfico de Residuos vs. Valores Ajustados")
plot(modelo_all$fitted.values, sqrt(abs(resid(modelo_all)/sd(resid(modelo_all)))), xlab = "Valores Ajustados", ylab = "Raíz Cuadrada de los Residuos Estandarizados", main = "Gráfico de Homocedasticidad")
autoplot(modelo_all)
shapiro.test(resid(modelo_all))
##
## Shapiro-Wilk normality test
##
## data: resid(modelo_all)
## W = 0.84168, p-value < 2.2e-16
vif(modelo_all)
## habitaciones banios areaconst parqueaderos estrato
## 1.622464 1.952212 1.573739 1.422341 1.496057
datos_sin_atipicos <- base1[-which(abs(resid(modelo_all)) > 2 * sd(resid(modelo_all))), ]
De manera resumida podemos encontrar que el valor que nos da en W, el cual es relativamente bajo, sugiere que los residuos no siguen una distribución Normal, por otro lado el El p-valor es extremadamente bajo, mucho menor que cualquier umbral típico (como 0.05 o 0.01). Esto significa que hay evidencia muy fuerte para rechazar la hipótesis nula del test, que es que los residuos siguen una distribución normal.
dwtest(modelo_all)
##
## Durbin-Watson test
##
## data: modelo_all
## DW = 1.6278, p-value = 2.202e-07
## alternative hypothesis: true autocorrelation is greater than 0
Esto que encontramos en este supuesto, queire decir que hay autocorrelación positiva significativa en los residuos del modelo, lo que sugiere que podría ser necesario ajustar el modelo o considerar otros enfoques para manejar esta autocorrelación.
gqtest(modelo_all)
##
## Goldfeld-Quandt test
##
## data: modelo_all
## GQ = 1.1129, df1 = 355, df2 = 355, p-value = 0.1571
## alternative hypothesis: variance increases from segment 1 to 2
En este supuesto encontramos que la varianza de los errores no varía significativamente entre los segmentos, lo que indica que no hay heterocedasticidad significativa en el modelo.
g3=ggplot(base1, aes(preciom, areaconst)) + geom_point() + geom_smooth(method = "lm", level = 0.95, formula = y ~ x)
g4=ggplot(base1, aes(preciom, banios)) + geom_point() + geom_smooth(method = "lm", level = 0.95, formula = y ~ x)
grid.arrange(g3, g4, ncol = 2)
### 5. Con el modelo identificado debe predecir el precio de la vivienda
con las características de la primera solicitud.
A continuación se crea un dataframe con las caracteristicas y los requisitos de la vivienda 1
requerimientos_cliente1<-data.frame(
estrato=c(4,5),
areaconst=c(200,200),
parqueaderos=c(1,1),
banios=c(2,2),
habitaciones=c(4,4)
)
requerimientos_cliente1
## estrato areaconst parqueaderos banios habitaciones
## 1 4 200 1 2 4
## 2 5 200 1 2 4
Ahora ejecutaremos el modelo sin ajustes tal como lo detalla el ejercicio:
Precio_1<-predict(modelo_all,data.frame(requerimientos_cliente1),type="response")
print(paste("Precio de la casa : ", as.character(Precio_1)))
## [1] "Precio de la casa : 320.69136594713"
## [2] "Precio de la casa : 398.241293159088"
base1_viviendas_e4<- base1 %>%
dplyr::filter(estrato==4,areaconst>=200,parqueaderos>=1,banios>=2,habitaciones==4,preciom<=350) %>%
mutate(promedio_reg=320.6913,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=350-preciom) %>%
arrange("areaconst")
base1_viviendas_e4
## # A tibble: 10 × 17
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 7471 Zona … <NA> 4 330 240 1 4 4
## 2 4458 Zona … 02 4 315 270 2 4 4
## 3 2837 Zona … <NA> 4 340 207 1 4 4
## 4 3352 Zona … <NA> 4 335 300 3 4 4
## 5 4727 Zona … 02 4 296 232 1 6 4
## 6 937 Zona … 02 4 350 280 2 3 4
## 7 1108 Zona … 02 4 330 260 1 3 4
## 8 1144 Zona … <NA> 4 320 200 2 4 4
## 9 2544 Zona … 01 4 340 264. 2 4 4
## 10 1822 Zona … <NA> 4 340 295 2 2 4
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## # diferencia_cupo <dbl>
base1_viviendas_e5<- base1 %>%
dplyr::filter(estrato==5,areaconst>=200,parqueaderos>=1,banios>=2,habitaciones==4,preciom<=350) %>%
mutate(promedio_reg=398.2412,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=350-preciom) %>%
arrange("areaconst")
base1_viviendas_e5
## # A tibble: 11 × 17
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 4210 Zona … 01 5 350 200 3 3 4
## 2 4800 Zona … 01 5 340 250 2 4 4
## 3 852 Zona … <NA> 5 340 208 2 6 4
## 4 819 Zona … 02 5 350 264 2 3 4
## 5 1343 Zona … 02 5 320 200 2 4 4
## 6 3053 Zona … 02 5 320 230 2 4 4
## 7 1163 Zona … <NA> 5 350 216 2 2 4
## 8 1849 Zona … <NA> 5 330 246 2 4 4
## 9 1887 Zona … 01 5 340 203 2 3 4
## 10 1842 Zona … 02 5 350 240 2 3 4
## 11 1943 Zona … <NA> 5 350 346 1 2 4
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## # diferencia_cupo <dbl>
Casas <-rbind(base1_viviendas_e4,base1_viviendas_e5)
map <- leaflet(Casas) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Tipo:", tipo, "<br>",
"Latitud:", latitud, "<br>",
"Longitud:", longitud, "<br>",
"Precio:", preciom) # Puedes personalizar el contenido del popup aquí
)
map # Muestra el mapa
Inicialmente realizamos el filtro de las viviendas tipo Casa de la zona Norte de la ciudad de Cali
base2 <- datavivienda %>%
filter(tipo=="Apartamento",zona=="Zona Sur")
dim(base2)
## [1] 2787 14
head(base2,3)
## # A tibble: 3 × 14
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 5098 Zona S… 05 4 290 96 1 2 3
## 2 698 Zona S… 02 3 78 40 1 1 2
## 3 8199 Zona S… <NA> 6 875 194 2 5 3
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # zona_numeric <dbl>
Es necesario estandarizar los datos de longitud y latitud, en este caso toca dividir el valor puesto entre 1000
# Crea un mapa
map <- leaflet(base2) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Tipo:", tipo, "<br>",
"Latitud:", latitud, "<br>",
"Longitud:", longitud, "<br>",
"Precio:", preciom) # Puedes personalizar el contenido del popup aquí
)
map # Muestra el mapa
cor(x=base2$areaconst,y=base2$preciom)
## [1] 0.7579955
scatter_price_area2 <- plot_ly(data = base2, x = ~areaconst, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
text = ~paste("Zona:", zona),
colors = ~zona)
scatter_price_area2 <- scatter_price_area2 %>%
layout(title = "Relación entre Precio y Área Construida",
xaxis = list(title = "Área Construida"),
yaxis = list(title = "Precio"))
scatter_price_area2
modelo_2_areaconst <- lm(preciom ~ areaconst, data = base1)
# Resumen del modelo
summary(modelo_2_areaconst)
##
## Call:
## lm(formula = preciom ~ areaconst, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1455.63 -93.96 -30.63 56.17 953.92
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 134.9491 12.7768 10.56 <2e-16 ***
## areaconst 1.1741 0.0408 28.77 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 183.2 on 720 degrees of freedom
## Multiple R-squared: 0.5349, Adjusted R-squared: 0.5342
## F-statistic: 828 on 1 and 720 DF, p-value: < 2.2e-16
Correlación : El valor de 0.7579 sugiere una correlación moderada aportando un 53.5% de variabilidad lo que significa que este procentaje de area construida explica el precio de la vivienda, teniendo en cuneta esto se peude concluir, que hay una relación positiva significativa entre estas dos variables, pero no es extremadamente fuerte, lo que nos lleva a concluir que si el área construida es mayor, es más probable que el precio de la vivienda aumente.
cor(x=base2$areaconst,y=base2$estrato)
## [1] 0.4815593
scatter_price_nse2 <- plot_ly(data = base2, x = ~areaconst, y = ~estrato,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
text = ~paste("Zona:", zona),
colors = ~zona)
scatter_price_nse2 <- scatter_price_nse2 %>%
layout(title = "Relación entre Precio y Estrato",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio"))
scatter_price_nse2
modelo_2_nse <- lm(preciom ~ estrato, data = base1)
# Resumen del modelo
summary(modelo_2_nse)
##
## Call:
## lm(formula = preciom ~ estrato, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -454.3 -124.9 -44.6 70.7 1387.9
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -256.710 34.718 -7.394 3.96e-13 ***
## estrato 167.201 8.045 20.783 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 212.3 on 720 degrees of freedom
## Multiple R-squared: 0.375, Adjusted R-squared: 0.3741
## F-statistic: 432 on 1 and 720 DF, p-value: < 2.2e-16
Correlación: El valor es 0,48 lo cual indica que el precio con la variable estrati tiene cierta relación pero muy debil y adicional a esto solo el 37.5% de la variabilida de los precios esta representada por la variable estrato, al final de esto podemos concluir que no hay una relación directa entre el precio y el estrato
cor(x=base2$banios,y=base2$preciom)
## [1] 0.7196705
scatter_price_bathrooms2 <- plot_ly(data = base2, x = ~banios, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
text = ~paste("Zona:", zona),
colors = ~zona)
scatter_price_bathrooms2 <- scatter_price_bathrooms2 %>%
layout(title = "Relación entre Precio y Número de Baños",
xaxis = list(title = "Número de Baños"),
yaxis = list(title = "Precio"))
scatter_price_bathrooms2
modelo_2_banios<- lm(preciom ~ banios, data = base1)
# Resumen del modelo
summary(modelo_2_banios)
##
## Call:
## lm(formula = preciom ~ banios, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -455.54 -142.55 -59.38 71.57 1313.12
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 118.228 21.631 5.466 6.36e-08 ***
## banios 92.163 5.593 16.479 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 228.8 on 720 degrees of freedom
## Multiple R-squared: 0.2739, Adjusted R-squared: 0.2729
## F-statistic: 271.6 on 1 and 720 DF, p-value: < 2.2e-16
Correlación: El valor es 0,71 lo cual indica que el precio con la variable numero de baños tiene relación y adicional a esto solo el 27.39% de la variabilida de los precios esta representada por la variable numero de baños, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de baños.
cor(x=base2$habitaciones,y=base2$preciom)
## [1] 0.3317538
scatter_price_rooms2 <- plot_ly(data = base2, x = ~habitaciones, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
colors = ~zona)
scatter_price_rooms2 <- scatter_price_rooms2 %>%
layout(title = "Relación entre Precio y Número de habitaciones",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio"))
scatter_price_rooms2
modelo_2_rooms<- lm(preciom ~ habitaciones, data = base2)
# Resumen del modelo
summary(modelo_2_rooms)
##
## Call:
## lm(formula = preciom ~ habitaciones, data = base2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -447.15 -104.98 -50.29 39.25 1449.25
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.641 16.415 -0.039 0.969
## habitaciones 100.464 5.413 18.559 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 180.7 on 2785 degrees of freedom
## Multiple R-squared: 0.1101, Adjusted R-squared: 0.1097
## F-statistic: 344.4 on 1 and 2785 DF, p-value: < 2.2e-16
Correlación: El valor es 0,33 lo cual indica que el precio con la variable numero de habitaciones tiene baja relación y adicional a esto solo el 11.01% de la variabilida de los precios esta representada por la variable numero de habitaciones, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de habitaciones.
En este caso como la zona esta filtrada lo mas seguro es no salga logico el ejercicio, de igual manera se realizara para comprobar esto, pero posteriormente se relizara con la base de datos completa e identifiar la correlación.
cor(x=base2$habitaciones,y=base2$zona_numeric)
## [1] NA
scatter_price_zone2 <- plot_ly(data = base1, x = ~zona_numeric, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
colors = ~zona_numeric)
scatter_price_zone2 <- scatter_price_zone2 %>%
layout(title = "Relación entre Precio y Número de habitaciones",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio"))
scatter_price_zone2
modelo_2_zone<- lm(preciom ~ zona_numeric, data = base2)
# Resumen del modelo
summary(modelo_2_zone)
##
## Call:
## lm(formula = preciom ~ zona_numeric, data = base2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -222.29 -122.29 -52.29 37.71 1452.71
##
## Coefficients: (1 not defined because of singularities)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 297.292 3.628 81.94 <2e-16 ***
## zona_numeric NA NA NA NA
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 191.6 on 2786 degrees of freedom
cor(x=datavivienda$habitaciones,y=datavivienda$zona_numeric)
## [1] 0.02696498
scatter_price_zone2 <- plot_ly(data = datavivienda, x = ~zona_numeric, y = ~preciom,
type = "scatter", mode = "markers",
marker = list(size = 8, opacity = 0.7),
colors = ~zona_numeric)
scatter_price_zone2 <- scatter_price_zone2 %>%
layout(title = "Relación entre Precio y Número de habitaciones",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio"))
scatter_price_zone2
modelo_1_zone2<- lm(preciom ~ zona_numeric, data = datavivienda)
# Resumen del modelo
summary(modelo_1_zone2)
##
## Call:
## lm(formula = preciom ~ zona_numeric, data = datavivienda)
##
## Residuals:
## Min 1Q Median 3Q Max
## -560.44 -203.15 -93.15 101.85 1596.85
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 263.824 8.415 31.35 <2e-16 ***
## zona_numeric 79.324 3.569 22.23 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 319.3 on 8317 degrees of freedom
## Multiple R-squared: 0.05607, Adjusted R-squared: 0.05595
## F-statistic: 494 on 1 and 8317 DF, p-value: < 2.2e-16
Correlación: El valor es 0,026 lo cual indica que el precio con la variable Zona tiene baja relación, casi inexistente a esto solo el 5.61% de la variabilida de los precios esta representada por la variable zona, al final de esto podemos concluir que no hay una relación directa entre el precio y la zona.
Primero se evaluara de manera conjunta todas las variabes solicitadas.
cor_2 <-base2[,c("preciom","areaconst","estrato","banios","habitaciones","parqueaderos")]
#cor_2
library(GGally)
ggpairs(cor_2, title=" ")
Ahora si realizaremos el modelo:
modelo_in2<- lm(preciom ~ 1, data=base2)
modelo_all2 <- lm(preciom ~ habitaciones + banios + areaconst + parqueaderos+ estrato, data = base2)
summary(modelo_all2)
##
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos +
## estrato, data = base2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1201.45 -42.25 -1.60 36.71 935.81
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -215.05601 13.40840 -16.039 < 2e-16 ***
## habitaciones -22.67919 3.37020 -6.729 2.06e-11 ***
## banios 47.93433 3.01751 15.885 < 2e-16 ***
## areaconst 1.40640 0.04902 28.693 < 2e-16 ***
## parqueaderos 57.18042 3.29246 17.367 < 2e-16 ***
## estrato 54.35821 2.80476 19.381 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 94.47 on 2781 degrees of freedom
## Multiple R-squared: 0.7572, Adjusted R-squared: 0.7568
## F-statistic: 1735 on 5 and 2781 DF, p-value: < 2.2e-16
1.habitac: Un incremento de una unidad en el número de habitaciones se asocia con una disminución de aproximadamente $22.67 millones en el precio de la vivienda, manteniendo constantes las otras variables.
2.banios: Un aumento de una unidad en el número de baños está relacionado con un aumento de proximadamente $47.93 millones en el precio de la vivienda, manteniendo constantes las otras variables.
3.areaconst: Un incremento de una unidad en el área construida está relacionado con un aumento de aproximadamente $1.40 millones en el precio de la vivienda, manteniendo constantes las otras variables.
4.parquea: Un aumento de una unidad en el número de parqueaderos se asocia con un aumento de aproximadamente $57.18 millones en el precio de la vivienda, manteniendo constantes las otras variables.
5.estrato: Un aumento de una unidad en el estrato se asocia con un aumento de aproximadamente $54.35 millones en el precio de la vivienda, manteniendo constantes las otras variables.
6.R-squared (R-cuadrado): El R-cuadrado mide la proporción de la variabilidad en el precio de la vivienda que es explicada por el modelo. Un R-cuadrado de 0.7572 indica que alrededor del 75.72% de la variabilidad en el precio de la vivienda es explicada por las variables independientes incluidas en el modelo.
autoplot(modelo_all2)
#### 4. Supuestos del modelo para e segundo modelo, entrenado con las
viviendas tipo apartamento de la zona sur.
plot(modelo_all2$fitted.values, resid(modelo_all2), xlab = "Valores Ajustados", ylab = "Residuos", main = "Gráfico de Residuos vs. Valores Ajustados")
plot(modelo_all2$fitted.values, sqrt(abs(resid(modelo_all2)/sd(resid(modelo_all2)))), xlab = "Valores Ajustados", ylab = "Raíz Cuadrada de los Residuos Estandarizados", main = "Gráfico de Homocedasticidad")
autoplot(modelo_all2)
shapiro.test(resid(modelo_all2))
##
## Shapiro-Wilk normality test
##
## data: resid(modelo_all2)
## W = 0.7846, p-value < 2.2e-16
vif(modelo_all2)
## habitaciones banios areaconst parqueaderos estrato
## 1.418807 2.481899 2.072688 1.944476 1.741592
datos_sin_atipicos <- base1[-which(abs(resid(modelo_all2)) > 2 * sd(resid(modelo_all2))), ]
De manera resumida podemos encontrar que el valor que nos da en W, esta por debajo de 1, sugiere que los residuos no siguen una distribución Normal, por otro lado el El p-valor es extremadamente bajo, mucho menor que cualquier umbral típico (como 0.05 o 0.01). Esto significa que hay evidencia muy fuerte para rechazar la hipótesis nula del test, que es que los residuos siguen una distribución normal.
dwtest(modelo_all2)
##
## Durbin-Watson test
##
## data: modelo_all2
## DW = 1.5063, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
Para este caso podemos identificar que existe autocorrelación positiva en los residuos de tu modelo. Esto puede afectar la validez de tus resultados, por lo que sería recomendable ajustar tu modelo para manejar este problema.
gqtest(modelo_all2)
##
## Goldfeld-Quandt test
##
## data: modelo_all2
## GQ = 0.9188, df1 = 1388, df2 = 1387, p-value = 0.9426
## alternative hypothesis: variance increases from segment 1 to 2
En este supuesto encontramos que no hay heterocedasticidad en tu modelo de regresión, lo que significa que la varianza de los residuos es constante a lo largo de las observaciones. Esto es positivo para la validez del modelo.
g3=ggplot(base2, aes(preciom, areaconst)) + geom_point() + geom_smooth(method = "lm", level = 0.95, formula = y ~ x)
g4=ggplot(base2, aes(preciom, banios)) + geom_point() + geom_smooth(method = "lm", level = 0.95, formula = y ~ x)
grid.arrange(g3, g4, ncol = 2)
Ahora vamos a validar si el ajuste al modelo anterior tambien se puede proponer para este modelo entrenado con apartamentos de la Zona Sur
datos_sin_atipicos <- base2[-which(abs(resid(modelo_all2)) > 2 * sd(resid(modelo_all2))), ]
Vamos a aplicar el proceso de Forward Stepwise para confirmar cuales podrian ser las mejores variables a usar en este caso.
forward <- step(modelo_in2, direction='forward', scope=formula(modelo_all2), trace=0)
# Visualización de los resultados
forward$anova
## Step Df Deviance Resid. Df Resid. Dev AIC
## 1 NA NA 2786 102222866 29293.22
## 2 + areaconst -1 58732885.4 2785 43489980 26913.38
## 3 + estrato -1 12599342.2 2784 30890638 25962.01
## 4 + parqueaderos -1 3811022.8 2783 27079615 25597.04
## 5 + banios -1 1858794.2 2782 25220821 25400.85
## 6 + habitaciones -1 404098.3 2781 24816723 25357.83
#resultado final del modelo
summary(forward)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios +
## habitaciones, data = base2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1201.45 -42.25 -1.60 36.71 935.81
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -215.05601 13.40840 -16.039 < 2e-16 ***
## areaconst 1.40640 0.04902 28.693 < 2e-16 ***
## estrato 54.35821 2.80476 19.381 < 2e-16 ***
## parqueaderos 57.18042 3.29246 17.367 < 2e-16 ***
## banios 47.93433 3.01751 15.885 < 2e-16 ***
## habitaciones -22.67919 3.37020 -6.729 2.06e-11 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 94.47 on 2781 degrees of freedom
## Multiple R-squared: 0.7572, Adjusted R-squared: 0.7568
## F-statistic: 1735 on 5 and 2781 DF, p-value: < 2.2e-16
De acuerdo al modelo de Steppwise se puede evidenciar que la variable mas relvente para explicar el precio, luego esta el areaconstruida,estrato, parqueaderos, baños y numero de habitaciones.
requerimientos_vivienda2<-data.frame( estrato=c(5,6), areaconst=c(300,300), parqueaderos=c(3,3), banios=c(3,3), habitaciones=c(5,5) )
requerimientos_vivienda2
## estrato areaconst parqueaderos banios habitaciones
## 1 5 300 3 3 5
## 2 6 300 3 3 5
Precio_1_sur<-predict(modelo_all2,data.frame(requerimientos_vivienda2),type="response")
print(paste("Precio del apartamento :", as.character(Precio_1_sur)))
## [1] "Precio del apartamento : 680.603654796031"
## [2] "Precio del apartamento : 734.961864917186"
base2_viviendas_e5<- base2 %>% dplyr::filter(estrato==5,areaconst>=100,parqueaderos>=3,banios>=3,habitaciones>=5,preciom<=850) %>% mutate(promedio_reg=680.6036,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=850-preciom) %>% arrange("areaconst")
base2_viviendas_e5
## # A tibble: 3 × 17
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 7182 Zona S… <NA> 5 730 573 3 8 5
## 2 7512 Zona S… <NA> 5 670 300 3 5 6
## 3 8036 Zona S… <NA> 5 530 256 3 5 5
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## # diferencia_cupo <dbl>
base2_viviendas_e6<- base2 %>% dplyr::filter(estrato==6,areaconst>=100,parqueaderos>=2,banios>=3,habitaciones>=5,preciom<=850) %>% mutate(promedio_reg=734.9618,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=850-preciom) %>% arrange("areaconst")
base2_viviendas_e6
## # A tibble: 1 × 17
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 4266 Zona S… 05 6 700 250 2 4 5
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## # diferencia_cupo <dbl>
aptos<- rbind(base2_viviendas_e5,base2_viviendas_e6)
map <- leaflet(aptos) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Tipo:", tipo, "<br>",
"Latitud:", latitud, "<br>",
"Longitud:", longitud, "<br>",
"Precio:", preciom) # Puedes personalizar el contenido del popup aquí
)
map # Muestra el mapa
set.seed(1234)
n <- nrow(base1)
print(n)
## [1] 722
train_indices <- sample(1:n, size = 0.7 * n)
#print(train_indices)
train_base1 <- base1[train_indices, ]
test_base1 <- base1[-train_indices, ]
dim(train_base1)
## [1] 505 14
dim(test_base1)
## [1] 217 14
Ya con este proceso tenemos separada la base de entrenamiento y prueba, ya con esto procederemos a entrenar el modelo, usando esta base:
modelo_train_b1 <- lm(preciom ~ habitaciones + banios + areaconst + parqueaderos+ estrato, data = train_base1)
summary(modelo_train_b1)
##
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos +
## estrato, data = train_base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -773.91 -81.34 -17.62 40.56 984.01
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -205.96052 36.55256 -5.635 2.94e-08 ***
## habitaciones 3.15010 5.18225 0.608 0.5436
## banios 17.82037 6.91665 2.576 0.0103 *
## areaconst 0.87613 0.05711 15.342 < 2e-16 ***
## parqueaderos 28.87205 7.22893 3.994 7.48e-05 ***
## estrato 69.54357 9.04626 7.688 8.03e-14 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 162.7 on 499 degrees of freedom
## Multiple R-squared: 0.6681, Adjusted R-squared: 0.6647
## F-statistic: 200.9 on 5 and 499 DF, p-value: < 2.2e-16
Seteamos una nueva variable para a NA precionm para posteriormente asignarle el valor de la vivienda calculado por el modelo
# Asignar NA a la variable precio en test_base1
test_base1$preciomn <- NA
Ejecutamos el modelo y le asigans el valor a la variable precio mn
test_base1$preciomn <- predict(modelo_train_b1,test_base1,type="response")
Lo que se puede observar es que el modelo predice valores cercanos al valor encontrado en la base de datos de test para algunos casos y para otros no, es claro que como se evidencio en los anteriores ejericios este modelo requiere ajustes, posiblemente en la selección de las variables del modelo.
set.seed(1234)
n <- nrow(base2)
print(n)
## [1] 2787
train_indices <- sample(1:n, size = 0.7 * n)
#print(train_indices)
train_base2 <- base2[train_indices, ]
test_base2 <- base2[-train_indices, ]
dim(train_base2)
## [1] 1950 14
dim(test_base2)
## [1] 837 14
Ya con este proceso tenemos separada la base de entrenamiento y prueba, ya con esto procederemos a entrenar el modelo, usando esta base:
modelo_train_b2 <- lm(preciom ~ habitaciones + banios + areaconst + parqueaderos+ estrato, data = train_base2)
summary(modelo_train_b2)
##
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos +
## estrato, data = train_base2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -490.19 -38.65 1.10 36.75 807.42
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -202.2336 14.4093 -14.035 < 2e-16 ***
## habitaciones -28.2615 3.6218 -7.803 9.78e-15 ***
## banios 38.2155 3.3163 11.523 < 2e-16 ***
## areaconst 2.0717 0.0634 32.674 < 2e-16 ***
## parqueaderos 38.3821 3.5355 10.856 < 2e-16 ***
## estrato 51.7985 3.0221 17.140 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 86.24 on 1944 degrees of freedom
## Multiple R-squared: 0.7956, Adjusted R-squared: 0.7951
## F-statistic: 1513 on 5 and 1944 DF, p-value: < 2.2e-16
Seteamos una nueva variable para a NA precionm para posteriormente asignarle el valor de la vivienda calculado por el modelo
# Asignar NA a la variable precio en test_base1
test_base2$preciomn <- NA
Ejecutamos el modelo y le asigans el valor a la variable precio mn
test_base2$preciomn <- predict(modelo_train_b2,test_base2,type="response")
Lo que se puede observar es que el modelo predice valores cercanos al valor encontrado en la base de datos de test para algunos casos y para otros no, es claro que como se evidencio en los anteriores ejericios este modelo requiere ajustes, posiblemente en la selección de las variables del modelo.
mse_base1 <- mean((test_base1$preciom - test_base1$preciomn)^2)
print(mse_base1)
## [1] 20359.49
Este resultado de MSE 20359.49 indica que, en promedio, el cuadrado de los errores de predicción es 20359.49, un MSE más bajo es preferible, ya que indica que las predicciones del modelo están más cerca de los valores reales.
mse_base2 <- mean((test_base2$preciom - test_base2$preciomn)^2)
print(mse_base2)
## [1] 14411.17
Este MSE aun cuando es mejor que con la base 1 sigue siendo alto, es importante definitivamente hacer ajustes al medelo porque los valores que arroja la predicción siguen siendo lejanos del los reales.
mae_base1 <- mean(abs(test_base1$preciom - test_base1$preciomn))
print(mae_base1)
## [1] 94.33283
Esto quiere decir que en promedio cada predio se esta alejando del valor real 94.33, el cual es un valor considrable teniendo en cuenta el valor de los precios de las viviendas.
Se puede observar en la base 1 que con las condiciones de vivienda solicitadas en el ejercicio, según la predicción de precio del modelo se pueden encontrar viviendas desde 320 millones para estrato 4 y 398 millones para estrato 5, ahora bien teniendo en cuenta el presupuesto de 350 millones inicialmente por el resultado del modelo solo se tendría la opción de casa en estrato 4, pero si buscamos en promedio con el valor que dio el modelo si se encuentran casas de estrato 5 con estas condiciones
Para la base 2 con las condiciones de vivienda solicitadas en el ejercicio, según la predicción del modelo se pueden encontrar viviendas, exactamente 3 apartamentos con estas condiciones y valor de 680 millones para estrato 5 y de 735 millones para estrato 6, aproximadamente, para este caso el valor máximo que es el de estrato 6 podemos tener el presupuesto suficiente para seleccionar los apartmentos que encontremos en la base, que para este caso con esas condiciones en estrato 5 encontramos 3 y para estrato 6 no se encontró ninguno con las condiciones originales, por esto optamos por hacer una oferta con 2 parqueaderos, para la cual encontramos un apartamento.
Viéndolo desde el punto de vista técnico encontramos que los modelos que se desarrollaron no obtuvieron un buen performance de predicción en ninguno de los casos, donde obtuvo un mejor comportamiento fue con la base de viviendas del Sur, pero tal como lo propusimos en el contenido del ejercicio es importante hacer unos ajustes, tales como Steppwise para seleccionar las mejores variables predictoras para este caso, donde para cada base se detallo y se evidenciaron cuales eran.
Me queda de experiencia de haber realizado los puntos del otro ejercicio donde entrenamos con el 70% de los datos de cada una de las bases y hacemos el test con el 30, que es mas diciente hacer este tipo de ejercicios y por medio de los errores cuadráticos ver las diferencias Vs los datos reales y de esta forma poder llegar a una buena predicción en un modelo de este estilo.