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).
La compañía C&A, en aras de dar la mejor solución a nuestros clientes, quiere determinar las mejores opciones de vivienda que se ajuste al presupuesto y gustos de los solicitantes. Es por esto por lo que, para dar solución a la solicitud, se puso en marcha la iniciativa junto al área de analítica de datos, para la creación de un modelo que pudiera pronosticar adecuadamente el precio de una vivienda por medio de las características suministradas por la empresa internacional. Para esto, se uso un algoritmo de regresión lineal múltiple, el cual está construido mediante las variables área construida, estrato, número de cuartos, número de parqueaderos y número de baños, garantizando la mejor ubicación para los dos empleados de la empresa y sus familias.
Para hacerlo aún mas personalizado, se crearon dos modelos para cada una de las 2 solicitudes, uno teniendo en cuenta casas de la zona norte y otro para los apartamentos de la zona sur. Esto garantizó que el algoritmo solo se entrenara con los patrones y características de cada una de esas zonas.
Interpretación del modelo
El primer modelo está enfocado en la primera solicitud. El impacto de cada variable sobre el precio de la vivienda es el siguiente:
\[ precio_m = 33.96564 + 0.83083 \times areaconst + 84.28927 \times estrato4 + 137.92112 \times estrato5 + 327.80065 \times estrato6 + 27.10245 \times banios + \varepsilon \]
Además, el R2, el cual es una métrica para medir el rendimiento del modelo, es de 0.66, lo que indica que aproximadamente el 66% de la variabilidad del precio de un inmueble es explicada por las variables explicativas del modelo, lo cual es un rendimiento bastante aceptable.
El segundo modelo esta enfocado en la segunda solicitud. El
impacto de cada variable sobre el precio es la siguiente:
\[ precio_m = -42.3541 + 2.6247
\times areaconst + 5.4340 \times estrato4 + 8.4178 \times estrato5 +
121.4733 \times estrato6 - 28.3972 \times habitaciones + 48.4498 \times
parqueaderos + 28.7492 \times banios + \varepsilon \]
Adicionalmente, se tiene un rendimiento bastante bueno, con un R2 de 0.86, es decir, que las variables incluidas explican aproximadamente el 86% de la variabilidad del precio, lo cual es bastante bueno.
La predicción de la solicitud
Tras construirse el modelo, se procede a realizar una predicción para cada una de las solicitudes, para determinar si las características sugeridas se adaptan al limite del presupuesto aprobado para cada empleado.
Para la primera solicitud se tiene la siguiente
predicción:
| Características | Vivienda 1 |
|---|---|
| Tipo | Casa |
| Área construida | 200 |
| Parqueaderos | 1 |
| Baños | 2 |
| Habitaciones | 4 |
| Estrato | 4 o 5 |
| Zona | Norte |
| Crédito preaprobado | 350 millones |
Debido a que 2 de las variables no fueron estadísticamente significativas en este modelo, no se incluirán en la predicción.
Predicción para estrato 4: 338 millones
Predicción para estrato 5: 392 millones
Por lo tanto, la mejor opción para la familia 1 es una casa de
estrato 4 con un área construida de 200 metros cuadrados, 1 parqueadero,
2 baños y 4 habitaciones puesto que es acorde al presupuesto aprobado de
350 millones.
Para la segunda solicitud se tiene la siguiente
predicción:
| Características | Vivienda 2 |
|---|---|
| Tipo | Apartamento |
| Área construida | 300 |
| Parqueaderos | 3 |
| Baños | 3 |
| Habitaciones | 5 |
| Estrato | 5 o 6 |
| Zona | Sur |
| Crédito preaprobado | 850 millones |
Predicción para estrato 4: 843 millones
Predicción para estrato 5: 956 millones
Esto significa que la mejor opción para la familia 2 es un apartamento de estrato 5 con un área construida de 300 metros cuadrados, 3 parqueaderos, 3 baños y 4 habitaciones puesto que es acorde al presupuesto aprobado de 350 millones.
Adicionalmente, desde la empresa C&A, y gracias al modelo construido, se pueden realizar diversas predicciones que pueden generar nuevas opciones de apartamentos y casas que igualmente se ajustan al presupuesto establecido para los 2 empleados. Ademas, se muestra a continuación algunas ofertas atractivas para ubicar adecadamente a la familia 1 y 2. (para ver la ubicación geoespacial de estas ofertas, ver Anexo)
Solicitud 1:
Para la primera solicitud se tienen estas ofertas con las siguientes características, algunas de ellas con el mínimo o mejores características a las solicitadas:
| Piso | Estrato | Precio | Área Construida | Parqueaderos | Baños | Habitaciones | Barrio |
|---|---|---|---|---|---|---|---|
| 2 | 4 | 330 | 240 | 1 | 4 | 4 | Acopi |
| 1 | 5 | 350 | 200 | 3 | 3 | 4 | El Bosque |
| 1 | 5 | 335 | 202 | 1 | 4 | 5 | El Bosque |
| 1 | 5 | 340 | 250 | 2 | 4 | 4 | El Bosque |
| 2 | 5 | 350 | 300 | 3 | 5 | 6 | El Bosque |
Solicitud 2:
Para la segunda solicitud se tienen estas ofertas con las siguientes características. Igualmente algunas de ellas con el mínimo o mejores características a las solicitadas:
| Piso | Estrato | Precio | Área Construida | Parqueaderos | Baños | Habitaciones | Barrio |
|---|---|---|---|---|---|---|---|
| 2 | 5 | 730 | 573 | 3 | 8 | 5 | Guadalupe |
| 2 | 5 | 670 | 300 | 3 | 5 | 6 | Seminario |
Sin embargo, para la segunda solicitud solo se tienen 2 ofertas del total de la base de datos. A pesar de esto, basandonos en el modelo predictivo que se construyó, se predicen 4 nuevas sugerencias que pueden ser en algun punto potenciales ofertas y que se ajustan igualmente al presupuesto. Para esto, se variaron ligeramente algunas características de lo solicitado para la familia 2, pero sin compremeter sustancialmente sus preferencias.
| Oferta | Tipo | Área Construida | Parqueaderos | Baños | Habitaciones | Estrato | Precio Estimado |
|---|---|---|---|---|---|---|---|
| 1 | Apartamento | 300 | 3 | 2 | 4 | 5 | 842.7312 |
| 2 | Apartamento | 255 | 3 | 3 | 5 | 6 | 838.0274 |
| 3 | Apartamento | 320 | 2 | 3 | 5 | 5 | 847.1273 |
| 4 | Apartamento | 275 | 2 | 1 | 3 | 6 | 841.3676 |
| Paso | Descripción de la Tarea | Metodología para Obtener los Datos |
|---|---|---|
| 1 | Filtro de la base de datos para incluir solo casas de la zona norte o zona sur | Seleccionar registros donde el tipo de vivienda sea “Casa” y la zona sea “Norte” de la ciudad. |
| 2 | Análisis exploratorio de datos enfocado en la correlación | Utilizar el paquete plotly en R para crear gráficos
interactivos de dispersión entre las variables de interés. |
| 3 | Estimación de un modelo de regresión lineal múltiple | Utilizar el paquete stats en R para ajustar un modelo
de regresión lineal con las variables seleccionadas. |
| 4 | Validación de supuestos del modelo | Utilizar herramientas de diagnóstico de regresión como gráficos de residuos, pruebas de normalidad y homocedasticidad. |
| 5 | Predicción del precio de la vivienda | Utilizar el modelo de regresión lineal múltiple estimado para predecir el precio de la vivienda solicitada. |
| 6 | Selección de ofertas potenciales | Utilizar el modelo de regresión para identificar viviendas que se ajusten al presupuesto de la empresa. |
| 7 | Repetir pasos del 1 al 6 para la segunda solicitud | Realizar nuevamente los pasos anteriores para la segunda solicitud, teniendo en cuenta el nuevo presupuesto. |
Importación de la base de datos
library(naniar)
library(ggplot2)
datos <- read.csv(file = "vivienda.csv",
header = TRUE,
sep = ";")
head(datos)
## id zona piso estrato preciom areaconst parqueaderos banios
## 1 1147 Zona Oriente NA 3 250 70 1 3
## 2 1169 Zona Oriente NA 3 320 120 1 2
## 3 1350 Zona Oriente NA 3 350 220 2 2
## 4 5992 Zona Sur 2 4 400 280 3 5
## 5 1212 Zona Norte 1 5 260 90 1 2
## 6 1724 Zona Norte 1 5 240 87 1 3
## habitaciones tipo barrio longitud latitud
## 1 6 Casa 20 de julio -76,51168 3,43382
## 2 3 Casa 20 de julio -76,51237 3,43369
## 3 4 Casa 20 de julio -76,51537 3,43566
## 4 3 Casa 3 de julio -76,54 3,435
## 5 3 Apartamento acopi -76,5135 3,45891
## 6 3 Apartamento acopi -76,517 3,36971
Tratamiento de datos faltantes
Se observa que la variable “piso” y “parqueaderos” tienen un
31 y 19 por ciennto de datos faltantes respectivamente, por lo que es
necesario realizar un tratamiento de datos faltantes en esas dos
variables.
round(colSums(is.na(datos)) / nrow(datos) * 100, 2)
## id zona piso estrato preciom areaconst
## 0.04 0.00 31.70 0.04 0.02 0.00
## parqueaderos banios habitaciones tipo barrio longitud
## 19.29 0.04 0.04 0.00 0.00 0.00
## latitud
## 0.00
vis_miss(datos)
El método seleccionado en este caso es el de imputación por
la moda, esto debido a que son variables numéricas discretas y la moda
se adapta mejor a ellos.
datos$areaconst <- gsub(",", ".", datos$areaconst)
imputar_moda <- function(x) {
moda <- names(sort(table(x), decreasing = TRUE))[1]
x_imputada <- ifelse(is.na(x), moda, x)
return(x_imputada)
}
datos <- as.data.frame(lapply(datos, imputar_moda))
Resultado final de la base de datos sin datos
faltantes
vis_miss(datos)
Se reemplaza las comas por puntos en las variables relacionadas con las coordenadas
datos$longitud <- gsub(",", ".", datos$longitud)
datos$latitud <- gsub(",", ".", datos$latitud)
Convertir variables a numéricas y categóricas
Se convierten las variables a sus respectivos tipos de
datos. En este caso son 4 variables categóricas y 6 variables
numéricas.
# Convertir a enteros las variables numéricas convertidas de texto
datos$piso <- as.integer(datos$piso)
datos$preciom <- as.integer(datos$preciom)
datos$areaconst <- as.numeric(datos$areaconst)
datos$parqueaderos <- as.integer(datos$parqueaderos)
datos$banios <- as.integer(datos$banios)
datos$habitaciones <- as.integer(datos$habitaciones)
datos$zona <- factor(datos$zona, levels = c("Zona Centro", "Zona Norte", "Zona Oeste", "Zona Oriente", "Zona Sur"))
datos$estrato <- as.factor(datos$estrato)
datos$tipo <- factor(datos$tipo, levels = c("Casa", "Apartamento"))
datos$barrio <- as.factor(datos$barrio)
# Eliminar filas con valores faltantes
datos <- na.omit(datos)
Tratamiento de datos atípicos
Se verifica si en las variables numéricas existe presencia
de valores atípicos que puedan perjudicar el análisis o la ejecución del
modelo. Para esto se hace uso del rango intercuartílico. Como se
observa, ningún registro está por fuera de los rangos intercuartílicos,
por lo que no hay presencia de outliers.
# Calcular el IQR para una columna 'x' en un data frame 'datos'
Q1 <- quantile(datos$x, 0.25)
Q3 <- quantile(datos$x, 0.75)
IQR <- Q3 - Q1
# Definir los límites para identificar outliers
lower <- Q1 - 1.5 * IQR
upper <- Q3 + 1.5 * IQR
# Identificar outliers
datos$x[datos$piso < lower | datos$piso > upper]
## NULL
datos$x[datos$preciom < lower | datos$preciom > upper]
## NULL
datos$x[datos$areaconst < lower | datos$areaconst > upper]
## NULL
datos$x[datos$parqueaderos < lower | datos$parqueaderos > upper]
## NULL
datos$x[datos$banios < lower | datos$banios > upper]
## NULL
datos$x[datos$habitaciones < lower | datos$habitaciones > upper]
## NULL
1. Filtros
Se filtra la base de datos para tener en cuenta solo casas en la zona norte.
# Filtrar las ofertas de casas en la zona norte de la ciudad
ofertas_norte <- subset(datos, tipo == "Casa" & zona == "Zona Norte")
# Mostrar los primeros 3 registros de las bases
head(ofertas_norte, 3)
## id zona piso estrato preciom areaconst parqueaderos banios
## 9 1209 Zona Norte 2 5 320 150 2 4
## 10 1592 Zona Norte 2 5 780 380 2 3
## 11 4057 Zona Norte 2 6 750 445 1 7
## habitaciones tipo barrio longitud latitud
## 9 6 Casa acopi -76.51341 3.47968
## 10 3 Casa acopi -76.51674 3.48721
## 11 6 Casa acopi -76.5295 3.38527
# Porcentaje de ofertas de casas en la zona norte
prop_ofertas_norte <- nrow(ofertas_norte) / nrow(datos)
print("Porcentaje de ofertas de casas en la zona norte:")
## [1] "Porcentaje de ofertas de casas en la zona norte:"
print(prop_ofertas_norte * 100)
## [1] 8.678928
2. Análisis exploratorio
Para variables numéricas con el precio:
library(plotly)
# 2. Gráfico de dispersión interactivo para cada variable
plot_area <- plot_ly(ofertas_norte, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers', marker = list(color = ~areaconst)) %>%
layout(title = 'Precio de la Casa vs. Área Construida',
xaxis = list(title = 'Área Construida'),
yaxis = list(title = 'Precio de la Casa'))
# 3. Calcular la matriz de correlación
correlation_matrix <- cor(ofertas_norte[, c("preciom", "areaconst", "banios", "habitaciones")])
# 4. Visualizar la matriz de correlación como un mapa de calor interactivo
plot_correlation <- plot_ly(z = ~correlation_matrix, colorscale = 'Reds', type = 'heatmap')
# Mostrar los gráficos
plot_area
correlation_matrix
## preciom areaconst banios habitaciones
## preciom 1.0000000 0.7313480 0.5233357 0.3227096
## areaconst 0.7313480 1.0000000 0.4628152 0.3753323
## banios 0.5233357 0.4628152 1.0000000 0.5755314
## habitaciones 0.3227096 0.3753323 0.5755314 1.0000000
plot_correlation
Para variables categóricas con precio:
# Gráfico de barras para la relación entre el estrato y el precio de la casa
plot_estrato <- plot_ly(ofertas_norte, x = ~factor(estrato), y = ~preciom, type = 'bar', marker = list(color = ~preciom)) %>%
layout(title = 'Precio de la Casa por Estrato',
xaxis = list(title = 'Estrato'),
yaxis = list(title = 'Precio de la Casa'))
# Mostrar los gráficos
subplot(plot_estrato)
3. Modelo
set.seed(123)
id_train_1 <- sample(1:nrow(ofertas_norte), round(0.7 * nrow(ofertas_norte)))
train_1 <- ofertas_norte[id_train_1, ]
test_1 <- ofertas_norte[-id_train_1, ]
modelo1 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = train_1)
summary(modelo1)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = train_1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -653.27 -71.35 -14.28 47.17 947.14
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 33.36100 19.45140 1.715 0.087 .
## areaconst 0.80541 0.05017 16.055 < 2e-16 ***
## estrato4 83.42305 18.98245 4.395 1.36e-05 ***
## estrato5 130.03241 18.33088 7.094 4.52e-12 ***
## estrato6 344.32935 28.91361 11.909 < 2e-16 ***
## habitaciones 0.25580 4.53959 0.056 0.955
## parqueaderos 2.69060 5.82382 0.462 0.644
## banios 28.45758 5.79086 4.914 1.21e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 145.9 on 497 degrees of freedom
## Multiple R-squared: 0.686, Adjusted R-squared: 0.6816
## F-statistic: 155.1 on 7 and 497 DF, p-value: < 2.2e-16
Se vuelve a correr el modelo pero solo con las variables estadísticamente significativas
modelo1 <- lm(preciom ~ areaconst + estrato + banios, data = ofertas_norte)
summary(modelo1)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + banios, data = ofertas_norte)
##
## Residuals:
## Min 1Q Median 3Q Max
## -968.77 -73.13 -16.35 45.27 1069.02
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 33.96564 15.51078 2.190 0.0289 *
## areaconst 0.83083 0.04177 19.889 < 2e-16 ***
## estrato4 84.28927 16.89775 4.988 7.66e-07 ***
## estrato5 137.92112 15.73297 8.766 < 2e-16 ***
## estrato6 327.80065 25.82630 12.693 < 2e-16 ***
## banios 27.10245 4.50506 6.016 2.85e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 156.8 on 716 degrees of freedom
## Multiple R-squared: 0.661, Adjusted R-squared: 0.6587
## F-statistic: 279.3 on 5 and 716 DF, p-value: < 2.2e-16
4. Validación de supuestos
library(lmtest)
bptest(modelo1)
##
## studentized Breusch-Pagan test
##
## data: modelo1
## BP = 132.54, df = 5, p-value < 2.2e-16
h0: No hay heterocedasticidad en los errores
del modelo
ha: Existe heterocedasticidad en los errores del modelo
Debido a que el pvalor es muy pequeño, se niega la hipótesis nula, por lo que los existe heterocedasticidad.
shapiro.test(resid(modelo1))
##
## Shapiro-Wilk normality test
##
## data: resid(modelo1)
## W = 0.83045, p-value < 2.2e-16
h0: Los residuos del modelo siguen una
distribución normal.
ha: Los residuos del modelo no siguen una distribución normal.
Debido a que el pvalor es muy pequeño, se niega la hipótesis nula, por lo que los residuos del modelo no siguen una distribución normal.
dwtest(modelo1)
##
## Durbin-Watson test
##
## data: modelo1
## DW = 1.69, p-value = 1.163e-05
## alternative hypothesis: true autocorrelation is greater than 0
h0: No hay autocorrelación en los residuos del
modelo.
ha: Existe autocorrelación en los residuos del modelo.
Debido a que el pvalor es muy pequeño, se niega la hipótesis nula, por lo que existe autocorrelación en los residuos.
library(car)
vif(modelo1)
## GVIF Df GVIF^(1/(2*Df))
## areaconst 1.430202 1 1.195910
## estrato 1.376739 3 1.054732
## banios 1.382317 1 1.175720
Según el factor de inflación de la varianza (VIF), cada variable
del modelo posee valores menores a 10, lo que sugiere que no hay una
colinealidad considerable entre las variables predictoras del
modelo.
5. Predicción
# Para estrato 4
predict(modelo1, list(areaconst= 200,estrato= "4", banios=2))
## 1
## 338.6254
# Para estrato 5
predict(modelo1, list(areaconst= 200,estrato= "5", banios=2))
## 1
## 392.2572
6. Sugerencia de ofertas
El modelo construido arroja la siguiente predicción con las características que quiere el cliente.
# Oferta principal
predict(modelo1, list(areaconst= 200,estrato= "4", banios=2))
## 1
## 338.6254
Teniendo en cuenta la base de datos, se busca 5 sugerencias de casas que cumplan con las sugerencias y presupuesto establecido para la familiar 1. Para esto, se ilustra visualiza mediante un mapa de la ciudad de Cali, la ubicación de las 5 propuestas sugeridas por la empresa.
ofertas_norte$estrato <- as.numeric(as.character(ofertas_norte$estrato))
ofertas_filtradas1 <- subset(ofertas_norte,
areaconst >= 200 &
estrato >= 4 &
habitaciones >= 4 &
parqueaderos >= 1 &
banios >= 2 &
preciom <= 350)
nrow(ofertas_filtradas1)
## [1] 39
Características de las 5 sugerencias.
head(ofertas_filtradas1, 5)
## id zona piso estrato preciom areaconst parqueaderos banios
## 155 7471 Zona Norte 2 4 330 240 1 4
## 2163 4210 Zona Norte 1 5 350 200 3 3
## 2165 4267 Zona Norte 1 5 335 202 1 4
## 2173 4800 Zona Norte 1 5 340 250 2 4
## 2183 4209 Zona Norte 2 5 350 300 3 5
## habitaciones tipo barrio longitud latitud
## 155 4 Casa acopi -76.5498 3.39758
## 2163 4 Casa el bosque -76.5301 3.48503
## 2165 5 Casa el bosque -76.53044 3.48399
## 2173 4 Casa el bosque -76.533 3.465
## 2183 6 Casa el bosque -76.5301 3.48577
Ubicación de las sugerencias.
library(leaflet)
sugerencias1 <- data.frame(
ciudad = c("Ciudad A", "Ciudad B", "Ciudad C", "Ciudad D", "Ciudad E"),
longitud = c(-76.5498, -76.5301, -76.53044, -76.533, -76.5301),
latitud = c(3.39758, 3.48503, 3.48399, 3.465, 3.48577)
)
mapa <- leaflet(data = sugerencias1) %>%
addTiles() %>%
setView(lng = -76.5, lat = 3.4, zoom = 12) %>%
addMarkers(lng = ~longitud, lat = ~latitud, popup = ~ciudad)
mapa
1. Filtros
ofertas_sur <- subset(datos, tipo == "Apartamento" & zona == "Zona Sur")
# Mostrar los primeros 3 registros de las bases
head(ofertas_sur, 3)
## id zona piso estrato preciom areaconst parqueaderos banios
## 24 5098 Zona Sur 5 4 290 96 1 2
## 164 698 Zona Sur 2 3 78 40 1 1
## 264 8199 Zona Sur 2 6 875 194 2 5
## habitaciones tipo barrio longitud latitud
## 24 3 Apartamento acopi -76.53464 3.44987
## 164 2 Apartamento aguablanca -76.501 3.4
## 264 3 Apartamento aguacatal -76.557 3.459
# Proporción de ofertas de casas en la zona sur
prop_ofertas_sur <- nrow(ofertas_sur) / nrow(datos)
print("Porcentaje de ofertas de casas en la zona sur:")
## [1] "Porcentaje de ofertas de casas en la zona sur:"
print(prop_ofertas_sur * 100)
## [1] 33.50162
2. Análisis exploratorio
Para variables
numéricas con el precio:
library(plotly)
# 2. Gráfico de dispersión interactivo para cada variable
plot_area <- plot_ly(ofertas_sur, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers', marker = list(color = ~areaconst)) %>%
layout(title = 'Precio de la Casa vs. Área Construida',
xaxis = list(title = 'Área Construida'),
yaxis = list(title = 'Precio de la Casa'))
# 3. Calcular la matriz de correlación
correlation_matrix <- cor(ofertas_sur[, c("preciom", "areaconst", "banios", "habitaciones")])
# 4. Visualizar la matriz de correlación como un mapa de calor interactivo
plot_correlation <- plot_ly(z = ~correlation_matrix, colorscale = 'Reds', type = 'heatmap')
# Mostrar los gráficos
plot_area
correlation_matrix
## preciom areaconst banios habitaciones
## preciom 1.0000000 0.7579955 0.7196705 0.3317538
## areaconst 0.7579955 1.0000000 0.6618179 0.4339608
## banios 0.7196705 0.6618179 1.0000000 0.5149227
## habitaciones 0.3317538 0.4339608 0.5149227 1.0000000
plot_correlation
Para variables categóricas con precio:
# Gráfico de barras para la relación entre el estrato y el precio de la casa
plot_estrato <- plot_ly(ofertas_norte, x = ~factor(estrato), y = ~preciom, type = 'bar', marker = list(color = ~preciom)) %>%
layout(title = 'Precio de la Casa por Estrato',
xaxis = list(title = 'Estrato'),
yaxis = list(title = 'Precio de la Casa'))
# Mostrar los gráficos
subplot(plot_estrato)
3. Modelo
set.seed(345)
id_train_2 <- sample(1:nrow(ofertas_sur), round(0.7 * nrow(ofertas_sur)))
train_2 <- ofertas_sur[id_train_1, ]
test_2 <- ofertas_sur[-id_train_1, ]
modelo2 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = train_2)
summary(modelo2)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = train_2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -310.58 -32.47 -0.57 31.96 672.24
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -42.3541 22.7300 -1.863 0.063 .
## areaconst 2.6247 0.1296 20.253 < 2e-16 ***
## estrato4 5.4340 14.8978 0.365 0.715
## estrato5 8.4178 15.9587 0.527 0.598
## estrato6 121.4733 18.0227 6.740 4.40e-11 ***
## habitaciones -28.3972 7.1131 -3.992 7.53e-05 ***
## parqueaderos 48.4498 9.5660 5.065 5.77e-07 ***
## banios 28.7492 6.8033 4.226 2.83e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 85.89 on 497 degrees of freedom
## Multiple R-squared: 0.8644, Adjusted R-squared: 0.8625
## F-statistic: 452.5 on 7 and 497 DF, p-value: < 2.2e-16
4. Validación de supuestos
bptest(modelo1)
##
## studentized Breusch-Pagan test
##
## data: modelo1
## BP = 132.54, df = 5, p-value < 2.2e-16
h0: No hay heterocedasticidad en los errores
del modelo
ha: Existe heterocedasticidad en los errores del modelo
Debido a que el pvalor es muy pequeño, se niega la hipótesis nula, por lo que los existe heterocedasticidad.
shapiro.test(resid(modelo1))
##
## Shapiro-Wilk normality test
##
## data: resid(modelo1)
## W = 0.83045, p-value < 2.2e-16
h0: Los residuos del modelo siguen una
distribución normal.
ha: Los residuos del modelo no siguen una distribución normal.
Debido a que el pvalor es muy pequeño, se niega la hipótesis nula, por lo que los residuos del modelo no siguen una distribución normal.
dwtest(modelo1)
##
## Durbin-Watson test
##
## data: modelo1
## DW = 1.69, p-value = 1.163e-05
## alternative hypothesis: true autocorrelation is greater than 0
h0: No hay autocorrelación en los residuos del
modelo.
ha: Existe autocorrelación en los residuos del modelo.
Debido a que el pvalor es muy pequeño, se niega la hipótesis nula, por lo que existe autocorrelación en los residuos.
vif(modelo1)
## GVIF Df GVIF^(1/(2*Df))
## areaconst 1.430202 1 1.195910
## estrato 1.376739 3 1.054732
## banios 1.382317 1 1.175720
Según el factor de inflación de la varianza (VIF), cada variable
del modelo posee valores menores a 10, lo que sugiere que no hay una
colinealidad considerable entre las variables predictoras del
modelo.
5. Predicción
# Para estrato 5
predict(modelo2, list(tipo = "Apartamento", areaconst=300, parqueaderos=3, banios=3, habitaciones=5, estrato="5"))
## 1
## 843.0832
# Para estrato 6
predict(modelo2, list(tipo = "Apartamento", areaconst=300, parqueaderos=3, banios=3, habitaciones=5, estrato="6"))
## 1
## 956.1387
6. Sugerencia de ofertas
El modelo construido arroja la siguiente predicción con las características que quiere el cliente.
# Oferta principal
predict(modelo2, list(tipo = "Apartamento", areaconst=300, parqueaderos=3, banios=3, habitaciones=5, estrato="5"))
## 1
## 843.0832
Teniendo en cuenta la base de datos, se busca 5 sugerencias de casas
que cumplan con las sugerencias y presupuesto establecido para la
familiar 1. Para esto, se ilustra visualiza mediante un mapa de la
ciudad de Cali, la ubicación de las 5 propuestas sugeridas por la
empresa.
ofertas_sur$estrato <- as.numeric(as.character(ofertas_sur$estrato))
ofertas_filtradas2 <- subset(ofertas_sur,
areaconst >= 300 &
estrato >= 5 &
habitaciones >= 5 &
parqueaderos >= 3 &
banios >= 3 &
preciom <= 850)
nrow(ofertas_filtradas2)
## [1] 2
Características de las 5 sugerencias.
head(ofertas_filtradas2, 5)
## id zona piso estrato preciom areaconst parqueaderos banios
## 3251 7182 Zona Sur 2 5 730 573 3 8
## 6669 7512 Zona Sur 2 5 670 300 3 5
## habitaciones tipo barrio longitud latitud
## 3251 5 Apartamento guadalupe -76.548 3.408
## 6669 6 Apartamento seminario -76.55 3.409
Ubicación de las sugerencias.
library(leaflet)
sugerencias2 <- data.frame(
ciudad = c("Ciudad A", "Ciudad B"),
longitud = c(-76.548, -76.55),
latitud = c(3.408, 3.409)
)
mapa <- leaflet(data = sugerencias2) %>%
addTiles() %>%
setView(lng = -76.5, lat = 3.4, zoom = 12) %>%
addMarkers(lng = ~longitud, lat = ~latitud, popup = ~ciudad)
mapa
Debido a que solo existen 2 ofertas con estas características en
la base de datos, a continuación se usa el modelo para determinar otras
4 posibles sugerencias que se pueden llegar a adaptar al presupuesto
aprobado, cambiando ligeramente algunas características de las
solicitudes.
# Ofertas opcionadas
predict(modelo2, list(tipo = "Apartamento", areaconst=300, parqueaderos=3, banios=2, habitaciones=4, estrato="5"))
## 1
## 842.7312
predict(modelo2, list(tipo = "Apartamento", areaconst=255, parqueaderos=3, banios=3, habitaciones=5, estrato="6"))
## 1
## 838.0274
predict(modelo2, list(tipo = "Apartamento", areaconst=320, parqueaderos=2, banios=3, habitaciones=5, estrato="5"))
## 1
## 847.1273
predict(modelo2, list(tipo = "Apartamento", areaconst=275, parqueaderos=2, banios=1, habitaciones=3, estrato="6"))
## 1
## 841.3676