Importación y Carga de Datos

# install.packages(devtools)
# devtools::install_github("dgonxalex80/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
## Loading required package: boot
## Loading required package: broom
## 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
# Carga los datos
data(vivienda)
head(vivienda)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1147 Zona O… <NA>        3     250        70            1      3            6
## 2  1169 Zona O… <NA>        3     320       120            1      2            3
## 3  1350 Zona O… <NA>        3     350       220            2      2            4
## 4  5992 Zona S… 02          4     400       280            3      5            3
## 5  1212 Zona N… 01          5     260        90            1      2            3
## 6  1724 Zona N… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Pasos requeridos para la obtención de los resultados

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

Análisis Exploratorio

El resumen de la base de datos obtenido es el siguiente:

summary(vivienda)
##        id           zona               piso              estrato     
##  Min.   :   1   Length:8322        Length:8322        Min.   :3.000  
##  1st Qu.:2080   Class :character   Class :character   1st Qu.:4.000  
##  Median :4160   Mode  :character   Mode  :character   Median :5.000  
##  Mean   :4160                                         Mean   :4.634  
##  3rd Qu.:6240                                         3rd Qu.:5.000  
##  Max.   :8319                                         Max.   :6.000  
##  NA's   :3                                            NA's   :3      
##     preciom         areaconst       parqueaderos        banios      
##  Min.   :  58.0   Min.   :  30.0   Min.   : 1.000   Min.   : 0.000  
##  1st Qu.: 220.0   1st Qu.:  80.0   1st Qu.: 1.000   1st Qu.: 2.000  
##  Median : 330.0   Median : 123.0   Median : 2.000   Median : 3.000  
##  Mean   : 433.9   Mean   : 174.9   Mean   : 1.835   Mean   : 3.111  
##  3rd Qu.: 540.0   3rd Qu.: 229.0   3rd Qu.: 2.000   3rd Qu.: 4.000  
##  Max.   :1999.0   Max.   :1745.0   Max.   :10.000   Max.   :10.000  
##  NA's   :2        NA's   :3        NA's   :1605     NA's   :3       
##   habitaciones        tipo              barrio             longitud     
##  Min.   : 0.000   Length:8322        Length:8322        Min.   :-76.59  
##  1st Qu.: 3.000   Class :character   Class :character   1st Qu.:-76.54  
##  Median : 3.000   Mode  :character   Mode  :character   Median :-76.53  
##  Mean   : 3.605                                         Mean   :-76.53  
##  3rd Qu.: 4.000                                         3rd Qu.:-76.52  
##  Max.   :10.000                                         Max.   :-76.46  
##  NA's   :3                                              NA's   :3       
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.381  
##  Median :3.416  
##  Mean   :3.418  
##  3rd Qu.:3.452  
##  Max.   :3.498  
##  NA's   :3

Procederemos a eliminar los registros donde este campo es nulo ya que posiblemente se traten de error en los datos. Las viviendas estudiadas abarcan una variedad de tipos, desde casas hasta apartamentos, con un rango de estratos entre 3 y 6. Por otra parte convertiremos los valores de zona t typo a minuscula para evitar omitir registros al momento de aplicar filtros.

data <- vivienda
data <- vivienda
data[c("zona", "tipo")] <- lapply(data[c("zona", "tipo")], tolower)
data <- data[!is.na(data$id),]
head(data)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1147 zona o… <NA>        3     250        70            1      3            6
## 2  1169 zona o… <NA>        3     320       120            1      2            3
## 3  1350 zona o… <NA>        3     350       220            2      2            4
## 4  5992 zona s… 02          4     400       280            3      5            3
## 5  1212 zona n… 01          5     260        90            1      2            3
## 6  1724 zona n… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Realizando un análisis del comportamiento de datos perdidos, observamos lo siguiente:

#install.packages("naniar")
require(naniar)
## Loading required package: naniar
## Warning: package 'naniar' was built under R version 4.3.3
vis_miss(data)

Imputación de Datos

Este proceso implica estimar los valores faltantes en un conjunto de datos utilizando información disponible en los datos observados.

Del gráfico anterior, podemos observar que el porcentaje de datos faltantes en “piso” es del 32% y en “parqueaderos” es del 19%.

summary(data$parqueaderos)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   1.000   1.000   2.000   1.835   2.000  10.000    1602

Dado que la mayoría de los valores se encuentran en un rango relativamente estrecho entre 1 y 2, con una mediana de 2, una opción razonable podría ser imputar el valor medio (mean) a los valores faltantes, que es aproximadamente 2. Sin embargo, basándonos en hechos prácticos, lo mejor en este caso es suponer que los valores faltantes corresponden a casas sin parqueaderos. Por lo tanto, en este caso, reemplazaremos los valores nulos por 0.

data$parqueaderos[is.na(data$parqueaderos)]<-0

Ahora, vamos a convertir la variable “piso”, actualmente representada como caracteres, a números. Posteriormente, analizaremos su distribución estadística para comprender mejor su comportamiento.

data$piso <- as.numeric(as.character(data$piso))
summary(data$piso)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   1.000   2.000   3.000   3.771   5.000  12.000    2635

La mediana es menos sensible a valores atípicos que la media, lo que la hace una opción más robusta para imputar en este caso, por lo tanto los 2635 valores faltantes los reemplazaremos por 3.

data$piso[is.na(data$piso)]<-2

Ahora realizaremos una validación nuevamente de los datos faltantes.

#install.packages("mice")
library(mice)
## Warning: package 'mice' was built under R version 4.3.3
## 
## Attaching package: 'mice'
## The following object is masked from 'package:stats':
## 
##     filter
## The following objects are masked from 'package:base':
## 
##     cbind, rbind
grafico <- md.pattern(data, rotate.names = TRUE)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

En base a lo enunciado en el primer punto debemos filtrar la data por aquellas inmuebles del tipo casas y que se encuentren ubicadas en el norte, y pot otra parte vamos a aprovechar para retirar el campo id al se una columna unicamente informativa.

viviendas_estudio <- data[data$tipo == "casa" & data$zona == "zona norte", ]
head(viviendas_estudio, 3)
## # A tibble: 3 × 13
##      id zona     piso estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1209 zona n…     2       5     320       150            2      4            6
## 2  1592 zona n…     2       5     780       380            2      3            3
## 3  4057 zona n…     2       6     750       445            0      7            6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

A continuación , haremos un grafico de nuestros datos de estudio. Para ello realizaremos un casteo de los campos de latitud y longitud para hacer el mapa.

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

library("leaflet")
## Warning: package 'leaflet' was built under R version 4.3.3
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
viviendas_estudio$longitud <- as.numeric(viviendas_estudio$longitud)
viviendas_estudio$latitud <- as.numeric(viviendas_estudio$latitud)

mapa <- leaflet() %>%
  addProviderTiles("CartoDB.Positron")

mapa <- mapa %>%
  addCircleMarkers(data = viviendas_estudio,
                   lng = ~longitud,
                   lat = ~latitud,
                   radius = 3,  # Tamaño de los círculos
                   color = "green",  # Color de los puntos
                   popup = ~paste("ID:", id))

mapa

Del grafico anterior podemos observar que a partir de que realizamos un flitro por la zona norte, la distribución de los puntos esta esparcida por toda la ciudad, de esto podemos entender que es necesario una transformación o limpieza de los datos que nos permita tener información mas confiable.

  1. 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.
#Realizamos la instalación de la libreria plotly
#install.packages("plotly")
library(plotly)
## Warning: package 'plotly' was built under R version 4.3.3
## 
## 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
#Realizamos la instalación de la libreria plotly
#install.packages("plotly")
library(plotly)
library(ggplot2)

data_corr_precios <- data[, c("preciom", "areaconst", "estrato", "banios", "habitaciones", "zona")]

data_corr_precios$zona <- as.factor(data_corr_precios$zona)

plot_base <- ggplot(data_corr_precios, aes(x = preciom, y = areaconst, colour = factor(estrato))) +
  geom_point(size = 0.5) +
  facet_grid(~zona)

plot_interactivo <- ggplotly(plot_base)

plot_interactivo

Modelo de Regresión Lineal Múltiple

  1. 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).
# Realizamos la regresión multiple del modelo con los atributos solicitados
modelo_lm <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = data)

summary(modelo_lm)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1596.26   -89.52   -18.63    54.31  1192.21 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -318.31275   11.68459  -27.24   <2e-16 ***
## areaconst       0.96050    0.01875   51.23   <2e-16 ***
## estrato        92.22507    2.43661   37.85   <2e-16 ***
## habitaciones  -25.72893    1.86899  -13.77   <2e-16 ***
## parqueaderos   48.32521    2.01829   23.94   <2e-16 ***
## banios         57.21454    2.23875   25.56   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 175.1 on 8313 degrees of freedom
## Multiple R-squared:  0.7164, Adjusted R-squared:  0.7163 
## F-statistic:  4200 on 5 and 8313 DF,  p-value: < 2.2e-16

Ahora, graficaremos nuestro modelo:

# Graficar los valores ajustados versus los valores observados
plot(data$preciom, fitted(modelo_lm), 
     xlab = "Preciom observado", ylab = "Preciom ajustado",
     main = "Valores ajustados vs observados")

# Agregar una línea de referencia
abline(0, 1, col = "red")

Tanto del gráfico como de los valores obtenidos en el resumen del modelo, se observa una amplia dispersión en los residuos, con un mínimo de -1596.26 y un máximo de 1192.21. Esta dispersión puede ser atribuida a la variabilidad inherente en los datos, como se ilustra en el gráfico, donde los puntos muestran una distribución dispersa. Esta variabilidad desafía la capacidad de nuestro modelo para predecir con precisión todos los posibles valores presentes en los datos.

Ahora, centrémonos en un análisis específico considerando solo el caso de Base 1. Para llevar a cabo este análisis, replicaremos el modelo para obtener:

# Realizamos la regresión multiple del modelo con los atributos solicitados 
# para el caso de Base1
modelo_lm_base1 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = viviendas_estudio)

summary(modelo_lm_base1)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = viviendas_estudio)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -964.04  -80.10  -17.08   50.06 1069.45 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -236.47551   30.36582  -7.788 2.40e-14 ***
## areaconst       0.82677    0.04368  18.926  < 2e-16 ***
## estrato        86.42579    7.39747  11.683  < 2e-16 ***
## habitaciones    1.44443    4.16411   0.347    0.729    
## parqueaderos   -1.67672    4.31505  -0.389    0.698    
## banios         26.97978    5.34384   5.049 5.65e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 159.1 on 716 degrees of freedom
## Multiple R-squared:  0.6508, Adjusted R-squared:  0.6484 
## F-statistic: 266.9 on 5 and 716 DF,  p-value: < 2.2e-16
# Graficar los valores ajustados versus los valores observados
plot(viviendas_estudio$preciom, fitted(modelo_lm_base1), 
     xlab = "Preciom observado base1", ylab = "Preciom ajustado base1",
     main = "Valores ajustados vs observados")

# Agregar una línea de referencia
abline(0, 1, col = "red")

Basándonos en nuestro análisis del modelo de regresión múltiple de la base 1, observamos que, al igual que el modelo obtenido con todos los datos, también muestra una gran variabilidad en los residuos. Esto sugiere que estos modelos no son totalmente confiables. Sin embargo, al comparar los coeficientes de área construida entre los datos generales y los casos específicos de la base 1, notamos un aumento en la magnitud para el primer caso (0.96) en comparación con las casas de la zona norte (0.82). Esto indica que la variabilidad de los precios con respecto al área construida es menor en los datos de todas las zonas. Es interesante observar que el coeficiente para el número de habitaciones es negativo en los datos generales, lo que sugiere que el precio disminuye con un mayor número de habitaciones, mientras que para las casas del tipo B1 tiende a aumentar, como lo refleja el coeficiente de 1.44. Además, hay una diferencia significativa en la relación entre el precio y el número de parqueaderos. Mientras que para los datos generales el coeficiente es de 48.32, para nuestro caso de estudio es de -1.676.

La comparación de estadísticas de ajuste revela diferencias significativas entre los dos casos analizados. En primer lugar, modelo de nuestro casoB1 exhibe un error estándar residual más bajo (159.1) en contraste con el modelo generado por la data en general (175.1), sugiriendo una mayor capacidad de este modelo en explicar la variabilidad en los datos. Sin embargo, primer modelo muestra un R cuadrado múltiple más elevado (0.7164) en comparación con el caso de estudio (0.6508), indicando que el modelo d una e la data en general proporcióna una superior variabilidad en la variable de respuesta. Realizando una mejor segmentacion de los datos ambos modelos podrian mejorar considerablemente su performance.

Validación de Supuestos

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

Los supuestos a verificar son los siguientes:

  1. Los errores son variables aleatorias normales, es decir, siguen una distribución normal: \(e \sim N(0, \sigma^2)\).
  2. Los errores tienen una media de cero: \(E[e] = 0\).
  3. Los errores tienen una varianza constante: \(V[e] = \sigma^2\).
  4. Los errores son mutuamente independientes: \(E[e_i, e_j] = 0\).

Normalidad de los Errores

# Prueba de Shapiro-Wilk para la normalidad de los residuos
shapiro.test(resid(modelo_lm_base1))
## 
##  Shapiro-Wilk normality test
## 
## data:  resid(modelo_lm_base1)
## W = 0.83823, p-value < 2.2e-16
# Histograma de los residuos
hist(resid(modelo_lm_base1), main="Histograma de Residuos")

El valor de W se encuentra en el rango de 0 a 1, donde un valor más cercano a 1 indica una mejor aproximación a la normalidad de los datos. En este caso, el valor de W=0.83823 sugiere que los datos no se ajustan perfectamente a una distribución normal.

El valor p es la probabilidad de observar los datos si la hipótesis nula de normalidad es verdadera. Dado que el valor p es menor que cualquier nivel de significancia común (como 0.05), se rechaza la hipótesis nula de normalidad. Esto indica que hay evidencia estadística significativa para concluir que los residuos no siguen una distribución normal.

Media cero de los errores:

# Media de los residuos
mean(resid(modelo_lm_base1))
## [1] 5.435811e-15

Este resultado es esencialmente cero en términos prácticos. Esto indica que la media de los residuos es extremadamente pequeña y prácticamente indistinguible de cero. Por lo tanto, podemos concluir que el segundo supuesto, que establece que los errores tienen una media de cero (E[e] = 0), se cumple para el modelo.

Varianza constante de los Errores

# Gráfico de dispersión de residuos
plot(fitted(modelo_lm_base1), resid(modelo_lm_base1), 
     xlab="Valores ajustados", ylab="Residuos",
     main="Gráfico de dispersión de Residuos")

Del grafico, podemos concluir que no se cumple el supuesto de que los errores tienen varianza constante.

Independencia de los Errores

# Prueba de Durbin-Watson
resultado <- car::durbinWatsonTest(modelo_lm_base1)
resultado
##  lag Autocorrelation D-W Statistic p-value
##    1       0.1831348      1.633018       0
##  Alternative hypothesis: rho != 0

El estadístico D-W se sitúa cerca de 2 (1.633018), indicando una baja autocorrelación positiva entre los residuos del modelo. Esta proximidad a 2 sugiere una ausencia de autocorrelación serial significativa en los residuos. Sin embargo, el valor p obtenido es 0, lo que arroja una sólida evidencia en contra de la hipótesis nula de ausencia de autocorrelación. Por ende, se concluye que existe autocorrelación significativa en los residuos del modelo. Dado que el valor p es menor que cualquier nivel de significancia común, se puede rechazar la hipótesis nula con certeza y afirmar la presencia de autocorrelación significativa en los residuos del modelo.

Predicción Precio Vivienda Caso 1

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

Inicialmente, creamos un marco de datos con los valores de las caracteristicas deseadas para la predicción.

nuevo_apto_base1 <- data.frame(
  areaconst = c(200, 200),
  parqueaderos = c(1,1),
  banios = c(2,2),
  habitaciones = c(4,4),
  estrato = c(4, 5)
)

prediccion_apto_base1 <- predict(modelo_lm_base1, nuevo_apto_base1)
nuevo_apto_base1$prediccion_precio <- prediccion_apto_base1

En base a este dataframe anterior, realizamos la predicción del precio del apartamento:

print(nuevo_apto_base1)
##   areaconst parqueaderos banios habitaciones estrato prediccion_precio
## 1       200            1      2            4       4          332.6430
## 2       200            1      2            4       5          419.0688

De esta forma, podemos observar que el rango del precio de la vivienda se encuentra entre 332 y 419 millones.

Predicción Opciones de Vivienda

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

Dado que el área construida, la cantidad de parqueaderos y el número de baños son atributos que añaden mayor valor a una propiedad, hemos establecido nuestras opciones de búsqueda considerando que las propiedades cumplan con estos requisitos mínimos.

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

casas_cumplen_base1 <- viviendas_estudio[pos, ]

casas_cumplen_base1 = casas_cumplen_base1[order(casas_cumplen_base1$preciom, decreasing = TRUE), ]

casas_cumplen_base1_5 <- head(casas_cumplen_base1, 5)
casas_cumplen_base1_5
## # A tibble: 5 × 13
##      id zona     piso estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  4210 zona n…     1       5     350       200            3      3            4
## 2   819 zona n…     2       5     350       264            2      3            4
## 3   937 zona n…     2       4     350       280            2      3            4
## 4  1163 zona n…     2       5     350       216            2      2            4
## 5  1842 zona n…     2       5     350       240            2      3            4
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
casas_cumplen_base1_5$longitud <- as.numeric(casas_cumplen_base1_5$longitud)
casas_cumplen_base1_5$latitud <- as.numeric(casas_cumplen_base1_5$latitud)

mapa <- leaflet() %>%
  addProviderTiles("CartoDB.Positron")

mapa_casas_cumplen_base1_5 <- mapa %>%
  addCircleMarkers(data = casas_cumplen_base1_5,
                   lng = ~longitud,
                   lat = ~latitud,
                   radius = 10,  # Tamaño de los círculos
                   color = "green",  # Color de los puntos
                   popup = ~paste("ID:", id))

mapa_casas_cumplen_base1_5

De esta forma podemos ver su ubicación en el mapa.

Segundo Caso de Estudio

  1. Realice los pasos del 1 al 6. Para la segunda solicitud que tiene un crédito pre-aprobado por valor de $850 millones.

De igual forma realizaremos la segmentación de la data a partir de la base de datos general a la cual ya se le ha realizado la imputación de datos.

viviendas_estudio_caso2 <- data[data$tipo == "apartamento" & data$zona == "zona sur", ]
head(viviendas_estudio_caso2, 3)
## # A tibble: 3 × 13
##      id zona     piso estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  5098 zona s…     5       4     290        96            1      2            3
## 2   698 zona s…     2       3      78        40            1      1            2
## 3  8199 zona s…     2       6     875       194            2      5            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

A continuación , haremos un grafico de nuestros datos de estudio. Para ello realizaremos un casteo de los campos de latitud y longitud para hacer el mapa.

viviendas_estudio_caso2$longitud <- as.numeric(viviendas_estudio_caso2$longitud)
viviendas_estudio_caso2$latitud <- as.numeric(viviendas_estudio_caso2$latitud)

mapa <- leaflet() %>%
  addProviderTiles("CartoDB.Positron")

mapa_viviendas_estudio_caso2 <- mapa %>%
  addCircleMarkers(data = viviendas_estudio_caso2,
                   lng = ~longitud,
                   lat = ~latitud,
                   radius = 3,
                   color = "green",
                   popup = ~paste("ID:", id))

mapa_viviendas_estudio_caso2

De igual forma que para la zona norte se ven datos distribuidos en toda la ciudad, aunque tambien se logra apreciar donde se encuentra la mayor concentración de datos.

Correlación de los Datos Caso 2

data_corr_precios_caso2 <- viviendas_estudio_caso2[, c("preciom", "areaconst", "estrato", "banios", "habitaciones", "zona")]

data_corr_precios_caso2$zona <- as.factor(data_corr_precios_caso2$zona)

plot_base_caso2 <- ggplot(data_corr_precios_caso2, aes(x = preciom, y = areaconst, colour = factor(estrato))) +
  geom_point(size = 0.5) +
  facet_grid(~zona)

plot_interactivo_caso2 <- ggplotly(plot_base_caso2)

plot_interactivo_caso2

De este grafico, podemos observar que la mayor cantidad de apartamentos para la zona 2 se encuentra para los estratos 3,4 y 5.

Modelo de Regresión Lineal Múltiple Caso 2

# Realizamos la regresión multiple del modelo con los atributos solicitados
modelo_lm_caso2 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = viviendas_estudio_caso2)

summary(modelo_lm_caso2)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = viviendas_estudio_caso2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1252.31   -42.15    -2.06    36.32   934.06 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -221.04614   13.47771 -16.401  < 2e-16 ***
## areaconst       1.46061    0.04876  29.956  < 2e-16 ***
## estrato        57.00608    2.79648  20.385  < 2e-16 ***
## habitaciones  -22.71789    3.39549  -6.691 2.68e-11 ***
## parqueaderos   48.36353    3.02343  15.996  < 2e-16 ***
## banios         48.60871    3.04050  15.987  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 95.17 on 2781 degrees of freedom
## Multiple R-squared:  0.7536, Adjusted R-squared:  0.7531 
## F-statistic:  1701 on 5 and 2781 DF,  p-value: < 2.2e-16

Predicción Opciones de Vivienda

nuevo_apto_base2 <- data.frame(
  areaconst = c(300, 300),
  parqueaderos = c(3,3),
  banios = c(3,3),
  habitaciones = c(5,5),
  estrato = c(5, 6)
)

prediccion_apto_base2 <- predict(modelo_lm_caso2, nuevo_apto_base2)
nuevo_apto_base2$prediccion_precio <- prediccion_apto_base2

En base a este dataframe anterior, realizamos la predicción del precio del apartamento:

print(nuevo_apto_base2)
##   areaconst parqueaderos banios habitaciones estrato prediccion_precio
## 1       300            3      3            5       5          679.4951
## 2       300            3      3            5       6          736.5012

En este caso observamos que el rango se encuentra entre 679 y 736 millones, lo cual es menor al monto del crédito preaprobado por 850 millones.

De igual forma que para el caso anterior variabilizamos nuestro rango de busqueda para area construida, parqueadro y baños. Añadiendo mas de 5 habitaciones al contar con pocos casos.

pos_case2 <- which(viviendas_estudio_caso2$areaconst >= 300 &
             viviendas_estudio_caso2$parqueaderos >= 3 & 
             viviendas_estudio_caso2$banios >= 3 & 
             viviendas_estudio_caso2$habitaciones >= 5 & 
             (viviendas_estudio_caso2$estrato == 5 | viviendas_estudio_caso2$estrato == 6) & 
             viviendas_estudio_caso2$preciom <= 850)

casas_cumplen_caso2 <- viviendas_estudio_caso2[pos_case2, ]

casas_cumplen_caso2 = casas_cumplen_caso2[order(casas_cumplen_caso2$preciom, decreasing = TRUE), ]

casas_cumplen_caso2 <- head(casas_cumplen_caso2, 5)
casas_cumplen_caso2
## # A tibble: 2 × 13
##      id zona     piso estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  7182 zona s…     2       5     730       573            3      8            5
## 2  7512 zona s…     2       5     670       300            3      5            6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Realizamos de igual forma el grafico.

casas_cumplen_caso2$longitud <- as.numeric(casas_cumplen_caso2$longitud)
casas_cumplen_caso2$latitud <- as.numeric(casas_cumplen_caso2$latitud)

mapa <- leaflet() %>%
  addProviderTiles("CartoDB.Positron")

mapa_casas_cumplen_caso2 <- mapa %>%
  addCircleMarkers(data = casas_cumplen_caso2,
                   lng = ~longitud,
                   lat = ~latitud,
                   radius = 10,  # Tamaño de los círculos
                   color = "green",  # Color de los puntos
                   popup = ~paste("ID:", id))

mapa_casas_cumplen_caso2