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) .
Los datos de los tres últimos meses se adjuntan en la base que puede obtener con el siguiente código en R:
| variable | descripción |
|---|---|
| zona | ubicación de la vivienda : Zona Centro, Zona Norte,… |
| piso | piso que ocupa la vivienda : primer piso, segundo piso… |
| estrato | estrato socio-económico : 3, 4, 5, 6 |
| preciom | precio de la vivienda en millones de pesos |
| areaconst | área construida |
| parqueaderos | número de parqueaderos |
| banios | número de baños |
| habitaciones | número de habitaciones |
| tipo | tipo de vivienda : Casa, Apartamento |
| barrio | barrio de ubicación de la vivienda : 20 de Julio, Alamos,… |
| longitud | coordenada geográfica |
| latitud | coordenada geográfica |
kable(head(vivi_1,3), caption = "Encabezados de resgistros vivienda caso 1")
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 | 0 | 7 | 6 | Casa | acopi | -76.52950 | 3.38527 |
skim(vivi_1)
| Name | vivi_1 |
| Number of rows | 722 |
| Number of columns | 13 |
| _______________________ | |
| Column type frequency: | |
| character | 4 |
| numeric | 9 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| zona | 0 | 1.00 | 10 | 10 | 0 | 1 | 0 |
| piso | 372 | 0.48 | 2 | 2 | 0 | 5 | 0 |
| tipo | 0 | 1.00 | 4 | 4 | 0 | 1 | 0 |
| barrio | 0 | 1.00 | 4 | 25 | 0 | 103 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| id | 0 | 1 | 2574.65 | 1986.26 | 58.00 | 766.25 | 2257.00 | 4225.00 | 8319.00 | ▇▃▃▂▁ |
| estrato | 0 | 1 | 4.20 | 0.98 | 3.00 | 3.00 | 4.00 | 5.00 | 6.00 | ▇▅▁▇▂ |
| preciom | 0 | 1 | 445.91 | 268.36 | 89.00 | 261.25 | 390.00 | 550.00 | 1940.00 | ▇▃▁▁▁ |
| areaconst | 0 | 1 | 264.85 | 167.17 | 30.00 | 140.00 | 240.00 | 336.75 | 1440.00 | ▇▃▁▁▁ |
| parqueaderos | 0 | 1 | 1.31 | 1.53 | 0.00 | 0.00 | 1.00 | 2.00 | 10.00 | ▇▁▁▁▁ |
| banios | 0 | 1 | 3.56 | 1.52 | 0.00 | 2.00 | 3.00 | 4.00 | 10.00 | ▅▇▃▁▁ |
| habitaciones | 0 | 1 | 4.51 | 1.83 | 0.00 | 3.00 | 4.00 | 5.00 | 10.00 | ▁▇▅▂▁ |
| longitud | 0 | 1 | -76.52 | 0.02 | -76.59 | -76.53 | -76.52 | -76.50 | -76.47 | ▁▁▇▆▂ |
| latitud | 0 | 1 | 3.46 | 0.03 | 3.33 | 3.45 | 3.47 | 3.48 | 3.50 | ▁▁▁▂▇ |
map <- leaflet(vivi_1) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
popup = ~paste("ID:", id, "<br>Barrio:", barrio),
radius = 6,
color = "red", fillOpacity = 0.5, stroke = FALSE
)
map
Se encuentran viviendas fuera del perímetro de la zona norte de la ciudad; se asume que la zona no se encuentra categorizada correctamente y que los valores de latitud y longitud en la data son correctos; se procede a borrar los registros ubicados incorrectamente de los datos a analizar.
# Definir área de interés (rectángulo)
lat_min <- 3.451
lat_max <- 3.49584
lon_min <- -76.53814
lon_max <- -76.482
# Filtrar solo puntos dentro del área
vivi_filtrado <- vivi_1 %>%
dplyr::filter(
latitud >= lat_min & latitud <= lat_max,
longitud >= lon_min & longitud <= lon_max
)
map3 <- leaflet(vivi_filtrado) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
popup = ~paste("ID:", id, "<br>Barrio:", barrio),
radius = 6,
color = "blue", fillOpacity = 0.5, stroke = FALSE
)
map3
# Selecciona solo las variables numéricas del df
df_num <- vivi_filtrado[c(4:9)]
# Matriz de correlación
mat_cor <- cor(df_num, use = "complete.obs")
# Pasar la matriz a formato largo
df_cor <- melt(mat_cor)
# Graficar heatmap con valores dentro de las celdas
ggplot(df_cor, aes(Var1, Var2, fill = value)) +
geom_tile(color = "white") +
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1,1), space = "Lab",
name = "Coef. Correlación") +
geom_text(aes(label = round(value, 2)), size = 4) +
theme_minimal() +
theme(axis.text.x = element_text(angle =45, vjust = 1, hjust = 1)) +
labs(title = "Matriz de Correlación",
x = "", y = "")
-El precio se explica principalmente por el área construida (0,73), el estrato (0,6) y el número de baños (0,54), las variables como habitaciones y baños (0,62) están muy relacionadas entre sí, lo que puede reducir la relevancia estadística de una de ellas en el modelo.
p1 <- plot_ly(vivi_filtrado,
x = ~areaconst,
y = ~preciom,
type = 'scatter',
mode = 'markers',
marker = list(size = 8, opacity = 0.6),
color = ~estrato # Asignar color según estrato
) %>%
layout(title = "Precio vs Área Construida",
xaxis = list(title = "Área Construida (m²)"),
yaxis = list(title = "Precio (millones)"),
coloraxis = list(colorbar = list(title = "Estrato")))
p1
-En la gráfica se puede observar una correlación positiva fuerte entre las variables precio y área construida; la dispersión de los datos es menor en áreas inferiores a 500 m² y la mayoría de las viviendas no supera los 1000 millones. Las viviendas con áreas superiores a 500 m² muestran una dispersión mayor y algunas viviendas tienen áreas representativas, pero costos inferiores.
p2 <- plot_ly(vivi_filtrado, x = ~factor(estrato), y = ~preciom, type = "box",
boxpoints = "all", jitter = 0.3, pointpos = -1.8) %>%
layout(title = "Boxplot Precio vs Estrato",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio (millones)"))
p2
El gráfico de distribución de precios por estrato muestra las siguientes diferencias:
-Estrato 3: concentra las viviendas con los precios más bajos, además de presentar menor dispersión en comparación con los demás estratos. Esto indica que en este nivel los precios son más homogéneos.
-Estratos 4 y 5: presentan un rango de precios similar, aunque en el estrato 5 la dispersión es más simétrica, lo que refleja una distribución más equilibrada alrededor de la mediana.
-Estrato 6: agrupa las viviendas más costosas, con un rango amplio que va aproximadamente de 430 hasta 1.300 millones de pesos, lo que muestra gran diversidad en el valor de las propiedades de este nivel..
p3 <- plot_ly(vivi_filtrado, x = ~factor(banios), y = ~preciom, type = "box",
boxpoints = "all", jitter = 0.3, pointpos = -1.8) %>%
layout(title = "Boxplot Precio vs Número de Baños",
xaxis = list(title = "Número de Baños"),
yaxis = list(title = "Precio (millones)"))
p3
El gráfico de precios en función del número de baños permite identificar los siguientes patrones:
-Viviendas sin baños: presentan un rango de precios superior al esperado en comparación con las viviendas con 1, 2 o 3 baños. Este comportamiento resulta atípico y sugiere que algunos registros deberían ser revisados, ya que no siguen la tendencia lógica del mercado.
-Viviendas con 1, 2 y 3 baños: concentran la mayoría de los datos en los precios más bajos, lo que coincide con lo esperado para propiedades de menor tamaño y con características más básicas.
-Viviendas con 5 y 6 baños: muestran rangos y distribuciones muy similares, lo que indica un comportamiento prácticamente idéntico en el precio, sin una diferenciación clara entre estos dos niveles.
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = vivi_filtrado )
summary(modelo)
Call:
lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
banios, data = vivi_filtrado)
Residuals:
Min 1Q Median 3Q Max
-906.99 -69.86 -19.04 37.01 1098.41
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -208.09573 36.34846 -5.725 1.70e-08 ***
areaconst 0.75268 0.05377 13.998 < 2e-16 ***
estrato 75.94773 8.97200 8.465 2.34e-16 ***
habitaciones 7.96291 5.07985 1.568 0.117563
parqueaderos 8.43679 4.92329 1.714 0.087157 .
banios 21.32973 6.35444 3.357 0.000843 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 155.7 on 549 degrees of freedom
Multiple R-squared: 0.6298, Adjusted R-squared: 0.6265
F-statistic: 186.8 on 5 and 549 DF, p-value: < 2.2e-16
Interpretación del modelo:
-Variables más influyentes y confiables: área construida, estrato y número de baños.
-Habitaciones no tiene efecto estadísticamente claro, probablemente porque ya está correlacionado con área o baños.
-Parqueaderos influye, pero de forma débil.
-El modelo tiene un ajuste aceptable (63%), aunque aún queda variabilidad sin explicar (quizás por ubicación exacta, barrio, antigüedad de la vivienda, etc.).
vif(modelo)
areaconst estrato habitaciones parqueaderos banios
1.723501 1.667250 1.862199 1.363714 2.073198
Interpretación:
-Todos los valores están por debajo de 2.1, lo que indica que:
-No existe multicolinealidad preocupante.
-Las variables areaconst, estrato, habitaciones, parqueaderos y baños aportan información independiente al modelo.
-las variables en la regresión sin riesgo de inflar los errores estándar.
par(mfrow = c(2, 2))
plot(modelo)
Observaciones:
-En la gráfica de residuales se observa que algunos puntos se dispersan más en los valores grandes, un indicio de heterocedasticidad leve.
-En la gráfica de normalidad Q-Q, el centro sigue la línea y en las colas se apartan, evidenciando residuos no totalmente normales.
-La gráfica Scale-Location refleja que la varianza de los residuos aumenta con el valor ajustado (heterocedasticidad).
-La gráfica de residuos influyentes nos muestra tres datos: 102, 538 y 471; este último es un candidato a revisar por su particularidad de influencia.
bptest(modelo)
studentized Breusch-Pagan test
data: modelo
BP = 106.46, df = 5, p-value < 2.2e-16
shapiro.test(modelo$residuals)
Shapiro-Wilk normality test
data: modelo$residuals
W = 0.77606, p-value < 2.2e-16
dwtest(modelo)
Durbin-Watson test
data: modelo
DW = 1.5981, p-value = 8.225e-07
alternative hypothesis: true autocorrelation is greater than 0
Observaciones:
-Las pruebas realizadas rechazan las hipótesis nulas de homocedasticidad, normalidad y autocorrelación, es decir, el modelo viola varios supuestos clásicos de la regresión lineal.
-Se pueden aplicar transformaciones logarítmicas como solución a la heterocedasticidad y revisar los valores influyentes para el caso de la no normalidad.
new_vivienda <- data.frame(
areaconst = 200,
estrato = c(4,5),
habitaciones = 4,
parqueaderos = 1,
banios = 2
)
predict(modelo,new_vivienda)
1 2
329.1789 405.1267
-La predicción del valor de la casa con las características solicitadas en el caso uno es de 329 millones en estrato 4 y 405 millones en el estrato 5, el presupuesto de 350 millones se ajusta al precio para adquirir la vivienda con las caracteristicas.
ofertas_1 <- vivi_filtrado %>%
filter(
areaconst >= 200, # Rango cercano a 200 m²
estrato >= 4 & estrato <= 5, # Estrato 4 o 5
parqueaderos >= 1, # 1 parqueadero
banios >= 2, # 2 baños
habitaciones >= 4, # 4 habitaciones
preciom <= 330
)
ofertas_1 <- ofertas_1 %>% arrange(preciom)%>% slice_head(n = 5)
kable((ofertas_1), caption = "Inmuebles potenciales caso 1")
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1020 | Zona Norte | 02 | 4 | 230 | 250 | 2 | 3 | 5 | Casa | la merced | -76.50799 | 3.47424 |
| 1009 | Zona Norte | NA | 5 | 250 | 243 | 1 | 4 | 5 | Casa | el bosque | -76.50755 | 3.47838 |
| 1914 | Zona Norte | 02 | 5 | 300 | 205 | 2 | 5 | 6 | Casa | vipasa | -76.51832 | 3.48138 |
| 4458 | Zona Norte | 02 | 4 | 315 | 270 | 2 | 4 | 4 | Casa | el bosque | -76.53176 | 3.48780 |
| 1343 | Zona Norte | 02 | 5 | 320 | 200 | 2 | 4 | 4 | Casa | la flora | -76.51524 | 3.48893 |
map2 <- leaflet(ofertas_1) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
popup = ~paste("Area:", areaconst, "<br>Precio:", preciom),
radius = 6,
color = "blue", fillOpacity = 0.5, stroke = FALSE
)
map2
-Se seleccionan las 5 propuestas más económicas que cumplen con las características solicitadas sin superar el valor de la predicción de 330 millones (~329).
7.1. Realice un filtro a la base de datos e incluya solo las ofertas de : base2: apartamentos, de la zona sur de la ciudad. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta. (Adicional un mapa con los puntos de las bases. Discutir si todos los puntos se ubican en la zona correspondiente o se presentan valores en otras zonas, por que?).
kable(head(vivi_2,3), caption = "Encabezados de resgistros vivienda caso 2")
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 |
skim(vivi_2)
| Name | vivi_2 |
| Number of rows | 2787 |
| Number of columns | 13 |
| _______________________ | |
| Column type frequency: | |
| character | 4 |
| numeric | 9 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| zona | 0 | 1.00 | 8 | 8 | 0 | 1 | 0 |
| piso | 622 | 0.78 | 2 | 2 | 0 | 12 | 0 |
| tipo | 0 | 1.00 | 11 | 11 | 0 | 1 | 0 |
| barrio | 0 | 1.00 | 4 | 29 | 0 | 141 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| id | 0 | 1 | 4130.79 | 2116.86 | 3.00 | 2291.50 | 4004.00 | 5876.00 | 8302.00 | ▃▇▇▆▅ |
| estrato | 0 | 1 | 4.63 | 0.84 | 3.00 | 4.00 | 5.00 | 5.00 | 6.00 | ▂▇▁▇▃ |
| preciom | 0 | 1 | 297.29 | 191.55 | 75.00 | 175.00 | 245.00 | 335.00 | 1750.00 | ▇▁▁▁▁ |
| areaconst | 0 | 1 | 97.47 | 52.57 | 40.00 | 65.00 | 85.00 | 110.00 | 932.00 | ▇▁▁▁▁ |
| parqueaderos | 0 | 1 | 1.21 | 0.79 | 0.00 | 1.00 | 1.00 | 2.00 | 10.00 | ▇▁▁▁▁ |
| banios | 0 | 1 | 2.49 | 0.93 | 0.00 | 2.00 | 2.00 | 3.00 | 8.00 | ▁▇▁▁▁ |
| habitaciones | 0 | 1 | 2.97 | 0.63 | 0.00 | 3.00 | 3.00 | 3.00 | 6.00 | ▁▂▇▂▁ |
| longitud | 0 | 1 | -76.53 | 0.01 | -76.57 | -76.54 | -76.53 | -76.52 | -76.46 | ▂▇▆▁▁ |
| latitud | 0 | 1 | 3.39 | 0.03 | 3.33 | 3.37 | 3.38 | 3.41 | 3.50 | ▃▇▃▁▁ |
map4<- leaflet(vivi_2) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
popup = ~paste("ID:", id, "<br>Barrio:", barrio),
radius = 6,
color = "red", fillOpacity = 0.5, stroke = FALSE
)
map4
Se encuentran viviendas fuera del perímetro de la zona sur de la ciudad; se asume que la zona no se encuentra categorizada correctamente y que los valores de latitud y longitud en la data son correctos; se procede a borrar los registros ubicados incorrectamente de los datos a analizar.
# Definir área de interés (rectángulo)
lat_min <- 3.33367
lat_max <- 3.42477
lon_min <- -76.55177
lon_max <- -76.51428
# Filtrar solo puntos dentro del área
vivi_filtrado2 <- vivi_2 %>%
dplyr::filter(
latitud >= lat_min & latitud <= lat_max,
longitud >= lon_min & longitud <= lon_max
)
map5 <- leaflet(vivi_filtrado2) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
popup = ~paste("ID:", id, "<br>Barrio:", barrio),
radius = 6,
color = "blue", fillOpacity = 0.5, stroke = FALSE
)
map5
7.2. Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio de la casa) en función del área construida, estrato, numero de baños, numero de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.
# Selecciona solo las variables numéricas del df
df_num2 <- vivi_filtrado2[c(4:9)]
# Matriz de correlación
mat_cor2 <- cor(df_num2, use = "complete.obs")
# Pasar la matriz a formato largo
df_cor2 <- melt(mat_cor2)
# Graficar heatmap con valores dentro de las celdas
ggplot(df_cor2, aes(Var1, Var2, fill = value)) +
geom_tile(color = "white") +
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1,1), space = "Lab",
name = "Coef. Correlación") +
geom_text(aes(label = round(value, 2)), size = 4) +
theme_minimal() +
theme(axis.text.x = element_text(angle =45, vjust = 1, hjust = 1)) +
labs(title = "Matriz de Correlación",
x = "", y = "")
-El precio se explica principalmente por el área construida (0,76), el número de baños (0,73), la cantidad de parqueaderos (0,7) y el estrato (0,67). Las variables como baños, parqueaderos y estrato tienen una relación superior a 0,48; están muy relacionadas entre sí, lo que puede reducir la relevancia estadística de una de ellas en el modelo..
p1 <- plot_ly(vivi_filtrado2,
x = ~areaconst,
y = ~preciom,
type = 'scatter',
mode = 'markers',
marker = list(size = 8, opacity = 0.6),
color = ~banios # Asignar color según baños
) %>%
layout(title = "Precio vs Área Construida",
xaxis = list(title = "Área Construida (m²)"),
yaxis = list(title = "Precio (millones)"),
coloraxis = list(colorbar = list(title = "Estrato")))
p1
-En la gráfica se puede observar una correlación positiva entre las variables precio y área construida; la dispersión de los datos es menor en áreas inferiores a 200 m² y la mayoría de apartamentos no supera los 1000 millones. Los apartamentos con áreas superiores a 200 m² muestran una dispersión mayor y algunos tienen áreas representativas, pero costos inferiores.
p3 <- plot_ly(vivi_filtrado2, x = ~factor(banios), y = ~preciom, type = "box",
boxpoints = "all", jitter = 0.3, pointpos = -1.8) %>%
layout(title = "Boxplot Precio vs Número de Baños",
xaxis = list(title = "Número de Baños"),
yaxis = list(title = "Precio (millones)"))
p3
El gráfico de precios en función del número de baños permite identificar los siguientes patrones:
-Los apartamentos sin baños: presentan un rango de precios superior al esperado en comparación con las viviendas con 1, 2, 3 o 4 baños. Este comportamiento resulta atípico y sugiere que algunos registros deberían ser revisados, ya que no siguen la tendencia lógica del mercado.
-En apartamentos entre 1 y 6 baños: se evidencia el aumento de la dispersión de los precios en relación con la cantidad de baños.
-Los apartamentos con 7 y 8 baños tienen tan solo un registro, registros insuficientes para alguna observación de la distribución de los datos.
p21 <- plot_ly(vivi_filtrado2, x = ~factor(parqueaderos), y = ~preciom, type = "box",
boxpoints = "all", jitter = 0.3, pointpos = -1.8) %>%
layout(title = "Boxplot Precio vs Parqueaderos",
xaxis = list(title = "Parqueaderos"),
yaxis = list(title = "Precio (millones)"))
p21
El gráfico de distribución de precios por parqueaderos muestra las siguientes diferencias:
-Tendencia general: A medida que aumenta el número de parqueaderos, el precio de la vivienda tiende a incrementarse, lo que confirma que este atributo está asociado con propiedades de mayor valor.
-2 a 4 parqueaderos: Los precios se incrementan progresivamente, con medianas más altas y una mayor dispersión, lo que refleja mayor heterogeneidad en este grupo
-Se observan muy pocos registros con 10 parqueaderos, lo que los convierte en valores atípicos o excepcionales, pero mantienen precios elevados como era de esperar.
7.3. Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f(área construida, estrato, número de cuartos, número de parqueaderos, número de baños ) ) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).
modelo2 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = vivi_filtrado2 )
summary(modelo2)
Call:
lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
banios, data = vivi_filtrado2)
Residuals:
Min 1Q Median 3Q Max
-1157.34 -42.69 -2.27 35.87 937.43
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -218.05208 15.30420 -14.25 < 2e-16 ***
areaconst 1.34792 0.05473 24.63 < 2e-16 ***
estrato 53.16020 3.15316 16.86 < 2e-16 ***
habitaciones -21.83864 3.86544 -5.65 1.81e-08 ***
parqueaderos 57.49571 3.51023 16.38 < 2e-16 ***
banios 53.44848 3.44331 15.52 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 96.5 on 2284 degrees of freedom
Multiple R-squared: 0.7562, Adjusted R-squared: 0.7557
F-statistic: 1417 on 5 and 2284 DF, p-value: < 2.2e-16
Interpretación del modelo:
-El área construida, el estrato, los parqueaderos y los baños son variables determinantes y significativas en el precio de la vivienda
-El efecto negativo de las habitaciones refleja un posible problema de multicolinealidad con otras variables (área, baños), más que un efecto real en el mercado
-El modelo tiene un buen poder predictivo (R² ≈ 76%), pero aún queda un 24% de variabilidad sin explicar, posiblemente asociada con factores como ubicación exacta, barrio, acabados o antigüedad de la vivienda.
vif(modelo2)
areaconst estrato habitaciones parqueaderos banios
2.068606 1.723014 1.392440 1.874004 2.531803
Interpretación:
-Todos los valores están por debajo de 3, lo que indica que no existe un problema grave de multicolinealidad.
-El mayor valor lo tiene baños (2.53), lo cual es lógico porque está correlacionado con habitaciones y área construida, pero no llega a ser preocupante.
7.4. Realice la validación de supuestos del modelo e interprete los resultados (no es necesario corregir en caso de presentar problemas, solo realizar sugerencias de que se podría hacer).
par(mfrow = c(2, 2))
plot(modelo2)
Observaciones:
-En la gráfica de residuales se observa cierta curvatura y dispersión creciente en los residuos a medida que aumenta el valor ajustado
-En la gráfica de normalidad Q-Q, los residuos se desvían bastante de la línea recta, sobre todo en los extremos (colas). Indica que los residuos no son perfectamente normales.
-La gráfica Scale-Location refleja que La dispersión aumenta en valores altos de los ajustes, lo que refuerza la presencia de heterocedasticidad.
-La gráfica de residuos influyentes nos muestra tres datos: 1955, 3815 y 3870; candidatos a revisar por su particularidad de influencia.
bptest(modelo2)
studentized Breusch-Pagan test
data: modelo2
BP = 841.98, df = 5, p-value < 2.2e-16
shapiro.test(modelo2$residuals)
Shapiro-Wilk normality test
data: modelo2$residuals
W = 0.7665, p-value < 2.2e-16
dwtest(modelo2)
Durbin-Watson test
data: modelo2
DW = 1.5249, p-value < 2.2e-16
alternative hypothesis: true autocorrelation is greater than 0
Observaciones:
-Las pruebas realizadas rechazan las hipótesis nulas de homocedasticidad, normalidad y autocorrelación, es decir, el modelo viola varios supuestos clásicos de la regresión lineal.
-Se pueden aplicar transformaciones logarítmicas como solución a la heterocedasticidad y revisar los valores influyentes para el caso de la no normalidad.
7.5. Con el modelo identificado debe predecir el precio de la vivienda con las características de la primera solicitud.
new_vivienda2 <- data.frame(
areaconst = 300,
estrato = c(5,6),
habitaciones = 5,
parqueaderos = 3,
banios = 3
)
predict(modelo2,new_vivienda2)
1 2
675.7653 728.9255
-La predicción del valor de la casa con las características solicitadas en el caso uno es de 675 millones en estrato 5 y 728 millones en el estrato 6, el presupuesto de 850 millones se ajusta al precio para adquirir la vivienda con las caracteristicas.
7.6. Con las predicciones del modelo sugiera potenciales ofertas que responda a la solicitud de la vivienda 2. Tenga encuentra que la empresa tiene crédito pre-aprobado de máximo 850 millones de pesos. Realice un análisis y presente en un mapa al menos 5 ofertas potenciales que debe discutir.
ofertas_2 <- vivi_filtrado2 %>%
filter(
areaconst >= 300, # Rango cercano a 200 m²
estrato >= 5 & estrato <= 6, # Estrato 4 o 5
parqueaderos >= 3, # 1 parqueadero
banios >= 3, # 2 baños
habitaciones >= 5, # 4 habitaciones
preciom <= 730
)
ofertas_2 <- ofertas_2 %>% arrange(preciom)%>% slice_head(n = 5)
kable((ofertas_2), caption = "Inmuebles potenciales caso 2")
| id | zona | piso | estrato | preciom | areaconst | parqueaderos | banios | habitaciones | tipo | barrio | longitud | latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 7512 | Zona Sur | NA | 5 | 670 | 300 | 3 | 5 | 6 | Apartamento | seminario | -76.550 | 3.409 |
| 7182 | Zona Sur | NA | 5 | 730 | 573 | 3 | 8 | 5 | Apartamento | guadalupe | -76.548 | 3.408 |
map22 <- leaflet(ofertas_2) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud, lat = ~latitud,
popup = ~paste("Area:", areaconst, "<br>Precio:", preciom),
radius = 6,
color = "blue", fillOpacity = 0.5, stroke = FALSE
)
map22
-El filtro seleccionado tan solo arroja dos propuestas que cumplen con las características solicitadas sin superar el valor de la predicción de 730 millones (~728).