1. Introducción

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).

2. Objetivo

3. Métodos

Los datos son obtenidos de la librería paqueteMETODOS de R y, analizados a través de la misma herramienta haciendo uso de diferentes paquetes que permiten realizar un análisis estadístico de acuerdo a la siguiente metodología.

3.1. Cargue de datos

3.2. Identificación de datos faltantes por variable

faltantes <- colSums(is.na(vivienda)) %>% as.data.frame() 
faltantes
##                 .
## id              3
## zona            3
## piso         2638
## estrato         3
## preciom         2
## areaconst       3
## parqueaderos 1605
## banios          3
## habitaciones    3
## tipo            3
## barrio          3
## longitud        3
## latitud         3

3.3. Imputación y estandarización de datos

  • Imputar por cero. Los datos faltantes de la variable “parqueaderos” sugiere que esos inmuebles no tienen parqueaderos.
vivienda$parqueaderos[is.na(vivienda$parqueaderos)] <- 0
  • Imputar por la moda. La variable “piso” es cualitativa de escala ordinal, por lo que los datos faltantes se reemplazan por la moda.
moda_piso <- Mode(vivienda$piso, na.rm = TRUE)
vivienda$piso[is.na(vivienda$piso)] <- moda_piso
  • Eliminar registros con datos faltantes.
vivienda <- na.omit(vivienda)
  • Estandarizar variable “tipo” ya que realmente consta de dos opciones.
vivienda$tipo <- ifelse(vivienda$tipo=="Casa","CASA",ifelse(vivienda$tipo=="casa","CASA",vivienda$tipo))
vivienda$tipo <- ifelse(vivienda$tipo=="apto","APARTAMENTO",ifelse(vivienda$tipo=="Apartamento","APARTAMENTO",vivienda$tipo))
  • Homogeneizar variable “barrio”.
vivienda$barrio <- trimws(chartr("ÁÉÍÓÚ", "AEIOU", toupper(vivienda$barrio)))
  • Ajustar las variables “longitud” y “latitud” de acuerdo a las coordenadas válidas.
vivienda$longitud <- ifelse(vivienda$longitud<=-90,vivienda$longitud/1000,vivienda$longitud)
vivienda$latitud <- ifelse(vivienda$latitud>=270,vivienda$latitud/1000,vivienda$latitud)
  • Definir las varibles “estrato” y “piso” como cualitativas de escala ordinal.
vivienda$estrato <- as.character(vivienda$estrato) 
vivienda$piso <- as.character(vivienda$piso) 
  • Verificar que después de la imputación no se cuenta con datos faltantes.
faltantes <- colSums(is.na(vivienda)) %>% as.data.frame() 
faltantes
##              .
## id           0
## zona         0
## piso         0
## estrato      0
## preciom      0
## areaconst    0
## parqueaderos 0
## banios       0
## habitaciones 0
## tipo         0
## barrio       0
## longitud     0
## latitud      0

4. Pasos requeridos para la obtención de los resultados

Una vez realizada la imputación y estandarización de datos, se tiene la base que hará parte del análisis.

vivienda <- data.frame(vivienda)
head(vivienda,3)
##     id         zona piso estrato preciom areaconst parqueaderos banios
## 1 1147 Zona Oriente   02       3     250        70            1      3
## 2 1169 Zona Oriente   02       3     320       120            1      2
## 3 1350 Zona Oriente   02       3     350       220            2      2
##   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.1. Construcción de base de datos.

1. Realice un filtro a la base de datos e incluya solo las ofertas de : base1: casas, de la zona norte 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?).

Inicialmente se realizan filtros sobre las variables “tipo” (CASA) y “zona” (Zona Norte). Obteniendo 722 viviendas.

vivienda1 <- dplyr::filter(vivienda, tipo=="CASA" & zona=="Zona Norte")
nrow(vivienda1)
## [1] 722

Sin embargo, al generar un mapa preliminar se evidencian viviendas en otras zonas, por lo que se procede a delimitar una latitud y una longitud con puntos estratégicos de la ciudad de Cali, y se adiciona al filtro inicial. Así pues, se seleccionan las viviendas que tienen latitud superior a la del Acuaparque de la caña (3.4556) y longitud mayor a la de Cuchilla La Estaca (-76.5403). Adicionalmente se omiten aquellas viviendas que no registran baños ni habitaciones. Obteniendo 522 viviendas, es decir, 200 viviendas menos.

Se crea la base de datos “vivienda1”.

vivienda1 <- dplyr::filter(vivienda, tipo=="CASA" & zona=="Zona Norte" & banios>0 & habitaciones>0
                           & latitud>=3.4556 & longitud>=-76.5403)

library(DT)
datatable(vivienda1, list(pageLength=3))
knitr::kable (summary(vivienda1))
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
Min. : 88.0 Length:522 Length:522 Length:522 Min. : 110.0 Min. : 30.0 Min. : 0.000 Min. : 1.000 Min. : 2.000 Length:522 Length:522 Min. :-76.54 Min. :3.456
1st Qu.: 598.8 Class :character Class :character Class :character 1st Qu.: 236.2 1st Qu.: 132.2 1st Qu.: 0.000 1st Qu.: 2.000 1st Qu.: 3.000 Class :character Class :character 1st Qu.:-76.52 1st Qu.:3.468
Median :1348.0 Mode :character Mode :character Mode :character Median : 370.0 Median : 230.0 Median : 1.000 Median : 3.000 Median : 4.000 Mode :character Mode :character Median :-76.52 Median :3.476
Mean :1984.9 NA NA NA Mean : 416.7 Mean : 252.5 Mean : 1.506 Mean : 3.515 Mean : 4.615 NA NA Mean :-76.51 Mean :3.476
3rd Qu.:3167.5 NA NA NA 3rd Qu.: 528.8 3rd Qu.: 330.0 3rd Qu.: 2.000 3rd Qu.: 4.000 3rd Qu.: 5.000 NA NA 3rd Qu.:-76.50 3rd Qu.:3.484
Max. :5821.0 NA NA NA Max. :1800.0 Max. :1440.0 Max. :10.000 Max. :10.000 Max. :10.000 NA NA Max. :-76.48 Max. :3.496

Se crea el mapa con las viviendas seleccionadas según la base “vivienda1”.

# install.packages("leaflet")
library(leaflet)

vivienda1.coord <- data.frame(
  lat = c(vivienda1$latitud),
  long = c(vivienda1$longitud)
)

# Crea un mapa
map <- leaflet(vivienda1.coord) %>%
  addTiles() %>%
  addMarkers(
    lng = ~long,
    lat = ~lat,
    layerId = 1,
    popup = ~as.character(lat)
  ) %>%
  addRectangles(
    lng1=-76.5403, lat1=3.4556,
    lng2=max(vivienda1$longitud), lat2=max(vivienda1$latitud),
    fillColor = "transparent",color="red"
  ) 

# Muestra el mapa
map

4.2. Análisis exploratorio de datos.

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.

Al analizar la correlación entre el precio de las viviendas y el estrato mediante un gráfico de cajas y alambres se evidencia claramente que a mayor estrato mayor precio promedio de las casas de la zona norte.

plot_ly(vivienda1, x = ~estrato, y = ~preciom, type = 'box') 
kruskal.test(preciom ~ estrato, data = vivienda1)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  preciom by estrato
## Kruskal-Wallis chi-squared = 278.2, df = 3, p-value < 2.2e-16

Ahora se analiza el precio de las viviendas frente al área construida mediante un gráfico de dispersión, evidenciando que a mayor área contruida mayor es el precio, con un coeficiente de correlación de \(0.7419\).

plot1 <- ggplot(vivienda1, aes(x = areaconst, y = preciom)) +
  geom_point(aes(color = estrato)) +
  labs(x = "Área Construida (m2)",
       y = "Precio (millones)") +
  theme_minimal()

ggplotly(plot1)
round(cor(vivienda1$areaconst, vivienda1$preciom),4)
## [1] 0.7419

A simple vista no se observa una correlación del precio de las viviendas frente al número de baños, parqueaderos y habitaciones, con coeficientes de correlación de \(0.555\), \(0.4616\) y \(0.421\), respectivamente

plot3 <- ggplot(vivienda1, aes(x = banios, y = preciom)) +
  geom_point(aes(color = estrato)) +
  labs(x = "# baños",
       y = "Precio (millones)") +
  theme_minimal()

ggplotly(plot3)
round(cor(vivienda1$banios, vivienda1$preciom),4)
## [1] 0.555
plot4 <- ggplot(vivienda1, aes(x = parqueaderos, y = preciom)) +
  geom_point(aes(color = estrato)) +
  labs(x = "# parqueaderos",
       y = "Precio (millones)") +
  theme_minimal()

ggplotly(plot4)
round(cor(vivienda1$parqueaderos, vivienda1$preciom),4)
## [1] 0.4616
plot2 <- ggplot(vivienda1, aes(x = habitaciones, y = preciom)) +
  geom_point(aes(color = estrato)) +
  labs(x = "# habitaciones",
       y = "Precio (millones)") +
  theme_minimal()

ggplotly(plot2)
round(cor(vivienda1$habitaciones, vivienda1$preciom),4)
## [1] 0.421

4.3. Estimación de un modelo de regresión lineal múltiple.

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).

Se estima un modelo de regresión lineal múltiple para casas de zona norte, teniendo en cuenta que la variable “estrato” es ordinal.

ModeloRLM = lm(data=vivienda1, preciom~areaconst+habitaciones+banios+parqueaderos+estrato) 
summary(ModeloRLM)
## 
## Call:
## lm(formula = preciom ~ areaconst + habitaciones + banios + parqueaderos + 
##     estrato, data = vivienda1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -886.52  -63.40  -13.09   34.15 1105.27 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   33.37412   20.28759   1.645  0.10057    
## areaconst      0.74076    0.05195  14.258  < 2e-16 ***
## habitaciones   7.91285    5.13864   1.540  0.12421    
## banios        15.66939    6.49960   2.411  0.01627 *  
## parqueaderos  14.64259    4.68507   3.125  0.00188 ** 
## estrato4      85.73019   19.27868   4.447 1.07e-05 ***
## estrato5     126.34566   18.75614   6.736 4.37e-11 ***
## estrato6     267.78089   34.63721   7.731 5.66e-14 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 144.2 on 514 degrees of freedom
## Multiple R-squared:  0.6571, Adjusted R-squared:  0.6524 
## F-statistic: 140.7 on 7 and 514 DF,  p-value: < 2.2e-16
#COEFICIENTES
coef(ModeloRLM)
##  (Intercept)    areaconst habitaciones       banios parqueaderos     estrato4 
##   33.3741159    0.7407591    7.9128491   15.6693901   14.6425928   85.7301878 
##     estrato5     estrato6 
##  126.3456615  267.7808927
#R2
print(summary(ModeloRLM)$r.squared)
## [1] 0.6571137

Al analizar el modelo para estimar los precios de las casas de la zona norte de Cali, se observa que el coeficiente de determinación, \(R^2\), es igual a \(0.6524\), es decir que, aproximadamente el \(65.24%\) de las variaciones de dichos precios pueden explicarse utilizando las variables incluidas en el modelo.

Las variables área construida, el estrato, el número de baños y parqueaderos del modelo son estadísticamente significativas, es decir que tienen un impacto importante y medible en el precio de las casas de la zona norte de Cali.

El modelo resultante es: \[ Preciom = 33.37 + 0.74 * (areaconst) + 7.91 * (habitaciones) + 15.67 * (banios) + 14.64 * (parqueaderos) + 85.73 * (estrato4) + 126.35 * (estrato5) + 267.78 * (estrato6) \] La ecuación del modelo muestra cómo impactan las variables en los precios de las viviendas, por ejemplo, un aumento de una unidad en el área construida se relaciona con un aumento de aproximadamente \(0.74\) unidades en el precio.

4.4. Validación de supuestos del modelo.

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).

Se realiza análisis gráfico para realizar la validación de los supuestos del modelo, con el proposito de evaluar la idoneidad del mismo. A continuación se tienen los gráficos utilizados habitualmente.

par(mfrow = c(2, 2))
plot(ModeloRLM)

Procediendo con su interpretación:

Supuesto Análisis Cumplimiento
Normalidad En el Gráfico Q - Q Residuals se aprecia que los puntos no siguen una tendencia lineal con respecto a la diagonal que representa la concordancia entre los residuales estandarizados y los cuantiles teóricos, lo que evidencia que no sigue una distribución normal. No
Homocedasticidad En el Gráfico Residuals Vs. Fitted, se evidencia que los residuales se alejan de cero a medida que se incrementan los valores ajustados, es decir que no se tiene una dispersión constante de los residuales, concluyendo que el modelo tiene heterocedasticidad. No
Linealidad En el Gráfico Residuals Vs. Fitted, se observa que los residuos no se distribuyen alrededor de la línea horizontal en cero, evidenciando que la relación entre las variables no es estrictamente lineal. No
Outliers En la Gráfica Residuals Vs. Leverage se observa que los residuos estandarizados se encuentran cerca a \(0\) para valores de levarage pequeños lo que puede indica que las observaciones están ajustadas correctamente por el modelo, sin embargo hay algunos valore atípicos representados por valores de leverage alto. No

Para sustentar los análisis previos dados a partir de las gráficas, se realizan las pruebas correspondientes a los supuestos de normalidad, homocedasticidad y no autocorrelación. De acuerdo con los \(p-value\) obtenidos se tiene que son cercanos a cero, es decir que se rechazan las hipótesis nulas de cada supuesto.

Normalidad <- shapiro.test(ModeloRLM$residuals)
homocedasticidad <- lmtest::bptest(ModeloRLM)
autocorrelacion <- lmtest::dwtest(ModeloRLM)

resultados <- rbind(
  c("Normalidad", Normalidad$method, format(Normalidad$p.value, 
                                            scientific = TRUE)),
  c("Homocedasticidad", homocedasticidad$method, format(homocedasticidad$p.value, 
                                                        scientific = TRUE)),
  c("No Autocorrelación", autocorrelacion$method, format(autocorrelacion$p.value, 
                                                      scientific = TRUE)))
colnames(resultados) <- c("Prueba", "Método", "Valor p")
kable(resultados)
Prueba Método Valor p
Normalidad Shapiro-Wilk normality test 5.493929e-26
Homocedasticidad studentized Breusch-Pagan test 1.372001e-19
No Autocorrelación Durbin-Watson test 2.166482e-02

4.5. Predicción de precios.

5. Con el modelo identificado debe predecir el precio de la vivienda con las características de la primera solicitud.

Se definen los datos de predicción de la vivienda 1, encontrando que el precio de la vivienda de estrato 4 es de \(\$344.89\) millones de pesos, y para estrato 5 es de \(\$385.50\).

Vivienda_1 = data.frame( areaconst=c(200,200),
                         habitaciones=c(4,4),
                         banios=c(2,2),
                         parqueaderos=c(1,1), 
                         estrato=c("4","5")
)

knitr::kable(Vivienda_1)
areaconst habitaciones banios parqueaderos estrato
200 4 2 1 4
200 4 2 1 5
predict(ModeloRLM, newdata = Vivienda_1)
##        1        2 
## 344.8889 385.5044

4.6. Propuesta de ofertas potenciales.

6. Con las predicciones del modelo sugiera potenciales ofertas que responda a la solicitud de la vivienda 1. Tenga encuentra que la empresa tiene crédito pre-aprobado de máximo 350 millones de pesos. Realice un análisis y presente en un mapa al menos 5 ofertas potenciales que debe discutir.

Teniendo en cuenta que se tiene un crédito pre-aprobado de máximo \(\$350\) millones de pesos, y se requiere una casa en la zona norte en estrato 4 o 5, con un área contruida de mínimo 200 metros cuadrados, un parqueadero, 2 baños y 4 habitaciones.

parametros_vivienda_1 <- which((vivienda1$estrato=="4" | vivienda1$estrato=="5") & vivienda1$areaconst>=200 & vivienda1$parqueaderos>=1 & vivienda1$banios>=2 & vivienda1$habitaciones>=4 & vivienda1$preciom<=350)

Se filtran las viviendas ofertadas que cumplen con los parámetros.

oferta <- vivienda1[parametros_vivienda_1,]

Se seleccionan 5 Ofertas que cumple las caracteristicas, ordenadas por área construida de mayor a menor.

oferta_5 = oferta[order(oferta$areaconst, decreasing = TRUE), ]

knitr::kable(head(oferta_5, 5))
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
326 3101 Zona Norte 02 5 340 355 2 5 8 CASA SAN VICENTE -76.52377 3.46384
503 1943 Zona Norte 02 5 350 346 1 2 4 CASA VIPASA -76.51847 3.47503
75 4209 Zona Norte 02 5 350 300 3 5 6 CASA EL BOSQUE -76.53010 3.48577
500 1822 Zona Norte 02 4 340 295 2 2 4 CASA VIPASA -76.51777 3.48060
203 937 Zona Norte 02 4 350 280 2 3 4 CASA LA MERCED -76.50603 3.46643

Se crea el mapa con las viviendas seleccionadas según la base “vivienda1”.

# install.packages("leaflet")
library(leaflet)

oferta_5 <- head(oferta_5, 5)

oferta_5.coord <- data.frame(
  lat = c(oferta_5$latitud),
  long = c(oferta_5$longitud)
)

# Crea un mapa
map_oferta <- leaflet(oferta_5.coord) %>%
  addTiles() %>%
  addMarkers(
    lng = ~long,
    lat = ~lat,
    layerId = 1,
    popup = ~as.character(lat)
  ) %>%
  addRectangles(
    lng1=-76.5403, lat1=3.4556,
    lng2=max(oferta_5$longitud), lat2=max(oferta_5$latitud),
    fillColor = "transparent",color="red"
  ) 

# Muestra el mapa
map_oferta