María, agente de bienes raíces con una vasta experiencia en el sector, ha recibido una solicitud de asesoría para la compra de dos viviendas por parte de una compañía internacional. Esta compañía desea ubicar a dos de sus empleados con sus familias en la ciudad de Cali. Las solicitudes incluyen una serie de características específicas para las viviendas, tanto en términos de estructura como de ubicación y precio. En este informe, se presenta un análisis detallado de las ofertas disponibles en el mercado que cumplen con las características solicitadas.
El mercado inmobiliario en Cali ha experimentado una disminución en las ventas de bienes raíces en lo corrido del año, influenciado por las tensiones políticas y sociales. Sin embargo, se espera una recuperación en el corto plazo con la reactivación económica. En este contexto, se ha realizado un análisis exhaustivo de las ofertas disponibles, utilizando técnicas de modelación y análisis de datos para identificar las opciones más viables para la compañía internacional.
Se realizó un análisis exploratorio de las viviendas disponibles en las zonas Norte y Sur de Cali, utilizando variables clave como área construida, estrato, número de baños, número de habitaciones, y precio. Los resultados indican una correlación significativa entre el precio de la vivienda y las variables mencionadas. En particular, se observó que:
Área construida y número de habitaciones son las variables con mayor correlación positiva con el precio. Estrato también muestra una correlación positiva, aunque ligeramente más baja. Número de baños y parqueaderos también influyen positivamente en el precio, pero en menor medida. Estas correlaciones confirman la importancia de estas variables en la determinación del precio de las viviendas.
Se estimaron modelos de regresión lineal múltiple para predecir el precio de las viviendas con base en las variables mencionadas. Los coeficientes del modelo son estadísticamente significativos y reflejan el impacto esperado de cada variable en el precio de la vivienda.
En particular:
Área construida: Un aumento en el área construida resulta en un aumento significativo en el precio de la vivienda. Estrato: Viviendas en estratos más altos tienen precios significativamente mayores. Número de habitaciones: Cada habitación adicional aumenta el precio de manera considerable. R² del modelo: El modelo explica un porcentaje considerable de la variabilidad en los precios, lo que sugiere un buen ajuste.
Primera Solicitud (Casa en Zona Norte) Para la primera solicitud, que busca una casa en la Zona Norte con un crédito pre-aprobado de 350 millones de pesos, se identificaron varias ofertas que cumplen con estos criterios. Las predicciones del modelo sugieren que estas opciones están dentro del rango de precio accesible para la compañía. Las propiedades sugeridas tienen un precio estimado que se ajusta al presupuesto y cumplen con las especificaciones de área, estrato, y número de habitaciones.
Segunda Solicitud (Apartamento en Zona Sur) En el caso de la segunda solicitud, que busca un apartamento en la Zona Sur con un crédito pre-aprobado de 850 millones de pesos, también se identificaron múltiples opciones viables. Las ofertas seleccionadas no solo cumplen con los requisitos de espacio y ubicación, sino que también se ajustan al rango de precio esperado, lo que las convierte en opciones altamente recomendadas.
Oferta 1: Se recomienda comprar una casa en la Zona Norte, dada su excelente relación precio-calidad y el ajuste preciso al presupuesto de 350 millones. El precio predicho para la primera solicitud es: 312.1 millones de pesos
1. Ecuación del Modelo: El modelo predice el precio de una vivienda (preciompreciom) en función de cinco variables: área construida (areaconstareaconst), estrato (estratoestrato), número de parqueaderos (parqueaderosparqueaderos), número de baños (baniosbanios), y número de habitaciones (habitacioneshabitaciones).
2. Coeficientes:
Intercepto (-238.17): El precio base (cuando todas las variables son cero) sería negativo, lo cual no es interpretativamente significativo en este contexto, pero se debe a la naturaleza del modelo.
Área construida (0.676730.67673): Por cada metro cuadrado adicional, el precio de la vivienda aumenta en promedio 0.68 millones de pesos.
Estrato (80.6380.63): Cada incremento en el estrato aumenta el precio en aproximadamente 80.63 millones de pesos.
Parqueaderos (24.0124.01): Cada parqueadero adicional aumenta el precio en 24.01 millones de pesos.
Baños (18.9018.90): Cada baño adicional incrementa el precio en 18.90 millones de pesos.
Habitaciones (7.657.65): Este coeficiente no es estadísticamente significativo (p=0.177p=0.177), indicando que el número de habitaciones no tiene un impacto claro en el precio.
3. Significación Estadística:
Área construida, estrato, parqueaderos y baños tienen coeficientes altamente significativos (p<0.05p<0.05), lo que indica que estas variables están fuertemente asociadas con el precio de la vivienda.
Número de habitaciones no es estadísticamente significativo (p=0.177p=0.177), lo que sugiere que no es un buen predictor del precio en este modelo.
4. Calidad del Modelo:
R2=0.6041R2=0.6041: Aproximadamente el 60.41% de la variabilidad en el precio de las viviendas es explicada por este modelo.
Error estándar de los residuos (155.1): Muestra la dispersión de los puntos alrededor de la línea de regresión, indicando un error medio de 155.1 millones de pesos en las predicciones.
Rendimiento del Modelo:
Error Cuadrático Medio (MSE = 23606.68 ): Este valor mide la media de los errores al cuadrado entre los valores predichos y los reales. Un MSE alto indica que, en promedio, las predicciones del modelo se desvían bastante de los valores reales. En este caso, un MSE de 23606.68 sugiere que hay una considerable dispersión de los errores.
Error Absoluto Medio (MAE = 97.18533 ): El MAE mide la magnitud media de los errores de predicción en unidades originales (millones de pesos, en este caso). Un MAE de 97.18533 indica que, en promedio, las predicciones del modelo se desvían 97.1 millones de pesos del valor real.
El modelo tiene un ajuste razonable con una buena capacidad explicativa, aunque podría mejorarse. Variables como el área construida, estrato, y número de parqueaderos son los factores más determinantes en el precio de una vivienda en este caso, mientras que el número de habitaciones no muestra una influencia significativa. El MSE y el MAE sugieren que el modelo tiene una precisión limitada y podría beneficiarse de mejoras adicionales, como la inclusión de más variables predictoras o la exploración de modelos más complejos.
Basado en lo anterior, el modelo permite encontrar que la mejor opción es una casa en el barrio la merced (ver mapa abajo). Con un precio de 310.2 millones, la cual cumple con todas las caracteristicas solicitadas por los compradores.
Oferta 2: Para la segunda solicitud, se recomienda una de las opciones de apartamentos en la Zona Sur, que no solo ofrece una excelente ubicación sino que también se encuentra dentro del presupuesto disponible. El precio predicho para la segunda solicitud es: 675.02 millones de pesos.
Siguiendo la misma interpretación que la anterior, en este nuevo modelo. La mejor opción es una casa en el barrio seminario, con un valor de 751.5 millones.
P.S. Aunque el ejercicio solicitaba 5 opciones de casa. Las casas mencionadas con las unicas que cumplen todos los requisitos solicitados por el comprador.
El análisis realizado permite a María ofrecer recomendaciones fundamentadas a la compañía internacional, asegurando que las opciones seleccionadas no solo cumplen con las necesidades de los empleados, sino que también representan una inversión segura en un mercado que está próximo a reactivarse. La combinación de técnicas de análisis exploratorio y modelación predictiva ha sido clave para identificar las mejores ofertas disponibles.
library(paqueteMODELOS)
## Loading required package: boot
## Loading required package: broom
## Warning: package 'broom' was built under R version 4.3.3
## Loading required package: GGally
## Loading required package: ggplot2
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
## Loading required package: gridExtra
## Loading required package: knitr
## Loading required package: summarytools
library(dplyr)
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:gridExtra':
##
## combine
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(ggplot2)
library(leaflet)
library(car)
## Loading required package: carData
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
## The following object is masked from 'package:boot':
##
## logit
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
data("vivienda")
# 1. Filtrado de la base de datos para casas en la Zona Norte
base1 <- vivienda[vivienda$tipo == "Casa" & vivienda$zona == "Zona Norte", ]
head(base1,3)
## # 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>
# Asegúrate de que los datos filtrados no tengan valores NA en latitud y longitud
base1_clean <- base1[!is.na(base1$latitud) & !is.na(base1$longitud), ]
# Crea un mapa con leaflet
map <- leaflet(base1_clean) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Precio:", preciom, "millones") # Personaliza el contenido del popup
)
# Muestra el mapa
map
Se evidencia una mayor concentación de puntos en la Zona Norte como es esperado debido al filtro que se aplicó. Sin embargo, llama la atención que además hay puntos en la zona sur y dispersos por toda la ciudad. Esto se puede deber a una categorización (labeling) incorrecto en la base de datos.
# Correlaciones entre variables seleccionadas
correlations <- cor(base1 %>% select(preciom, areaconst, estrato, parqueaderos, banios, habitaciones), use = "complete.obs")
print(correlations)
## preciom areaconst estrato parqueaderos banios habitaciones
## preciom 1.0000000 0.6853915 0.52827831 0.4116620 0.5086427 0.36508586
## areaconst 0.6853915 1.0000000 0.35352525 0.3069709 0.4574766 0.42068968
## estrato 0.5282783 0.3535252 1.00000000 0.2612647 0.3512569 0.05819709
## parqueaderos 0.4116620 0.3069709 0.26126471 1.0000000 0.3918638 0.24139617
## banios 0.5086427 0.4574766 0.35125685 0.3918638 1.0000000 0.59038214
## habitaciones 0.3650859 0.4206897 0.05819709 0.2413962 0.5903821 1.00000000
ggpairs(base1[,4:9], title=" ")
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 290 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 290 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 290 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 290 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 290 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 290 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 290 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 290 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 290 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 290 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 290 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
# 3. Modelo de regresión lineal múltiple
modelo <- lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones, data = base1)
summary(modelo)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios +
## habitaciones, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -784.29 -77.56 -16.03 47.67 978.61
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -238.17090 44.40551 -5.364 1.34e-07 ***
## areaconst 0.67673 0.05281 12.814 < 2e-16 ***
## estrato 80.63495 9.82632 8.206 2.70e-15 ***
## parqueaderos 24.00598 5.86889 4.090 5.14e-05 ***
## banios 18.89938 7.48800 2.524 0.012 *
## habitaciones 7.64511 5.65873 1.351 0.177
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 155.1 on 429 degrees of freedom
## (290 observations deleted due to missingness)
## Multiple R-squared: 0.6041, Adjusted R-squared: 0.5995
## F-statistic: 130.9 on 5 and 429 DF, p-value: < 2.2e-16
# Interpretación de los coeficientes y R^2
tidy(modelo)
## # A tibble: 6 × 5
## term estimate std.error statistic p.value
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -238. 44.4 -5.36 1.34e- 7
## 2 areaconst 0.677 0.0528 12.8 4.70e-32
## 3 estrato 80.6 9.83 8.21 2.70e-15
## 4 parqueaderos 24.0 5.87 4.09 5.14e- 5
## 5 banios 18.9 7.49 2.52 1.20e- 2
## 6 habitaciones 7.65 5.66 1.35 1.77e- 1
glance(modelo) # Incluye el R^2
## # A tibble: 1 × 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.604 0.599 155. 131. 5.42e-84 5 -2808. 5631. 5659.
## # ℹ 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
# 4. Validación de supuestos del modelo
# Normalidad de los residuos
qqPlot(modelo, main = "QQ Plot")
## [1] 405 513
# Homocedasticidad
ncvTest(modelo)
## Non-constant Variance Score Test
## Variance formula: ~ fitted.values
## Chisquare = 352.7061, Df = 1, p = < 2.22e-16
# Independencia de los residuos
durbinWatsonTest(modelo)
## lag Autocorrelation D-W Statistic p-value
## 1 0.1173407 1.761505 0.008
## Alternative hypothesis: rho != 0
# Linealidad
plot(modelo, which = 1)
# Dividir los datos en entrenamiento y prueba
set.seed(123)
train_indices <- sample(1:nrow(base1), 0.7 * nrow(base1))
train_data <- base1[train_indices, ]
test_data <- base1[-train_indices, ]
# Estimar el modelo en el set de entrenamiento
modelo <- lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones, data = train_data)
# Predicciones en el set de prueba
test_data$predicciones <- predict(modelo, test_data)
test_data$predicciones
## 1 2 3 4 5 6 7 8
## 446.4897 534.3219 NA 525.5452 518.2511 NA NA NA
## 9 10 11 12 13 14 15 16
## NA NA NA NA NA NA NA NA
## 17 18 19 20 21 22 23 24
## NA NA NA NA NA NA NA NA
## 25 26 27 28 29 30 31 32
## 258.6492 253.2745 NA NA 283.4657 NA NA NA
## 33 34 35 36 37 38 39 40
## 242.1747 NA NA NA 172.5127 NA NA NA
## 41 42 43 44 45 46 47 48
## NA 178.8796 169.5204 NA NA 400.4173 382.3157 389.9376
## 49 50 51 52 53 54 55 56
## 584.5243 482.2995 519.2814 431.2388 NA 203.3585 NA 185.1191
## 57 58 59 60 61 62 63 64
## 319.5827 NA 409.2619 515.7417 607.7276 888.5051 942.5556 571.7691
## 65 66 67 68 69 70 71 72
## 451.8877 NA 589.2429 382.4432 633.6747 452.4743 700.0896 692.3917
## 73 74 75 76 77 78 79 80
## 723.0482 452.4743 471.1928 460.3409 656.1439 357.1271 660.1324 NA
## 81 82 83 84 85 86 87 88
## 632.0475 NA 425.5028 580.0293 431.5047 460.3409 560.7859 444.6623
## 89 90 91 92 93 94 95 96
## 652.6076 632.1994 668.7819 730.5215 408.1809 461.5231 369.5263 321.8370
## 97 98 99 100 101 102 103 104
## 403.8435 413.3303 377.5102 365.2861 527.0968 371.7844 348.9359 NA
## 105 106 107 108 109 110 111 112
## NA NA NA 202.7172 268.6254 449.0917 NA NA
## 113 114 115 116 117 118 119 120
## NA 503.7789 209.3430 NA NA 206.0958 239.4169 NA
## 121 122 123 124 125 126 127 128
## 559.4074 738.4752 248.5972 NA 328.1079 328.2759 321.6540 NA
## 129 130 131 132 133 134 135 136
## NA NA 529.9786 439.9953 450.8471 551.2617 622.5439 NA
## 137 138 139 140 141 142 143 144
## 374.3389 484.5334 178.8796 NA 287.9749 282.8043 254.0086 NA
## 145 146 147 148 149 150 151 152
## NA 197.5981 NA 452.1323 438.1608 617.4693 515.7068 487.4843
## 153 154 155 156 157 158 159 160
## 581.8766 795.7427 529.8027 NA NA 554.0133 NA 487.7877
## 161 162 163 164 165 166 167 168
## 515.6034 626.3187 643.4790 1067.1028 648.0539 870.9901 652.3527 617.2699
## 169 170 171 172 173 174 175 176
## 776.5360 465.8149 944.8195 623.8846 212.2078 NA 353.3764 562.0338
## 177 178 179 180 181 182 183 184
## 736.6894 397.0529 1013.4368 577.3917 523.4701 548.1794 576.8953 763.8670
## 185 186 187 188 189 190 191 192
## NA 551.8098 178.7522 NA NA NA NA NA
## 193 194 195 196 197 198 199 200
## NA NA NA 166.2732 NA 248.1007 253.7163 248.1007
## 201 202 203 204 205 206 207 208
## 137.5715 NA NA 424.8273 380.2751 397.7385 436.4892 414.7268
## 209 210 211 212 213 214 215 216
## 711.1692 592.6871 351.1626 576.3471 NA 570.1076 NA NA
## 217 218
## 264.9474 NA
# Estimar el modelo en el set de entrenamiento
modelo <- lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones, data = test_data)
# Predicciones en el set de prueba
test_data$predicciones <- predict(modelo, test_data)
test_data$predicciones
## 1 2 3 4 5 6 7 8
## 417.0423 581.9452 NA 538.9999 489.0946 NA NA NA
## 9 10 11 12 13 14 15 16
## NA NA NA NA NA NA NA NA
## 17 18 19 20 21 22 23 24
## NA NA NA NA NA NA NA NA
## 25 26 27 28 29 30 31 32
## 260.0723 214.1526 NA NA 270.1245 NA NA NA
## 33 34 35 36 37 38 39 40
## 239.0859 NA NA NA 185.9141 NA NA NA
## 41 42 43 44 45 46 47 48
## NA 175.2284 163.4691 NA NA 432.1014 389.4513 400.2490
## 49 50 51 52 53 54 55 56
## 573.5836 480.4331 547.0854 413.5489 NA 151.4366 NA 183.0679
## 57 58 59 60 61 62 63 64
## 405.9199 NA 410.1403 518.7939 639.8207 992.5984 914.8389 573.2261
## 65 66 67 68 69 70 71 72
## 480.5207 NA 557.5226 370.9260 652.2275 461.9323 681.9872 748.9183
## 73 74 75 76 77 78 79 80
## 767.5362 461.9323 485.4508 453.4181 700.3652 379.2187 685.7570 NA
## 81 82 83 84 85 86 87 88
## 668.5812 NA 444.9342 548.6037 415.9660 453.4181 540.1664 415.9608
## 89 90 91 92 93 94 95 96
## 656.9772 596.1133 663.4919 737.1125 426.1874 476.9586 377.0393 352.6960
## 97 98 99 100 101 102 103 104
## 420.1565 413.3905 405.7559 353.0263 433.6496 381.3850 351.1689 NA
## 105 106 107 108 109 110 111 112
## NA NA NA 186.4932 252.6999 424.8958 NA NA
## 113 114 115 116 117 118 119 120
## NA 459.2528 196.3266 NA NA 210.9321 253.0851 NA
## 121 122 123 124 125 126 127 128
## 594.7779 728.3547 262.1837 NA 326.5085 289.7015 337.4377 NA
## 129 130 131 132 133 134 135 136
## NA NA 560.5325 446.2533 478.2861 572.5321 589.4346 NA
## 137 138 139 140 141 142 143 144
## 380.6502 500.7039 175.2284 NA 296.9179 287.9857 232.2519 NA
## 145 146 147 148 149 150 151 152
## NA 198.7469 NA 499.2264 463.2738 596.0041 472.0908 491.1789
## 153 154 155 156 157 158 159 160
## 642.9157 908.6069 527.1722 NA NA 588.8691 NA 467.9963
## 161 162 163 164 165 166 167 168
## 558.4266 681.8645 624.0925 1086.7708 673.8854 931.3599 694.0277 666.8382
## 169 170 171 172 173 174 175 176
## 814.1933 477.1853 1010.6017 644.1584 237.2969 NA 354.5995 541.7343
## 177 178 179 180 181 182 183 184
## 675.5076 409.4760 1094.6593 600.1972 549.9124 543.0127 542.8704 763.3405
## 185 186 187 188 189 190 191 192
## NA 568.0552 193.7536 NA NA NA NA NA
## 193 194 195 196 197 198 199 200
## NA NA NA 178.0746 NA 242.8745 249.9301 242.8745
## 201 202 203 204 205 206 207 208
## 142.0129 NA NA 429.9188 373.6547 413.7073 440.3397 418.1623
## 209 210 211 212 213 214 215 216
## 646.8130 604.9609 389.5417 585.3649 NA 577.5254 NA NA
## 217 218
## 264.0412 NA
#Filtrar aquellos valores que tuvieron prediccion
test_data <- test_data[!is.na(test_data$predicciones), ]
# Calcular el error cuadrático medio (MSE)
mse <- mean((test_data$preciom - test_data$predicciones)^2)
# Calcular el error absoluto medio (MAE)
mae <- mean(abs(test_data$preciom - test_data$predicciones))
# Imprimir los resultados
cat("MSE:", mse, "\n")
## MSE: 23606.68
cat("MAE:", mae, "\n")
## MAE: 97.18533
# 5. Predicción del precio para la primera solicitud
nueva_vivienda1 <- data.frame(
areaconst = 200,
estrato = 4,
parqueaderos = 1,
banios = 2,
habitaciones = 4
)
precio_pred1 <- predict(modelo, nueva_vivienda1)
print(paste("El precio predicho para la primera solicitud es:", round(precio_pred1, 2), "millones de pesos"))
## [1] "El precio predicho para la primera solicitud es: 318.49 millones de pesos"
# 6. Sugerencias de ofertas para la primera solicitud
ofertas1 <- base1 %>%
mutate(predicted_price = predict(modelo, .)) %>%
filter(predicted_price <= 350,
areaconst >= 200,
estrato >= 4,
parqueaderos >= 1,
banios >= 2,
habitaciones >= 4)
# Mostrar las ofertas potenciales
head(ofertas1)
## # A tibble: 1 × 14
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1222 Zona N… 02 4 360 216 2 2 4
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # predicted_price <dbl>
# Mapa con las ofertas potenciales
map <- leaflet(ofertas1) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Precio:", preciom, "millones") # Personaliza el contenido del popup
)
# Muestra el mapa
map
# 7. Repetición de los pasos 1 al 6 para la segunda solicitud
# Filtrado de la base para Apartamentos en la Zona Sur
base2 <- vivienda[vivienda$tipo == "Apartamento" & vivienda$zona == "Zona Sur", ]
# Mostrar los primeros 3 registros
head(base2)
## # A tibble: 6 × 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 1241 Zona S… <NA> 3 135 117 NA 2 3
## 5 5370 Zona S… <NA> 3 135 78 NA 1 3
## 6 6975 Zona S… 06 4 220 75 1 2 3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
# Tabla resumen para comprobar la consulta
summary(base2)
## id zona piso estrato
## Min. : 3 Length:2790 Length:2790 Min. :3.00
## 1st Qu.:2292 Class :character Class :character 1st Qu.:4.00
## Median :4004 Mode :character Mode :character Median :5.00
## Mean :4131 Mean :4.63
## 3rd Qu.:5876 3rd Qu.:5.00
## Max. :8302 Max. :6.00
## NA's :3 NA's :3
## preciom areaconst parqueaderos banios
## Min. : 75.0 Min. : 40.00 Min. : 1.000 Min. :0.000
## 1st Qu.: 175.0 1st Qu.: 65.00 1st Qu.: 1.000 1st Qu.:2.000
## Median : 245.0 Median : 85.00 Median : 1.000 Median :2.000
## Mean : 297.3 Mean : 97.47 Mean : 1.415 Mean :2.488
## 3rd Qu.: 335.0 3rd Qu.:110.00 3rd Qu.: 2.000 3rd Qu.:3.000
## Max. :1750.0 Max. :932.00 Max. :10.000 Max. :8.000
## NA's :3 NA's :3 NA's :409 NA's :3
## habitaciones tipo barrio longitud
## Min. :0.000 Length:2790 Length:2790 Min. :-76.57
## 1st Qu.:3.000 Class :character Class :character 1st Qu.:-76.54
## Median :3.000 Mode :character Mode :character Median :-76.53
## Mean :2.966 Mean :-76.53
## 3rd Qu.:3.000 3rd Qu.:-76.52
## Max. :6.000 Max. :-76.46
## NA's :3 NA's :3
## latitud
## Min. :3.334
## 1st Qu.:3.370
## Median :3.383
## Mean :3.390
## 3rd Qu.:3.406
## Max. :3.497
## NA's :3
# Mapa con las ofertas potenciales
map <- leaflet(base2) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Precio:", preciom, "millones") # Personaliza el contenido del popup
)
## Warning in validateCoords(lng, lat, funcName): Data contains 3 rows with either
## missing or invalid lat/lon values and will be ignored
# Muestra el mapa
map
# Convertir las columnas relevantes a numéricas
base2$preciom <- as.numeric(base2$preciom)
base2$areaconst <- as.numeric(base2$areaconst)
base2$estrato <- as.numeric(base2$estrato)
base2$parqueaderos <- as.numeric(base2$parqueaderos)
base2$banios <- as.numeric(base2$banios)
base2$habitaciones <- as.numeric(base2$habitaciones)
# Ahora calcula la correlación nuevamente
correlations2 <- cor(base2 %>% select(preciom, areaconst, estrato, parqueaderos, banios, habitaciones), use = "complete.obs")
print(correlations2)
## preciom areaconst estrato parqueaderos banios habitaciones
## preciom 1.0000000 0.7407150 0.6497479 0.6934386 0.7111289 0.2957800
## areaconst 0.7407150 1.0000000 0.4518617 0.5783506 0.6639216 0.4073401
## estrato 0.6497479 0.4518617 1.0000000 0.4859027 0.5348003 0.1768269
## parqueaderos 0.6934386 0.5783506 0.4859027 1.0000000 0.5563189 0.2367067
## banios 0.7111289 0.6639216 0.5348003 0.5563189 1.0000000 0.5204718
## habitaciones 0.2957800 0.4073401 0.1768269 0.2367067 0.5204718 1.0000000
# Gráficos interactivos
ggpairs(base2[,4:9], title=" ")
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 409 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 409 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 409 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 409 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 409 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 409 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 409 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 409 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 409 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 409 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 3 rows containing missing values
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 409 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
# Gráfico interactivo para la relación entre área construida y precio
plot_ly(data = base1, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers') %>%
layout(title = "Relación entre Área Construida y Precio",
xaxis = list(title = "Área Construida (m²)"),
yaxis = list(title = "Precio (Millones de Pesos)"))
## Warning: Ignoring 3 observations
# Gráfico interactivo para la relación entre área construida y precio
plot_ly(data = base2, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers') %>%
layout(title = "Relación entre Área Construida y Precio",
xaxis = list(title = "Área Construida (m²)"),
yaxis = list(title = "Precio (Millones de Pesos)"))
## Warning: Ignoring 3 observations
# Modelo de regresión lineal múltiple para la Zona Sur
modelo2 <- lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones, data = base2)
summary(modelo2)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios +
## habitaciones, data = base2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1092.02 -42.28 -1.33 40.58 926.56
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -261.62501 15.63220 -16.736 < 2e-16 ***
## areaconst 1.28505 0.05403 23.785 < 2e-16 ***
## estrato 60.89709 3.08408 19.746 < 2e-16 ***
## parqueaderos 72.91468 3.95797 18.422 < 2e-16 ***
## banios 50.69675 3.39637 14.927 < 2e-16 ***
## habitaciones -24.83693 3.89229 -6.381 2.11e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 98.02 on 2375 degrees of freedom
## (409 observations deleted due to missingness)
## Multiple R-squared: 0.7485, Adjusted R-squared: 0.748
## F-statistic: 1414 on 5 and 2375 DF, p-value: < 2.2e-16
# Predicción del precio para la segunda solicitud
nueva_vivienda2 <- data.frame(
areaconst = 300,
estrato = 5,
parqueaderos = 3,
banios = 3,
habitaciones = 5
)
precio_pred2 <- predict(modelo2, nueva_vivienda2)
print(paste("El precio predicho para la segunda solicitud es:", round(precio_pred2, 2), "millones de pesos"))
## [1] "El precio predicho para la segunda solicitud es: 675.02 millones de pesos"
# Sugerencias de ofertas para la segunda solicitud
ofertas2 <- base2 %>%
mutate(predicted_price = predict(modelo2, .)) %>%
filter(predicted_price <= 850,
areaconst >= 300,
estrato >= 5,
parqueaderos >= 3,
banios >= 3,
habitaciones >= 5)
# Mostrar las ofertas potenciales
head(ofertas2)
## # A tibble: 1 × 14
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 7512 Zona S… <NA> 5 670 300 3 5 6
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # predicted_price <dbl>
map <- leaflet(ofertas2) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
popup = ~paste("Barrio:", barrio, "<br>",
"Precio:", preciom, "millones") # Personaliza el contenido del popup
)
# Muestra el mapa
map