Anexos Técnicos: Estimaciones, Validaciones y Modelación
A continuación se presentan los códigos, salidas de los modelos
econométricos, pruebas formales de supuestos y soportes cartográficos
utilizados para respaldar el presente informe.
# --- CARGAR LIBRERÍAS ---
library(paqueteMODELOS)
library(dplyr)
library(knitr)
library(leaflet)
# CARGAR Y FILTRAR DATOS (Casas en Zona Norte)
data("vivienda", package = "paqueteMODELOS")
# Filtrar usando los nombres exactos de columnas
base1 <- vivienda %>%
filter(tipo == "Casa" & zona == "Zona Norte")
# 1. Mostrar los primeros 3 registros
cat("Primeros 3 registros de la Base 1 (Casas - Zona Norte):")
## Primeros 3 registros de la Base 1 (Casas - Zona Norte):
base1 %>% head(3) %>% kable()
| 1209 |
Zona Norte |
02 |
5 |
320 |
150 |
2 |
4 |
6 |
Casa |
acopi |
-76.51341 |
3.47968 |
| 1592 |
Zona Norte |
02 |
5 |
780 |
380 |
2 |
3 |
3 |
Casa |
acopi |
-76.51674 |
3.48721 |
| 4057 |
Zona Norte |
02 |
6 |
750 |
445 |
NA |
7 |
6 |
Casa |
acopi |
-76.52950 |
3.38527 |
# 2. Tabla de comprobación
cat("\nComprobación del filtro (Conteo):")
##
## Comprobación del filtro (Conteo):
base1 %>%
count(tipo, zona) %>%
kable()
# 3. Mapa interactivo con Leaflet
leaflet(base1) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
radius = 4, color = "blue", stroke = FALSE, fillOpacity = 0.6,
popup = paste("Precio:", base1$preciom, "Millones<br>",
"Área:", base1$areaconst, "m²")
) %>%
addControl("<b>Casas - Zona Norte</b>", position = "topright")
library(plotly)
# 1. Gráfico de dispersión: Precio vs Área Construida según Estrato
p1 <- plot_ly(base1, x = ~areaconst, y = ~preciom, color = ~as.factor(estrato),
type = 'scatter', mode = 'markers') %>%
layout(title = "Precio vs Área Construida según Estrato")
p1
# 2. Gráfico de caja para ver la relación Precio vs Estrato
p2 <- plot_ly(base1, x = ~as.factor(estrato), y = ~preciom, type = 'box',
color = ~as.factor(estrato)) %>%
layout(title = "Distribución del Precio según el Estrato")
p2
#3: MODELO DE REGRESIÓN LINEAL MÚLTIPLE ---
modelo1 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base1)
# Resumen detallado del modelo
summary(modelo1)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, 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 ***
## habitaciones 7.64511 5.65873 1.351 0.177
## parqueaderos 24.00598 5.86889 4.090 5.14e-05 ***
## banios 18.89938 7.48800 2.524 0.012 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 155.1 on 429 degrees of freedom
## (287 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
# 4.VALIDACIÓN DE SUPUESTOS (PRUEBAS FORMALES Y GRÁFICOS) ---
# Cargar librerías necesarias para pruebas formales
library(lmtest) # Para Breusch-Pagan y Durbin-Watson
# 1. Gráficos de diagnóstico estándar
par(mfrow = c(2, 2))
plot(modelo1)

par(mfrow = c(1, 1)) # Restaurar ventana
# 2. Supuesto de Normalidad de los Residuos
# Prueba de Shapiro-Wilk (H0: los residuos tienen distribución normal)
residuos <- residuals(modelo1)
shapiro_res <- shapiro.test(residuos)
print(shapiro_res)
##
## Shapiro-Wilk normality test
##
## data: residuos
## W = 0.85246, p-value < 2.2e-16
# 3. Supuesto de Homocedasticidad (Varianza constante de los errores)
# Prueba de Breusch-Pagan (H0: los errores son homocedásticos)
bp_res <- bptest(modelo1)
print(bp_res)
##
## studentized Breusch-Pagan test
##
## data: modelo1
## BP = 80.281, df = 5, p-value = 7.33e-16
# 4. Supuesto de No Autocorrelación de los errores
# Prueba de Durbin-Watson (H0: no hay autocorrelación)
dw_res <- dwtest(modelo1)
print(dw_res)
##
## Durbin-Watson test
##
## data: modelo1
## DW = 1.7615, p-value = 0.005472
## alternative hypothesis: true autocorrelation is greater than 0
# 5: PREDICCIÓN PARA LA VIVIENDA
# Creamos un "data.frame" con las características solicitadas para la Vivienda 1
# (Asumir estrato 4 para la predicción en especifico)
nueva_vivienda1 <- data.frame(
areaconst = 200,
estrato = 4,
habitaciones = 4,
parqueaderos = 1,
banios = 2
)
# Realizamos la predicción con su intervalo de confianza
prediccion_precio1 <- predict(modelo1, newdata = nueva_vivienda1, interval = "prediction")
print("Precio estimado (en millones) para la Vivienda 1:")
## [1] "Precio estimado (en millones) para la Vivienda 1:"
print(prediccion_precio1)
## fit lwr upr
## 1 312.101 6.205196 617.9968
# 6: BÚSQUEDA DE OFERTAS POTENCIALES de maximo 350 millone
# Filtramos la base1 (Casas en Zona Norte) con las condiciones de presupuesto y características cercanas
# Estrato 4 o 5, precio menor o igual a 350 millones, y área cercana a 200m²
ofertas_potenciales1 <- base1 %>%
filter(preciom <= 350, estrato %in% c(4, 5)) %>%
arrange(desc(preciom)) # Ordenadas de mayor a menor precio (o como prefieras)
# Seleccionamos al menos 5 ofertas potenciales para presentar en la tabla y el mapa
top_5_ofertas1 <- head(ofertas_potenciales1, 5)
# Mostrar la tabla con las 5 ofertas seleccionadas
cat("Top 5 ofertas potenciales para la Solicitud 1:")
## Top 5 ofertas potenciales para la Solicitud 1:
top_5_ofertas1 %>%
select(barrio, preciom, areaconst, estrato, habitaciones, banios, parqueaderos) %>%
kable()
| acopi |
350 |
118 |
4 |
3 |
3 |
NA |
| chipichape |
350 |
98 |
4 |
4 |
3 |
2 |
| el bosque |
350 |
200 |
5 |
4 |
3 |
3 |
| el bosque |
350 |
300 |
5 |
6 |
5 |
3 |
| el bosque |
350 |
240 |
5 |
6 |
3 |
2 |
# Mapa interactivo con las 5 ofertas seleccionadas
leaflet(top_5_ofertas1) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
radius = 8, color = "green", stroke = FALSE, fillOpacity = 0.8,
popup = paste("<b>Barrio:</b>", top_5_ofertas1$barrio, "<br>",
"<b>Precio:</b>", top_5_ofertas1$preciom, "Millones<br>",
"<b>Área:</b>", top_5_ofertas1$areaconst, "m²<br>",
"<b>Estrato:</b>", top_5_ofertas1$estrato)
) %>%
addControl("<b>Top 5 Ofertas - Vivienda 1 (Zona Norte)</b>", position = "topright")
# ==========================================
# PASO 7: ANÁLISIS COMPLETO PARA VIVIENDA 2
# (Apartamentos en la Zona Sur)
# ==========================================
# --- 1. FILTRO Y MAPA INICIAL
base2 <- vivienda %>%
filter(tipo == "Apartamento" & zona == "Zona Sur")
cat("Primeros 3 registros de la Base 2 (Apartamentos - Zona Sur):")
## Primeros 3 registros de la Base 2 (Apartamentos - Zona Sur):
base2 %>% head(3) %>% kable()
| 5098 |
Zona Sur |
05 |
4 |
290 |
96 |
1 |
2 |
3 |
Apartamento |
acopi |
-76.53464 |
3.44987 |
| 698 |
Zona Sur |
02 |
3 |
78 |
40 |
1 |
1 |
2 |
Apartamento |
aguablanca |
-76.50100 |
3.40000 |
| 8199 |
Zona Sur |
NA |
6 |
875 |
194 |
2 |
5 |
3 |
Apartamento |
aguacatal |
-76.55700 |
3.45900 |
cat("\nComprobación del filtro (Conteo):")
##
## Comprobación del filtro (Conteo):
base2 %>% count(tipo, zona) %>% kable()
| Apartamento |
Zona Sur |
2787 |
# Mapa inicial de la Base 2
leaflet(base2) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
radius = 4, color = "purple", stroke = FALSE, fillOpacity = 0.6,
popup = paste("Precio:", base2$preciom, "Millones<br>", "Área:", base2$areaconst, "m²")
) %>%
addControl("<b>Apartamentos - Zona Sur</b>", position = "topright")
# --- 2 y 3. MODELO DE REGRESIÓN LINEAL MÚLTIPLE
modelo2 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base2)
cat("\n--- Resumen del Modelo 2 ---")
##
## --- Resumen del Modelo 2 ---
summary(modelo2)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, 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 ***
## habitaciones -24.83693 3.89229 -6.381 2.11e-10 ***
## parqueaderos 72.91468 3.95797 18.422 < 2e-16 ***
## banios 50.69675 3.39637 14.927 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 98.02 on 2375 degrees of freedom
## (406 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
# --- 4. VALIDACIÓN DE SUPUESTOS
# Pruebas formales para la Base 2
library(lmtest)
shapiro_res2 <- shapiro.test(residuals(modelo2))
bp_res2 <- bptest(modelo2)
dw_res2 <- dwtest(modelo2)
print(shapiro_res2)
##
## Shapiro-Wilk normality test
##
## data: residuals(modelo2)
## W = 0.79118, p-value < 2.2e-16
print(bp_res2)
##
## studentized Breusch-Pagan test
##
## data: modelo2
## BP = 754.81, df = 5, p-value < 2.2e-16
print(dw_res2)
##
## Durbin-Watson test
##
## data: modelo2
## DW = 1.5333, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
# --- 5. PREDICCIÓN PARA LA VIVIENDA 2 ---
nueva_vivienda2 <- data.frame(
areaconst = 300,
estrato = 5, # estrato 5 como base para la predicción
habitaciones = 5,
parqueaderos = 3,
banios = 3
)
prediccion_precio2 <- predict(modelo2, newdata = nueva_vivienda2, interval = "prediction")
cat("\nPrecio estimado (en millones) para la Vivienda 2:")
##
## Precio estimado (en millones) para la Vivienda 2:
print(prediccion_precio2)
## fit lwr upr
## 1 675.0247 481.455 868.5945
# --- 6. BÚSQUEDA DE OFERTAS POTENCIALES (Máx 850 millones) ---
ofertas_potenciales2 <- base2 %>%
filter(preciom <= 850, estrato %in% c(5, 6)) %>%
arrange(desc(preciom))
top_5_ofertas2 <- head(ofertas_potenciales2, 5)
cat("\nTop 5 ofertas potenciales para la Solicitud 2:")
##
## Top 5 ofertas potenciales para la Solicitud 2:
top_5_ofertas2 %>%
select(barrio, preciom, areaconst, estrato, habitaciones, banios, parqueaderos) %>%
kable()
| ciudad jardín |
850 |
187.0 |
6 |
4 |
5 |
3 |
| ciudad jardín |
850 |
168.0 |
6 |
4 |
5 |
3 |
| ciudad jardín |
850 |
192.0 |
6 |
3 |
5 |
2 |
| ciudad jardín |
850 |
191.8 |
6 |
4 |
5 |
2 |
| ciudad jardín |
850 |
186.0 |
6 |
4 |
5 |
3 |
# Mapa interactivo con las 5 ofertas seleccionadas para la Vivienda 2
leaflet(top_5_ofertas2) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
radius = 8, color = "orange", stroke = FALSE, fillOpacity = 0.8,
popup = paste("<b>Barrio:</b>", top_5_ofertas2$barrio, "<br>",
"<b>Precio:</b>", top_5_ofertas2$preciom, "Millones<br>",
"<b>Área:</b>", top_5_ofertas2$areaconst, "m²<br>",
"<b>Estrato:</b>", top_5_ofertas2$estrato)
) %>%
addControl("<b>Top 5 Ofertas - Vivienda 2 (Zona Sur)</b>", position = "topright")