El presente proyecto surge de la necesidad de nuestra cliente Maria gerente de la inmobiliaria C&A, conforme a la solicitud recibida para la compra de dos viviendas con requisitos especificos por parte del usuario final.
Se procedió a realizar todas las etapas de ciclo de vida de la información almacenada en la base, realizando análisis exploratorio de datos, validación de datos faltantes, análisis de correlación e identificación de multicolinealidad, validación de supuestos y coeficientes, propuestas de mejoras al modelo, gráficos explicativos, desarrollo de modelos de regresión enfocados a la predicción de los valores de inmuebles y la identificación de posibles ofertas basadas en las predicciones.
En este desarrollo se resume el informe ejecutivo, y los anexos o evidencias del trabajo desarrollado con gráficos y validaciones que los respaldan.La base de datos de la ciudad de Cali cuenta con 8319 inmuebles, los cuales tienen la siguiente distribución por tipo:
Distribución de inmuebles por zonas ordenados por número.
Distribución de inmuebles por estrato ordenados por número.
Precios estimados según la solicitud de Vivienda 1
Precios estimados según la solicitud de Vivienda 2
Para este punto es importante resaltar que, se hicieron modificaciones en las detecciones dada la baja volumetría de la base y para permitir identificar inmuebles aproximados a la necesidad del usuario. Se identificaron las siguiente propiedades con los siguientes atributos:
id zona piso preciom areaconst parqueaderos banios habitaciones
7471 Zona Norte 02 330 240 2 4 4
1189 Zona Norte 02 330 400 2 5 8
952 Zona Norte 02 330 275 2 3 5
1108 Zona Norte 02 330 260 1 3 4
3043 Zona Norte 02 330 275 2 3 5
Identificación de inmuebles teniendo en cuenta las predicciones y ejecutando procesos automáticos(predict) para la busqueda en Vivienda 1Para este punto es importante resaltar que, se hicieron modificaciones en las detecciones dada la baja volumetría de la base y para permitir identificar inmuebles aproximados a la necesidad del usuario. Se identificaron las siguiente propiedades con los siguientes atributos:
id zona piso preciom areaconst parqueaderos banios habitaciones
4511 Zona Norte 01 275 190 1 2 3
Identificación de inmuebles teniendo en cuenta las predicciones y ejecutando procesos manuales para la busqueda en Vivienda 2Para este punto es importante resaltar que, se hicieron modificaciones en las detecciones dada la baja volumetría de la base y para permitir identificar inmuebles aproximados a la necesidad del usuario. Se identificaron las siguiente propiedades con los siguientes atributos:
id zona piso preciom areaconst parqueaderos banios habitaciones
7512 Zona Sur 02 670 300 3 5 6
7182 Zona Sur 08 730 573 3 8 5
Identificación de inmuebles teniendo en cuenta las predicciones y ejecutando procesos automáticos(predict) para la busqueda en Vivienda 2Para este punto es importante resaltar que, se hicieron modificaciones en las detecciones dada la baja volumetría de la base y para permitir identificar inmuebles aproximados a la necesidad del usuario. Se identificaron las siguiente propiedades con los siguientes atributos:
id zona piso preciom areaconst parqueaderos banios habitaciones
6868 Zona Sur 03 370 300 3 6 5
7512 Zona Sur 02 670 300 3 5 6
Los residuos no siguen una distribución
normal.
Presencia de heterocedasticidad (según la prueba de
Breusch-Pagan).
Autocorrelación positiva en los residuos (según la
prueba de Durbin-Watson).
El presente proyecto permitió ralizar predicciones sobre los constos de inmuebles según la necesidad espuesta por C&A, además, basadandose en las predicciones y los parametros especificos del requerimiento se identificaron casas y apartamentos que sirven para proponerle al cliente en cuestión.
Por otra parte, se realizaron las validaciones de supuestos, coeficientes y se describió como mejorar el modelo para tener mejor rendimiento y que este se vea reflejado en las métricas de desempeño. Se trabajó de forma independiente según lo especificado en la necesidad correspondiente a zonas para que los valores de imputación y las lógicas implementadas no causarán errores en la medición y evaluación del modelo.
Se adjuntan anexos de todas las fases realizadas, distribuidas por tipo y zona.## [1] 8322 13
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id : num [1:8322] 1147 1169 1350 5992 1212 ...
## $ zona : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
## $ piso : chr [1:8322] NA NA NA "02" ...
## $ estrato : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
## $ preciom : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
## $ areaconst : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
## $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
## $ banios : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
## $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
## $ tipo : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
## $ barrio : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
## $ longitud : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ latitud : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
## - attr(*, "spec")=List of 3
## ..$ cols :List of 13
## .. ..$ id : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ zona : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ piso : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ estrato : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ preciom : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ areaconst : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ parqueaderos: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ banios : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ habitaciones: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ tipo : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ barrio : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ longitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ latitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## ..$ default: list()
## .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
## ..$ delim : chr ";"
## ..- attr(*, "class")= chr "col_spec"
## - attr(*, "problems")=<externalptr>
## id zona piso estrato
## Min. : 1 Length:8322 Length:8322 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
## NA's :3 NA's :3
## preciom areaconst parqueaderos banios
## Min. : 58.0 Min. : 30.0 Min. : 1.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 : 2.000 Median : 3.000
## Mean : 433.9 Mean : 174.9 Mean : 1.835 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
## NA's :2 NA's :3 NA's :1605 NA's :3
## habitaciones tipo barrio longitud
## Min. : 0.000 Length:8322 Length:8322 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
## NA's :3 NA's :3
## latitud
## Min. :3.333
## 1st Qu.:3.381
## Median :3.416
## Mean :3.418
## 3rd Qu.:3.452
## Max. :3.498
## NA's :3
## id zona piso estrato preciom areaconst
## 3 3 2638 3 2 3
## parqueaderos banios habitaciones tipo barrio longitud
## 1605 3 3 3 3 3
## latitud
## 3
##
## Apartamento Casa
## 5100 3219
Se puede evidenciar en el gráfico de mapa, que no todos los puntos corresponden a la zona norte, aunque en la base así lo sugiere. Esto puede identificarse por el comportamiento de los puntos en el mapa basados en los atributos Latitud y Longitud.
## # A tibble: 3 × 13
## 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 NA 7 6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
##
## Casa
## Zona Norte 722
## id zona piso estrato preciom areaconst
## 0 0 372 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 287 0 0 0 0 0
## latitud
## 0
En el siguiente mapa, se puede evidenciar que no todas las viviendas de la zona norte se encuentran georreferenciadas correctamente dentro de una misma zona en la ciudad de Calí.
Teniendo en cuenta que en el análisis exploratorio de la zona norte se detectaron valores faltantes en las variables Piso y parqueaderos, se procederá a realizar las imputaciones correspondientes. Por otra parte, cabe resaltar que piso es una variable ordinal, por consiguiente, se tratará como variable categorica.
Convertimos el campo piso y estrato a factor ordenado, dado a que es una variable ordinal y las variables zona, tipo, barrio quedan como factores nominales, dado que, no tienen orden específico.
zona_selec$piso <- factor(
zona_selec$piso,
ordered = TRUE
)
zona_selec$estrato <- factor(
zona_selec$estrato,
ordered = TRUE
)
zona_selec$zona <- factor(zona_selec$zona)
zona_selec$tipo <- factor(zona_selec$tipo)
zona_selec$barrio <- factor(zona_selec$barrio)## spc_tbl_ [722 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id : num [1:722] 1209 1592 4057 4460 6081 ...
## $ zona : Factor w/ 1 level "Zona Norte": 1 1 1 1 1 1 1 1 1 1 ...
## $ piso : Ord.factor w/ 5 levels "01"<"02"<"03"<..: 2 2 2 2 2 2 2 3 NA NA ...
## $ estrato : Ord.factor w/ 4 levels "3"<"4"<"5"<"6": 3 3 4 2 3 2 3 3 1 1 ...
## $ preciom : num [1:722] 320 780 750 625 750 600 420 490 230 190 ...
## $ areaconst : num [1:722] 150 380 445 355 237 160 200 118 160 435 ...
## $ parqueaderos: num [1:722] 2 2 NA 3 2 1 4 2 NA NA ...
## $ banios : num [1:722] 4 3 7 5 6 4 4 4 2 0 ...
## $ habitaciones: num [1:722] 6 3 6 5 6 5 5 4 3 0 ...
## $ tipo : Factor w/ 1 level "Casa": 1 1 1 1 1 1 1 1 1 1 ...
## $ barrio : Factor w/ 103 levels "acopi","alameda del río",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ longitud : num [1:722] -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ latitud : num [1:722] 3.48 3.49 3.39 3.41 3.37 ...
## - attr(*, "spec")=List of 3
## ..$ cols :List of 13
## .. ..$ id : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ zona : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ piso : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ estrato : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ preciom : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ areaconst : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ parqueaderos: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ banios : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ habitaciones: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ tipo : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ barrio : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ longitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ latitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## ..$ default: list()
## .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
## ..$ delim : chr ";"
## ..- attr(*, "class")= chr "col_spec"
## - attr(*, "problems")=<externalptr>
## [1] 372
## [1] 287
# Aplicamos imputación KNN asegurando que 'zona' y 'estrato' no sean modificadas
zona_selec <- kNN(
data = zona_selec,
variable = c("piso", "parqueaderos"), # Solo imputamos estas
dist_var = c("preciom", "banios", "habitaciones", "areaconst"), # Variables numéricas para distancia
k = 5
)
# Eliminamos columnas auxiliares .imp
zona_selec <- zona_selec[, !grepl(".imp$", colnames(zona_selec))]## [1] 0
## [1] 0
p1 <- ggplot(zona_selec, aes(x = areaconst, y = preciom)) +
geom_point(alpha = 0.6, color = "blue") +
labs(title = "Relación entre Precio y Área Construida",
x = "Área Construida (m²)",
y = "Precio de la vivienda (millones)") +
theme_minimal()
# Convertir a gráfico interactivo con plotly
ggplotly(p1)p5 <- ggplot(zona_selec, aes(x = zona, y = preciom, fill = zona)) +
geom_boxplot(alpha = 0.7) +
labs(title = "Distribución del Precio según la Zona",
x = "Zona",
y = "Precio de la vivienda (millones)") +
theme_minimal() +
theme(legend.position = "none") # Oculta la leyenda para evitar redundancia
ggplotly(p5)# Seleccionamos solo las variables numéricas
vivienda_numeric <- zona_selec %>%
select(preciom, areaconst, banios,parqueaderos, habitaciones)
# Calculamos la matriz de correlación
cor_matrix <- cor(vivienda_numeric, use = "complete.obs")
# Mapa de calor de correlaciones
corrplot(cor_matrix, method = "color", type = "upper",
tl.cex = 0.8, tl.srt = 45, addCoef.col = "black", number.cex = 0.7)Para esto, es importante trabajar sobre las variables aplicando dummies a las categóricas estrato y zona; luego calculamos el VIF para detectar multicolinealidad teniendo en cuenta las siguientes reglas: VIF >= 10, Alta colinealidad. VIF >= 5, Colinealidad Media. VIF < 5, Podemos implementar estas variables en nuestro modelo.
# Convertimos 'tipo' y 'estrato' en variables dummy
zona_selec <- dummy_cols(zona_selec, select_columns = c("tipo", "estrato"), remove_selected_columns = TRUE)## id zona piso preciom areaconst parqueaderos banios habitaciones
## 1 1209 Zona Norte 02 320 150 2 4 6
## 2 1592 Zona Norte 02 780 380 2 3 3
## 3 4057 Zona Norte 02 750 445 3 7 6
## 4 4460 Zona Norte 02 625 355 3 5 5
## 5 6081 Zona Norte 02 750 237 2 6 6
## 6 7824 Zona Norte 02 600 160 1 4 5
## barrio longitud latitud tipo_Casa estrato_3 estrato_4 estrato_5 estrato_6
## 1 acopi -76.51341 3.47968 1 0 0 1 0
## 2 acopi -76.51674 3.48721 1 0 0 1 0
## 3 acopi -76.52950 3.38527 1 0 0 0 1
## 4 acopi -76.53179 3.40590 1 0 1 0 0
## 5 acopi -76.54044 3.36862 1 0 0 1 0
## 6 acopi -76.55210 3.42125 1 0 1 0 0
Validamos la colinealidad perfecta, excluimos tipo por ya estar filtrado en la base y estrato 6 ya que se puede calcular con otros estratos
# Verificar colinealidad perfecta
alias(lm(preciom ~ areaconst + habitaciones + parqueaderos + banios +
estrato_3 + estrato_4 + estrato_5 + estrato_6,
data = zona_selec))$Complete## (Intercept) areaconst habitaciones parqueaderos banios estrato_3
## estrato_6 1 0 0 0 0 -1
## estrato_4 estrato_5
## estrato_6 -1 -1
# Definir el modelo solo con las variables explicativas
modelo_vif <- lm(preciom ~ areaconst + habitaciones + parqueaderos + banios + estrato_3 + estrato_4 + estrato_5, data = zona_selec)
# Calcular el VIF
vif(modelo_vif)## areaconst habitaciones parqueaderos banios estrato_3 estrato_4
## 1.552373 1.650502 1.393091 2.048797 4.547384 3.240641
## estrato_5
## 3.821439
modelo <- lm(preciom ~ areaconst + habitaciones + parqueaderos + banios +
estrato_3 + estrato_4 + estrato_5,
data = zona_selec)
# Ver resumen del modelo
summary(modelo)##
## Call:
## lm(formula = preciom ~ areaconst + habitaciones + parqueaderos +
## banios + estrato_3 + estrato_4 + estrato_5, data = zona_selec)
##
## Residuals:
## Min 1Q Median 3Q Max
## -892.91 -69.63 -14.36 40.98 1024.21
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 336.05814 30.28062 11.098 < 2e-16 ***
## areaconst 0.78532 0.04266 18.411 < 2e-16 ***
## habitaciones 0.66131 4.02282 0.164 0.869471
## parqueaderos 30.87048 5.53324 5.579 3.43e-08 ***
## banios 18.94654 5.37561 3.525 0.000451 ***
## estrato_3 -317.27805 26.02820 -12.190 < 2e-16 ***
## estrato_4 -241.51109 24.73335 -9.765 < 2e-16 ***
## estrato_5 -192.59861 23.08885 -8.342 3.77e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 153.7 on 714 degrees of freedom
## Multiple R-squared: 0.6753, Adjusted R-squared: 0.6721
## F-statistic: 212.1 on 7 and 714 DF, p-value: < 2.2e-16
Multiple R-squared: Un 67.53%, indica que el modelo tiene buen poder de predicción, pero hay margen para mejorarlo.
Adjusted R-squared : 67.21%, significa que no hay muchas variables innecesarias en el modelo.
Intercepto: Cuando todas las variables son cero, el precio base es de 336.06 millones.
Área construida: Por cada metro cuadrado adicional el precio aumenta en 0.785 millones, es altamente significativa.
Habitaciones: No es significativa, no tiene impacto claro en el precio.
Parqueaderos: Por cada parqueadero adicional el precio aumenta en 30.87 millones, es altamente significativa.
Baños: Por cada baño adicional el precio aumenta en 18.95 millones, es altamente significativa.
Los coeficientes de estrato_3, estrato_4 y estrato_5 son negativos; esto indica que vivir en un estrato mas bajo reduce significativamente el precio.
Como el p-valor es < 2.2e-16, podemos rechazar la hipótesis nula de que todas las variables sean 0 (lo que indica que el modelo tiene validez estadística).
Se podría eliminar el atributo habitaciones, dado que, su p-valor es 0.869 indicando que no tiene relación clara con el precio.
Transformaciones logaritmicas.
Si el p-valor es mayor que el nivel de significancia del 5%, no se rechaza la hipótesis nula, indicando que los residuos son normales.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere que los residuos no son normales.
##
## Shapiro-Wilk normality test
##
## data: resid(modelo)
## W = 0.83366, p-value < 2.2e-16
El p-valor es menor que el nivel de significancia por tanto se rechaza la hipótesis nula, que establece que los residuos tienen una distribución normal. Es decir, igual que el Anderson-Darling los residuos del modelo no son normales.
Si el p-valor es mayor que el nivel de significancia del 5%, no se rechaza la hipótesis nula, indicando que los residuos siguen una distribución normal.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere que los residuos no son normales.
##
## Anderson-Darling normality test
##
## data: modelo$residuals
## A = 26.922, p-value < 2.2e-16
Dado que el p-valor es menor que un nivel de significancia, se rechaza la hipótesis nula de que los residuos siguen una distribución normal.
Si el p-valor es mayor que el nivel de significancia (por ejemplo, 0.05), no se rechaza la hipótesis nula, indicando homocedasticidad.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere heterocedasticidad en los residuos.
##
## studentized Breusch-Pagan test
##
## data: modelo
## BP = 135.45, df = 7, p-value < 2.2e-16
Si el p-valor es mayor que un nivel de significancia del 5%, NO se rechaza H₀, lo que indica que no hay evidencia de heterocedasticidad.
Si el p-valor es menor que el nivel de significancia del 5%, SE rechaza H₀, lo que sugiere que hay evidencia de heterocedasticidad.
##
## Goldfeld-Quandt test
##
## data: modelo
## GQ = 1.1593, df1 = 353, df2 = 353, p-value = 0.08266
## alternative hypothesis: variance increases from segment 1 to 2
El estadístico de Durbin-Watson (DW) varía entre 0 y 4:
##
## Durbin-Watson test
##
## data: modelo
## DW = 1.7211, p-value = 6.634e-05
## alternative hypothesis: true autocorrelation is greater than 0
# Crear un dataframe con las características de la Vivienda 1 en estrato 4
vivienda1_estrato4 <- data.frame(
areaconst = 200,
habitaciones = 4,
parqueaderos = 1,
banios = 2,
estrato_3 = 0, # No es estrato 3
estrato_4 = 1, # Es estrato 4
estrato_5 = 0 # No es estrato 5
)
# Crear un dataframe con las características de la Vivienda 1 en estrato 5
vivienda1_estrato5 <- data.frame(
areaconst = 200,
habitaciones = 4,
parqueaderos = 1,
banios = 2,
estrato_3 = 0, # No es estrato 3
estrato_4 = 0, # No es estrato 4
estrato_5 = 1 # Es estrato 5
)Se puede evienciar que, si el estrato es 5, el valor de la propiedad sería de 371.93 millones, por consiguiente, supera el credito preaprobado con valor de 350 millones. Por su parte, en estrato 4 el precio de la vivienda sería de 323.02 millones, lo cuál está en el rango del credito preaprobado.
# Predecir el precio para Vivienda 1 en estrato 4
precio_pred_estrato4 <- predict(modelo, newdata = vivienda1_estrato4)
# Predecir el precio para Vivienda 1 en estrato 5
precio_pred_estrato5 <- predict(modelo, newdata = vivienda1_estrato5)
# Mostrar los resultados
print(paste("Precio estimado para Vivienda 1 en estrato 4:", round(precio_pred_estrato4, 2), "millones"))## [1] "Precio estimado para Vivienda 1 en estrato 4: 323.02 millones"
print(paste("Precio estimado para Vivienda 1 en estrato 5:", round(precio_pred_estrato5, 2), "millones"))## [1] "Precio estimado para Vivienda 1 en estrato 5: 371.93 millones"
Para este punto es importante resaltar que, según las predicciones la vivienda deber ser estrato 4; debido a que, el valor está dentro del rango permitido por el credito preaprobado; por consiguiente no usaremos la predicción de estrato 5 porque el valor de la propiedad excede el crédito.
Por otra parte, este primer análisis se hace tomando el valor predicho y bsucarlos en la base segmentada por la zona especifica con los valores requeridos y el valor predicho. No nos muestra predicciones.
ofertas_potenciales <- zona_selec %>%
filter(areaconst >= 200,
parqueaderos >= 1,
banios >= 2,
habitaciones >= 4,
between(preciom, precio_pred_estrato4, 350)) %>% # Ahora filtramos con el precio predicho
arrange(preciom) # Ordenamos por precio predicho ascendente
# Seleccionar las 5 mejores ofertas
ofertas_potenciales <- head(ofertas_potenciales, 5)
# Mostrar las ofertas seleccionadas
print(ofertas_potenciales)## id zona piso preciom areaconst parqueaderos banios habitaciones
## 1 7471 Zona Norte 02 330 240 2 4 4
## 2 1189 Zona Norte 02 330 400 2 5 8
## 3 952 Zona Norte 02 330 275 2 3 5
## 4 1108 Zona Norte 02 330 260 1 3 4
## 5 3043 Zona Norte 02 330 275 2 3 5
## barrio longitud latitud tipo_Casa estrato_3 estrato_4 estrato_5
## 1 acopi -76.54980 3.39758 1 0 1 0
## 2 la floresta -76.51300 3.44400 1 1 0 0
## 3 la merced -76.50647 3.47516 1 0 1 0
## 4 la merced -76.51060 3.48108 1 0 1 0
## 5 la merced -76.52350 3.48329 1 0 0 1
## estrato_6
## 1 0
## 2 0
## 3 0
## 4 0
## 5 0
# Crear un mapa con las ofertas potenciales
mapa_ofertas <- leaflet(ofertas_potenciales) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitud, lat = ~latitud,
radius = 6, color = "blue",
label = ~paste("Precio Predicho: ", round(precio_pred_estrato4, 2), "millones<br>",
"Área: ", areaconst, "m²<br>",
"Parqueaderos: ", parqueaderos, "<br>",
"Baños: ", banios),
popup = ~paste("<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio Predicho:</b> ", round(precio_pred_estrato4, 2), "millones<br>",
"<b>Área:</b> ", areaconst, "m²<br>",
"<b>Estrato:</b> 4<br>",
"<b>Parqueaderos:</b> ", parqueaderos, "<br>",
"<b>Baños:</b> ", banios, "<br>",
"<b>Habitaciones:</b> ", habitaciones)
)
# Mostrar el mapa
mapa_ofertasEn este caso hacemos la predicción con el método predict aplicado a las propiedas y filtrando por las predicciones anteriores.
Podemos evidenciar que la propiedad con ID 4511 es la predicción y procedemos a graficarla en el mapa.
# Generar las predicciones para todas las viviendas
zona_selec$precio_predicho <- predict(modelo, newdata = zona_selec)
# Filtrar viviendas con precios predichos similares o menores a Vivienda 1 (323.02 millones)
ofertas_potenciales <- zona_selec %>%
filter(estrato_4 == 1,
areaconst >= 160 & areaconst <= 240,
parqueaderos <= 2,
banios >= 1 & banios <= 2,
habitaciones >= 3 & habitaciones <= 5,
precio_predicho <= precio_pred_estrato4) %>%
arrange(precio_predicho)
# Seleccionar las 5 mejores ofertas
ofertas_potenciales <- head(ofertas_potenciales, 5)
# Mostrar los resultados
print(ofertas_potenciales)## id zona piso preciom areaconst parqueaderos banios habitaciones
## 1 4511 Zona Norte 01 275 190 1 2 3
## barrio longitud latitud tipo_Casa estrato_3 estrato_4 estrato_5 estrato_6
## 1 acopi -76.53198 3.45165 1 0 1 0 0
## precio_predicho
## 1 314.5046
# Crear un mapa con las ofertas potenciales
mapa_ofertas <- leaflet(ofertas_potenciales) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitud, lat = ~latitud,
radius = 6, color = "blue",
label = ~paste("Precio Predicho: ", round(precio_predicho, 2), "millones<br>",
"Área: ", areaconst, "m²<br>",
"Parqueaderos: ", parqueaderos, "<br>",
"Baños: ", banios),
popup = ~paste("<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio Predicho:</b> ", round(precio_predicho, 2), "millones<br>",
"<b>Área:</b> ", areaconst, "m²<br>",
"<b>Estrato:</b> 4<br>",
"<b>Parqueaderos:</b> ", parqueaderos, "<br>",
"<b>Baños:</b> ", banios, "<br>",
"<b>Habitaciones:</b> ", habitaciones)
)
# Mostrar el mapa
mapa_ofertas## # A tibble: 3 × 13
## 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
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
##
## Apartamento
## Zona Sur 2787
## id zona piso estrato preciom areaconst
## 0 0 622 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 406 0 0 0 0 0
## latitud
## 0
Se puede evidenciar en el gráfico de mapa, que no todos los puntos corresponden a la zona sur, aunque en la base así lo sugiere. Esto puede identificarse por el comportamiento de los puntos en el mapa basados en los atributos Latitud y Longitud.
Teniendo en cuenta que en el análisis exploratorio de la zona norte se detectaron valores faltantes en las variables Piso y parqueaderos, se procederá a realizar las imputaciones correspondientes. Por otra parte, cabe resaltar que piso es una variable ordinal, por consiguiente, se tratará como variable categorica.
Convertimos el campo piso y estrato a factor ordenado, dado a que es una variable ordinal y las variables zona, tipo, barrio quedan como factores nominales, dado que, no tienen orden específico.
zona_selec$piso <- factor(
zona_selec$piso,
ordered = TRUE
)
zona_selec$estrato <- factor(
zona_selec$estrato,
ordered = TRUE
)
zona_selec$zona <- factor(zona_selec$zona)
zona_selec$tipo <- factor(zona_selec$tipo)
zona_selec$barrio <- factor(zona_selec$barrio)## spc_tbl_ [2,787 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id : num [1:2787] 5098 698 8199 1241 5370 ...
## $ zona : Factor w/ 1 level "Zona Sur": 1 1 1 1 1 1 1 1 1 1 ...
## $ piso : Ord.factor w/ 12 levels "01"<"02"<"03"<..: 5 2 NA NA NA 6 8 NA NA NA ...
## $ estrato : Ord.factor w/ 4 levels "3"<"4"<"5"<"6": 2 1 4 1 1 2 1 1 1 2 ...
## $ preciom : num [1:2787] 290 78 875 135 135 220 210 105 115 220 ...
## $ areaconst : num [1:2787] 96 40 194 117 78 75 72 68 58 84 ...
## $ parqueaderos: num [1:2787] 1 1 2 NA NA 1 2 NA 1 NA ...
## $ banios : num [1:2787] 2 1 5 2 1 2 2 2 2 2 ...
## $ habitaciones: num [1:2787] 3 2 3 3 3 3 3 3 2 3 ...
## $ tipo : Factor w/ 1 level "Apartamento": 1 1 1 1 1 1 1 1 1 1 ...
## $ barrio : Factor w/ 141 levels "acopi","aguablanca",..: 1 2 3 4 4 5 5 5 5 6 ...
## $ longitud : num [1:2787] -76.5 -76.5 -76.6 -76.5 -76.5 ...
## $ latitud : num [1:2787] 3.45 3.4 3.46 3.44 3.44 ...
## - attr(*, "spec")=List of 3
## ..$ cols :List of 13
## .. ..$ id : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ zona : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ piso : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ estrato : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ preciom : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ areaconst : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ parqueaderos: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ banios : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ habitaciones: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ tipo : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ barrio : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ longitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ latitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## ..$ default: list()
## .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
## ..$ delim : chr ";"
## ..- attr(*, "class")= chr "col_spec"
## - attr(*, "problems")=<externalptr>
## [1] 622
## [1] 406
# Aplicamos imputación KNN asegurando que 'zona' y 'estrato' no sean modificadas
zona_selec <- kNN(
data = zona_selec,
variable = c("piso", "parqueaderos"), # Solo imputamos estas
dist_var = c("preciom", "banios", "habitaciones", "areaconst"), # Variables numéricas para distancia
k = 5
)
# Eliminamos columnas auxiliares .imp
zona_selec <- zona_selec[, !grepl(".imp$", colnames(zona_selec))]## [1] 0
## [1] 0
p1 <- ggplot(zona_selec, aes(x = areaconst, y = preciom)) +
geom_point(alpha = 0.6, color = "blue") +
labs(title = "Relación entre Precio y Área Construida",
x = "Área Construida (m²)",
y = "Precio de la vivienda (millones)") +
theme_minimal()
# Convertir a gráfico interactivo con plotly
ggplotly(p1)p5 <- ggplot(zona_selec, aes(x = zona, y = preciom, fill = zona)) +
geom_boxplot(alpha = 0.7) +
labs(title = "Distribución del Precio según la Zona",
x = "Zona",
y = "Precio de la vivienda (millones)") +
theme_minimal() +
theme(legend.position = "none") # Oculta la leyenda para evitar redundancia
ggplotly(p5)# Seleccionamos solo las variables numéricas
vivienda_numeric <- zona_selec %>%
select(preciom, areaconst, banios,parqueaderos, habitaciones)
# Calculamos la matriz de correlación
cor_matrix <- cor(vivienda_numeric, use = "complete.obs")
# Mapa de calor de correlaciones
corrplot(cor_matrix, method = "color", type = "upper",
tl.cex = 0.8, tl.srt = 45, addCoef.col = "black", number.cex = 0.7)Para esto, es importante trabajar sobre las variables aplicando dummies a las categóricas estrato y zona; luego calculamos el VIF para detectar multicolinealidad teniendo en cuenta las siguientes reglas: VIF >= 10, Alta colinealidad. VIF >= 5, Colinealidad Media. VIF < 5, Podemos implementar estas variables en nuestro modelo.
# Convertimos 'tipo' y 'estrato' en variables dummy
zona_selec <- dummy_cols(zona_selec, select_columns = c("tipo", "estrato"), remove_selected_columns = TRUE)## id zona piso preciom areaconst parqueaderos banios habitaciones
## 1 5098 Zona Sur 05 290 96 1 2 3
## 2 698 Zona Sur 02 78 40 1 1 2
## 3 8199 Zona Sur 05 875 194 2 5 3
## 4 1241 Zona Sur 03 135 117 1 2 3
## 5 5370 Zona Sur 03 135 78 1 1 3
## 6 6975 Zona Sur 06 220 75 1 2 3
## barrio longitud latitud tipo_Apartamento estrato_3 estrato_4
## 1 acopi -76.53464 3.44987 1 0 1
## 2 aguablanca -76.50100 3.40000 1 1 0
## 3 aguacatal -76.55700 3.45900 1 0 0
## 4 alameda -76.51400 3.44100 1 1 0
## 5 alameda -76.53600 3.43600 1 1 0
## 6 alférez real -76.54627 3.39109 1 0 1
## estrato_5 estrato_6
## 1 0 0
## 2 0 0
## 3 0 1
## 4 0 0
## 5 0 0
## 6 0 0
Validamos la colinealidad perfecta, excluimos tipo por ya estar filtrado en la base y estrato 3 ya que se puede calcular con otros estratos.
# Verificar colinealidad perfecta
alias(lm(preciom ~ areaconst + habitaciones + parqueaderos + banios +
estrato_3 + estrato_4 + estrato_5 + estrato_6,
data = zona_selec))$Complete## (Intercept) areaconst habitaciones parqueaderos banios estrato_3
## estrato_6 1 0 0 0 0 -1
## estrato_4 estrato_5
## estrato_6 -1 -1
# Definir el modelo solo con las variables explicativas
modelo_vif <- lm(preciom ~ areaconst + habitaciones + parqueaderos + banios + estrato_4 + estrato_5 + estrato_6, data = zona_selec)
# Calcular el VIF
vif(modelo_vif)## areaconst habitaciones parqueaderos banios estrato_4 estrato_5
## 2.160350 1.454313 1.884140 2.561924 4.074578 4.257006
## estrato_6
## 3.984241
modelo <- lm(preciom ~ areaconst + habitaciones + parqueaderos + banios +
estrato_4 + estrato_5 + estrato_6,
data = zona_selec)
# Ver resumen del modelo
summary(modelo)##
## Call:
## lm(formula = preciom ~ areaconst + habitaciones + parqueaderos +
## banios + estrato_4 + estrato_5 + estrato_6, data = zona_selec)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1059.47 -36.05 -2.33 34.83 899.30
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -43.17127 10.08063 -4.283 1.91e-05 ***
## areaconst 1.28958 0.04624 27.886 < 2e-16 ***
## habitaciones -12.00833 3.15317 -3.808 0.000143 ***
## parqueaderos 64.32633 3.54277 18.157 < 2e-16 ***
## banios 39.11496 2.83311 13.806 < 2e-16 ***
## estrato_4 28.41974 6.83880 4.156 3.34e-05 ***
## estrato_5 54.11112 7.06401 7.660 2.55e-14 ***
## estrato_6 206.48160 8.87574 23.264 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 87.3 on 2779 degrees of freedom
## Multiple R-squared: 0.7928, Adjusted R-squared: 0.7923
## F-statistic: 1519 on 7 and 2779 DF, p-value: < 2.2e-16
Multiple R-squared: Un 79.28%, indica que el modelo tiene buen poder de predicción, pero hay margen para mejorarlo.
Adjusted R-squared : 79.23%, significa que no hay muchas variables innecesarias en el modelo.
Intercepto: Cuando todas las variables son 0, el precio base es -43.17 millones. Este valor negativo no tiene sentido realista, lo que indica que el modelo podría mejorar con una transformación.
Área construida: Por cada metro cuadrado adicional el precio aumenta en 1.29 millones, es altamente significativa.
Habitaciones: Por cada habitación adicional, el precio disminuye en 12 millones. Ahora es significativa, lo que indica que más habitaciones podrían estar asociadas con menor precio (quizás porque las viviendas más grandes y costosas tienen menos habitaciones y más áreas comunes).
Parqueaderos: Por cada parqueadero adicional el precio aumenta en 64.33 millones, es altamente significativa.
Baños: Por cada baño adicional el precio aumenta en 39.11 millones, es altamente significativa.
Los coeficientes de estrato_3, estrato_4 y estrato_5 son negativos; esto indica que vivir en un estrato mas bajo reduce significativamente el precio.
Como el p-valor es < 2.2e-16, podemos rechazar la hipótesis nula de que todas las variables sean 0 (lo que indica que el modelo tiene validez estadística).
Si el p-valor es mayor que el nivel de significancia del 5%, no se rechaza la hipótesis nula, indicando que los residuos son normales.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere que los residuos no son normales.
##
## Shapiro-Wilk normality test
##
## data: resid(modelo)
## W = 0.77438, p-value < 2.2e-16
El p-valor es menor que el nivel de significancia por tanto se rechaza la hipótesis nula, que establece que los residuos tienen una distribución normal. Es decir, igual que el Anderson-Darling los residuos del modelo no son normales.
Si el p-valor es mayor que el nivel de significancia del 5%, no se rechaza la hipótesis nula, indicando que los residuos siguen una distribución normal.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere que los residuos no son normales.
##
## Anderson-Darling normality test
##
## data: modelo$residuals
## A = 91.653, p-value < 2.2e-16
Dado que el p-valor es menor que un nivel de significancia, se rechaza la hipótesis nula de que los residuos siguen una distribución normal.
Si el p-valor es mayor que el nivel de significancia (por ejemplo, 0.05), no se rechaza la hipótesis nula, indicando homocedasticidad.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere heterocedasticidad en los residuos.
##
## studentized Breusch-Pagan test
##
## data: modelo
## BP = 780.92, df = 7, p-value < 2.2e-16
Si el p-valor es mayor que un nivel de significancia del 5%, NO se rechaza H₀, lo que indica que no hay evidencia de heterocedasticidad.
Si el p-valor es menor que el nivel de significancia del 5%, SE rechaza H₀, lo que sugiere que hay evidencia de heterocedasticidad.
##
## Goldfeld-Quandt test
##
## data: modelo
## GQ = 0.90591, df1 = 1386, df2 = 1385, p-value = 0.967
## alternative hypothesis: variance increases from segment 1 to 2
El estadístico de Durbin-Watson (DW) varía entre 0 y 4:
##
## Durbin-Watson test
##
## data: modelo
## DW = 1.7101, p-value = 7.042e-15
## alternative hypothesis: true autocorrelation is greater than 0
vivienda2_estrato5 <- data.frame(
areaconst = 300,
habitaciones = 5,
parqueaderos = 3,
banios = 3,
estrato_4 = 0, # No es estrato 3
estrato_5 = 1, # Es estrato 4
estrato_6 = 0 # No es estrato 5
)
vivienda2_estrato6 <- data.frame(
areaconst = 300,
habitaciones = 5,
parqueaderos = 3,
banios = 3,
estrato_4 = 0, # No es estrato 3
estrato_5 = 0, # No es estrato 4
estrato_6 = 1 # Es estrato 5
)Se puede evienciar que, si el estrato es 5, el valor de la propiedad sería de 648.09 millones.Por su parte, en estrato 6 el precio de la vivienda sería de 800.47 millones, ambos valores está en el rango del credito preaprobado.
# Predecir el precio para Vivienda 2 en estrato 5
precio2_pred_estrato5 <- predict(modelo, newdata = vivienda2_estrato5)
# Predecir el precio para Vivienda 2 en estrato 6
precio2_pred_estrato6 <- predict(modelo, newdata = vivienda2_estrato6)
# Mostrar los resultados
print(paste("Precio estimado para Vivienda 2 en estrato 5:", round(precio2_pred_estrato5, 2), "millones"))## [1] "Precio estimado para Vivienda 2 en estrato 5: 648.09 millones"
print(paste("Precio estimado para Vivienda 2 en estrato 6:", round(precio2_pred_estrato6, 2), "millones"))## [1] "Precio estimado para Vivienda 2 en estrato 6: 800.47 millones"
Para este punto es importante resaltar que, según las predicciones ambas predicciones según el estrato se encuentran dentro del rango del credito preaprobado que es de 850 millones.
ofertas_potenciales <- zona_selec %>%
filter(areaconst >= 300,
parqueaderos >= 3,
banios >= 3,
habitaciones >= 5,
between(preciom, precio2_pred_estrato5, 850)) %>%
arrange(preciom)
ofertas_potenciales <- head(ofertas_potenciales, 5)
print(ofertas_potenciales)## id zona piso preciom areaconst parqueaderos banios habitaciones
## 1 7512 Zona Sur 02 670 300 3 5 6
## 2 7182 Zona Sur 08 730 573 3 8 5
## barrio longitud latitud tipo_Apartamento estrato_3 estrato_4 estrato_5
## 1 seminario -76.550 3.409 1 0 0 1
## 2 guadalupe -76.548 3.408 1 0 0 1
## estrato_6
## 1 0
## 2 0
mapa_ofertas <- leaflet(ofertas_potenciales) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitud, lat = ~latitud,
radius = 6, color = "blue",
label = ~paste("Precio Predicho: ", round(precio2_pred_estrato5, 2), "millones<br>",
"Área: ", areaconst, "m²<br>",
"Parqueaderos: ", parqueaderos, "<br>",
"Baños: ", banios),
popup = ~paste("<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio Predicho:</b> ", round(precio2_pred_estrato5, 2), "millones<br>",
"<b>Área:</b> ", areaconst, "m²<br>",
"<b>Estrato:</b> 4<br>",
"<b>Parqueaderos:</b> ", parqueaderos, "<br>",
"<b>Baños:</b> ", banios, "<br>",
"<b>Habitaciones:</b> ", habitaciones)
)
mapa_ofertasPor otra parte, este primer análisis se hace tomando el valor predicho y buscarlos en la base segmentada por la zona especifica con los valores requeridos y el valor predicho. No nos muestra predicciones.
ofertas_potenciales <- zona_selec %>%
filter(areaconst >= 300,
parqueaderos >= 3,
banios >= 3,
habitaciones >= 5,
between(preciom, precio2_pred_estrato6, 850)) %>%
arrange(preciom)
ofertas_potenciales <- head(ofertas_potenciales, 5)
print(ofertas_potenciales)## [1] id zona piso preciom
## [5] areaconst parqueaderos banios habitaciones
## [9] barrio longitud latitud tipo_Apartamento
## [13] estrato_3 estrato_4 estrato_5 estrato_6
## <0 rows> (o 0- extensión row.names)
En este caso hacemos la predicción con el método predict aplicado a las propiedas y filtrando por las predicciones anteriores solo del estrato 5.
zona_selec$precio_predicho <- predict(modelo, newdata = zona_selec)
ofertas_potenciales <- zona_selec %>%
filter(areaconst >= 300,
parqueaderos >= 3,
banios >= 3,
habitaciones >= 5,
precio_predicho <= precio2_pred_estrato5) %>%
arrange(precio_predicho)
ofertas_potenciales <- head(ofertas_potenciales, 5)
print(ofertas_potenciales)## [1] id zona piso preciom
## [5] areaconst parqueaderos banios habitaciones
## [9] barrio longitud latitud tipo_Apartamento
## [13] estrato_3 estrato_4 estrato_5 estrato_6
## [17] precio_predicho
## <0 rows> (o 0- extensión row.names)
mapa_ofertas <- leaflet(ofertas_potenciales) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitud, lat = ~latitud,
radius = 6, color = "blue",
label = ~paste("Precio Predicho: ", round(precio_predicho, 2), "millones<br>",
"Área: ", areaconst, "m²<br>",
"Parqueaderos: ", parqueaderos, "<br>",
"Baños: ", banios),
popup = ~paste("<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio Predicho:</b> ", round(precio_predicho, 2), "millones<br>",
"<b>Área:</b> ", areaconst, "m²<br>",
"<b>Estrato:</b> 4<br>",
"<b>Parqueaderos:</b> ", parqueaderos, "<br>",
"<b>Baños:</b> ", banios, "<br>",
"<b>Habitaciones:</b> ", habitaciones)
)
mapa_ofertasEn este caso hacemos la predicción con el método predict aplicado a las propiedas y filtrando por las predicciones anteriores solo del estrato 6.
zona_selec$precio_predicho <- predict(modelo, newdata = zona_selec)
ofertas_potenciales <- zona_selec %>%
filter(areaconst >= 300,
parqueaderos >= 3,
banios >= 3,
habitaciones >= 5,
precio_predicho <= precio2_pred_estrato6) %>%
arrange(precio_predicho)
ofertas_potenciales <- head(ofertas_potenciales, 5)
print(ofertas_potenciales)## id zona piso preciom areaconst parqueaderos banios habitaciones
## 1 6868 Zona Sur 03 370 300 3 6 5
## 2 7512 Zona Sur 02 670 300 3 5 6
## barrio longitud latitud tipo_Apartamento estrato_3 estrato_4 estrato_5
## 1 melendez -76.54537 3.37812 1 1 0 0
## 2 seminario -76.55000 3.40900 1 0 0 1
## estrato_6 precio_predicho
## 1 0 711.3284
## 2 0 714.3162
mapa_ofertas <- leaflet(ofertas_potenciales) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitud, lat = ~latitud,
radius = 6, color = "blue",
label = ~paste("Precio Predicho: ", round(precio_predicho, 2), "millones<br>",
"Área: ", areaconst, "m²<br>",
"Parqueaderos: ", parqueaderos, "<br>",
"Baños: ", banios),
popup = ~paste("<b>Barrio:</b> ", barrio, "<br>",
"<b>Precio Predicho:</b> ", round(precio_predicho, 2), "millones<br>",
"<b>Área:</b> ", areaconst, "m²<br>",
"<b>Estrato:</b> 4<br>",
"<b>Parqueaderos:</b> ", parqueaderos, "<br>",
"<b>Baños:</b> ", banios, "<br>",
"<b>Habitaciones:</b> ", habitaciones)
)
mapa_ofertas