Lo primero que se realizara es instalar las librerias y paquetes necesarios para el ejercicio:

Caso de Negocio

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

Importar los datos

#install.packages("devtools") # solo la primera vez
#devtools::install_github("dgonxalex80/paqueteMODELOS", force =TRUE)
library(paqueteMODELOS)
## Loading required package: boot
## 
## Attaching package: 'boot'
## The following object is masked from 'package:psych':
## 
##     logit
## The following object is masked from 'package:car':
## 
##     logit
## Loading required package: broom
library(dplyr)
data(vivienda)
datavivienda <- vivienda

Limpieza de datos

Ahora realizaremos la validación de datos faltantes:

# Calcula el número de datos faltantes por variable
datos_faltantes <- datavivienda %>% summarise_all(~sum(is.na(.)))
kable(datos_faltantes, format = "markdown")
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
3 3 2638 3 2 3 1605 3 3 3 3 3 3

Como podemos visualizar hay 3 registros donde el valor para todos atributos o variables es nulo, de entrada lo ideal es eliminar estos 3 registros

# Filtra los registros donde id no es nulo de esta forma ya tendriamos el data set sin los 3 registros nulos
datavivienda <- datavivienda %>%
  filter(!is.na(id))

Teniendo en cuenta algunos problemas de calidad que tiene el atributo barrio, procederemos a realizar algunos ajustes de calidad.

# Pasar todos los caracteres a minuscula
datavivienda$barrio = tolower(datavivienda$barrio)

# Quitar las tildes:
#viviendasF$barrio = iconv(viviendasF$barrio, to = "ASCII//TRANSLIT")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"á", "a")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"é", "e")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"í", "i")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"ó", "o")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"ú", "u")

# Quitar caracteres especiales
#viviendasF$barrio = str_replace_all(viviendasF$barrio,"[^[0-9a-zA-Z ]]", "")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"é", "e")
datavivienda$barrio = str_replace_all(datavivienda$barrio,"√∫", "u")

# Corregir otros problemas de calidad
datavivienda$barrio = ifelse(datavivienda$barrio == "agua blanca","aguablanca",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "alfonso lopez i","alfonso lopez",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "calibella","cali bella",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ciudadela paso ancho","ciudadela pasoancho",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ingenio i","el ingenio i",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ingenio ii","el ingenio ii",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "la rivera i","la rivera",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "las vegas de","las vegas",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "pampa linda","pampalinda",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "ponce","pance",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "tequendema","tequendama",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "valle de lili","valle del lili",datavivienda$barrio)
datavivienda$barrio = ifelse(datavivienda$barrio == "zona norte los","zona norte",datavivienda$barrio)
tipoapto <- unique(datavivienda$tipo)
print(tipoapto)
## [1] "Casa"        "Apartamento"

Imputar la variable parqueadero:

Esto se relizara mediante un modelo de regresión lineal y de esta forma poder poblar al 100% la variale parqueadero.

library(tidyverse)

# Separa las observaciones con valores completos y los faltantes en `parqueaderos`
data_completa <- datavivienda %>% filter(!is.na(parqueaderos))
data_faltantes <- datavivienda %>% filter(is.na(parqueaderos))

# Ajusta un modelo de regresión lineal usando las observaciones completas
modelo <- lm(parqueaderos ~ estrato + preciom + areaconst + banios + habitaciones + tipo , data = data_completa)

# Predice los valores faltantes usando el modelo ajustado
data_faltantes$parqueaderos <- predict(modelo, newdata = data_faltantes)

# Combina las predicciones con el dataframe original
viviendas_imputadas <- datavivienda %>%
  mutate(parqueaderos = ifelse(is.na(parqueaderos), predict(modelo, newdata = .), parqueaderos))

viviendas_imputadas$parqueaderos <- trunc(viviendas_imputadas$parqueaderos)

# Verifica los cambios
summary(viviendas_imputadas)
##        id           zona               piso              estrato     
##  Min.   :   1   Length:8319        Length:8319        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  
##     preciom         areaconst       parqueaderos        banios      
##  Min.   :  58.0   Min.   :  30.0   Min.   : 0.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 : 1.000   Median : 3.000  
##  Mean   : 433.9   Mean   : 174.9   Mean   : 1.636   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  
##   habitaciones        tipo              barrio             longitud     
##  Min.   : 0.000   Length:8319        Length:8319        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  
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.381  
##  Median :3.416  
##  Mean   :3.418  
##  3rd Qu.:3.452  
##  Max.   :3.498

Despues de la imputación y procesos de calidad de los datos confirmamos como quedo nuestra base de datos:

# Calcula el número de datos faltantes por variable
datos_faltantes <- viviendas_imputadas %>% summarise_all(~sum(is.na(.)))
kable(datos_faltantes, format = "markdown")
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
0 0 2635 0 0 0 0 0 0 0 0 0 0
datavivienda <- viviendas_imputadas

Se crea una variable nueva para tener las zonas en tipo categorica

datavivienda$zona_numeric <- as.numeric(factor(datavivienda$zona, 
                                     levels = c("Zona Norte", "Zona Sur", "Zona Oriente", "Zona Oeste","Zona Centro"),
                                     labels = c(1, 2, 3, 4,5)))

BASE 1 VIVIENDAS TIPO CASA EN EL NORTE

Realice un filtro a la base de datos e incluya sólo 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?).

Para poder ejecutar este punto , es necesario primero filtrar la zona y el tipo y estandarizar los datos de longitud y latitud, en este caso toca dividir el valor puesto entre 1000.

Inicialmente realizamos el filtro de las viviendas tipo Casa de la zona Norte de la ciudad de Cali

base1 <- datavivienda %>%
  filter(tipo=="Casa",zona=="Zona Norte")
dim(base1)
## [1] 722  14
head(base1,3)
## # A tibble: 3 × 14
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1209 Zona N… 02          5     320       150            2      4            6
## 2  1592 Zona N… 02          5     780       380            2      3            3
## 3  4057 Zona N… 02          6     750       445            3      7            6
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   zona_numeric <dbl>

Y aqui comoo podemos evidenciar el proceso fue efectivo y ya contamos con la base 1 lista para trabajar.

Ahora procederemos a realizar el mapa con la base 1 filtrado.

Es necesario estandarizar los datos de longitud y latitud, en este caso toca dividir el valor puesto entre 1000

# Crea un mapa
map <- leaflet(base1) %>%
  addTiles() %>%
  addMarkers(
    lng = ~longitud,
    lat = ~latitud,
    popup = ~paste("Barrio:", barrio, "<br>",
                            "Tipo:", tipo, "<br>",
                            "Latitud:", latitud, "<br>",
                            "Longitud:", longitud, "<br>",
                            
                            "Precio:", preciom) # Puedes personalizar el contenido del popup aquí
  )

map # Muestra el mapa

Existen 253 Casas ubicadas en la zona norte , en su gran mayoría corresponden a esta , aunque hay algunos casos en los que esta marcados pero su latitud y longitud da por fuera de la zona , en su mayoría los que estan asignados al barrio acopi

Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio del apartamento) en función del área construida, estrato, número de baños, número de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.

Teniendo en cuenta que la correlación y la regresión lineal simple son herramientas bastante acertivas para identifiar que relación existe entre dos variables, por eso se toma la decisión de usar esta medodologia

Exploración Variable Área Construida Vs Precio

cor(x=base1$areaconst,y=base1$preciom)
## [1] 0.731348
scatter_price_area <- plot_ly(data = base1, x = ~areaconst, y = ~preciom,
                               type = "scatter", mode = "markers",
                               marker = list(size = 8, opacity = 0.7),
                               text = ~paste("Zona:", zona),
                               colors = ~zona)

scatter_price_area <- scatter_price_area %>%
  layout(title = "Relación entre Precio y Área Construida",
         xaxis = list(title = "Área Construida"),
         yaxis = list(title = "Precio"))

scatter_price_area
modelo_1_areaconst <- lm(preciom ~ areaconst, data = base1)
# Resumen del modelo
summary(modelo_1_areaconst)
## 
## Call:
## lm(formula = preciom ~ areaconst, data = base1)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1455.63   -93.96   -30.63    56.17   953.92 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 134.9491    12.7768   10.56   <2e-16 ***
## areaconst     1.1741     0.0408   28.77   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 183.2 on 720 degrees of freedom
## Multiple R-squared:  0.5349, Adjusted R-squared:  0.5342 
## F-statistic:   828 on 1 and 720 DF,  p-value: < 2.2e-16

Correlación : El valor de 0.7313 sugiere una correlación moderada aportando un 53.5% de variabilidad lo que significa que este procentaje de area construida explica el precio de la vivienda, teniendo en cuneta esto se peude concluir, que hay una relación positiva significativa entre estas dos variables, pero no es extremadamente fuerte, lo que nos lleva a concluir que si el área construida es mayor, es más probable que el precio de la vivienda aumente.

Exploración Estrato Vs Precio

cor(x=base1$areaconst,y=base1$estrato)
## [1] 0.4573818
scatter_price_nse <- plot_ly(data = base1, x = ~areaconst, y = ~estrato,
                               type = "scatter", mode = "markers",
                               marker = list(size = 8, opacity = 0.7),
                               text = ~paste("Zona:", zona),
                               colors = ~zona)

scatter_price_nse <- scatter_price_nse %>%
  layout(title = "Relación entre Precio y Estrato",
         xaxis = list(title = "Estrato"),
         yaxis = list(title = "Precio"))

scatter_price_nse
modelo_1_nse <- lm(preciom ~ estrato, data = base1)
# Resumen del modelo
summary(modelo_1_nse)
## 
## Call:
## lm(formula = preciom ~ estrato, data = base1)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -454.3 -124.9  -44.6   70.7 1387.9 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -256.710     34.718  -7.394 3.96e-13 ***
## estrato      167.201      8.045  20.783  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 212.3 on 720 degrees of freedom
## Multiple R-squared:  0.375,  Adjusted R-squared:  0.3741 
## F-statistic:   432 on 1 and 720 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,46 lo cual indica que el precio con la variable estrati tiene cierta relación pero muy debil y adicional a esto solo el 37.5% de la variabilida de los precios esta representada por la variable estrato, al final de esto podemos concluir que no hay una relación directa entre el precio y el estrato

Exploración Estrato Vs Numero de baños

cor(x=base1$banios,y=base1$preciom)
## [1] 0.5233357
scatter_price_bathrooms <- plot_ly(data = base1, x = ~banios, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   text = ~paste("Zona:", zona),
                                   colors = ~zona)

scatter_price_bathrooms <- scatter_price_bathrooms %>%
  layout(title = "Relación entre Precio y Número de Baños",
         xaxis = list(title = "Número de Baños"),
         yaxis = list(title = "Precio"))

scatter_price_bathrooms
modelo_1_banios<- lm(preciom ~ banios, data = base1)
# Resumen del modelo
summary(modelo_1_banios)
## 
## Call:
## lm(formula = preciom ~ banios, data = base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -455.54 -142.55  -59.38   71.57 1313.12 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  118.228     21.631   5.466 6.36e-08 ***
## banios        92.163      5.593  16.479  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 228.8 on 720 degrees of freedom
## Multiple R-squared:  0.2739, Adjusted R-squared:  0.2729 
## F-statistic: 271.6 on 1 and 720 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,52 lo cual indica que el precio con la variable numero de baños tiene cierta relación pero muy debil y adicional a esto solo el 27.39% de la variabilida de los precios esta representada por la variable numero de baños, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de baños.

Exploración Estrato Vs Numero de habitaciones

cor(x=base1$habitaciones,y=base1$preciom)
## [1] 0.3227096
scatter_price_rooms <- plot_ly(data = base1, x = ~habitaciones, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   colors = ~zona)

scatter_price_rooms <- scatter_price_rooms %>%
  layout(title = "Relación entre Precio y Número de habitaciones",
         xaxis = list(title = "Número de Habitaciones"),
         yaxis = list(title = "Precio"))

scatter_price_rooms
modelo_1_rooms<- lm(preciom ~ habitaciones, data = base1)
# Resumen del modelo
summary(modelo_1_rooms)
## 
## Call:
## lm(formula = preciom ~ habitaciones, data = base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -413.81 -174.50  -53.19  105.50 1233.81 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   232.348     25.187   9.225   <2e-16 ***
## habitaciones   47.384      5.179   9.149   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 254.2 on 720 degrees of freedom
## Multiple R-squared:  0.1041, Adjusted R-squared:  0.1029 
## F-statistic:  83.7 on 1 and 720 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,32 lo cual indica que el precio con la variable numero de habitaciones tiene baja relación y adicional a esto solo el 10.41% de la variabilida de los precios esta representada por la variable numero de habitaciones, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de habitaciones.

Exploración Estrato Vs Zona

En este caso como la zona esta filtrada lo mas seguro es no salga logico el ejercicio, de igual manera se realizara para comprobar esto, pero posteriormente se relizara con la base de datos completa e identifiar la correlación.

cor(x=base1$habitaciones,y=base1$zona_numeric)
## [1] NA
scatter_price_zone <- plot_ly(data = base1, x = ~zona_numeric, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   colors = ~zona_numeric)

scatter_price_zone <- scatter_price_zone %>%
  layout(title = "Relación entre Precio y Número de habitaciones",
         xaxis = list(title = "Número de Habitaciones"),
         yaxis = list(title = "Precio"))

scatter_price_zone
modelo_1_zone<- lm(preciom ~ zona_numeric, data = base1)
# Resumen del modelo
summary(modelo_1_zone)
## 
## Call:
## lm(formula = preciom ~ zona_numeric, data = base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -356.91 -184.66  -55.91  104.09 1494.09 
## 
## Coefficients: (1 not defined because of singularities)
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   445.906      9.987   44.65   <2e-16 ***
## zona_numeric       NA         NA      NA       NA    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 268.4 on 721 degrees of freedom

Realizaremos la correlación entre precio y zona con la base completa.

cor(x=datavivienda$habitaciones,y=datavivienda$zona_numeric)
## [1] 0.02696498
scatter_price_zone2 <- plot_ly(data = datavivienda, x = ~zona_numeric, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   colors = ~zona_numeric)

scatter_price_zone2 <- scatter_price_zone2 %>%
  layout(title = "Relación entre Precio y Número de habitaciones",
         xaxis = list(title = "Número de Habitaciones"),
         yaxis = list(title = "Precio"))

scatter_price_zone2
modelo_1_zone2<- lm(preciom ~ zona_numeric, data = datavivienda)
# Resumen del modelo
summary(modelo_1_zone2)
## 
## Call:
## lm(formula = preciom ~ zona_numeric, data = datavivienda)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -560.44 -203.15  -93.15  101.85 1596.85 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   263.824      8.415   31.35   <2e-16 ***
## zona_numeric   79.324      3.569   22.23   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 319.3 on 8317 degrees of freedom
## Multiple R-squared:  0.05607,    Adjusted R-squared:  0.05595 
## F-statistic:   494 on 1 and 8317 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,026 lo cual indica que el precio con la variable Zona tiene baja relación, casi inexistente a esto solo el 5.61% de la variabilida de los precios esta representada por la variable zona, al final de esto podemos concluir que no hay una relación directa entre el precio y la zona.

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

Primero se evaluara de manera conjunta todas las variabes solicitadas.

cor_1 <-base1[,c("preciom","areaconst","estrato","banios","habitaciones","parqueaderos")]
#cor_1
library(GGally)
ggpairs(cor_1, title=" ") 

Ahora si realizaremos el modelo:

modelo_in<- lm(preciom ~ 1, data=base1)

modelo_all <- lm(preciom ~ habitaciones + banios + areaconst  + parqueaderos+ estrato, data = base1)
summary(modelo_all)
## 
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos + 
##     estrato, data = base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -881.35  -77.16  -15.60   44.54 1028.87 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -219.36885   29.26709  -7.495 1.96e-13 ***
## habitaciones    0.53353    4.05051   0.132    0.895    
## banios         21.26676    5.32894   3.991 7.26e-05 ***
## areaconst       0.77619    0.04362  17.796  < 2e-16 ***
## parqueaderos   29.95492    5.59289   5.356 1.15e-07 ***
## estrato        77.54993    7.23291  10.722  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 156.1 on 716 degrees of freedom
## Multiple R-squared:  0.6642, Adjusted R-squared:  0.6618 
## F-statistic: 283.2 on 5 and 716 DF,  p-value: < 2.2e-16
Coeficientes de variables predictoras:

2.habitaciones: El coeficiente estimado para el número de habitaciones (habitac) es 0.53. Esto significa que, manteniendo todas las demás variables constantes, un aumento de una unidad en el número de habitaciones se asocia con un aumento estimado de $530 mil pesos en el precio de la vivienda, adicional a esto, este coeficiente no es estadísticamente significativo un p-value = 0.89.

3.banios: El coeficiente estimado para el número de baños (banios) es 21.26. Esto implica que, manteniendo constantes las demás variables, un aumento de una unidad en el número de baños se asocia con un aumento estimado de $21.93 millones de pesos de en el precio de la vivienda, adicional a esto, este cofeciente es estadísticamente significativo un p-value = 7.26e-05.

4.areaconst: El coeficiente para el área construida (areaconst) es 0.77. Esto significa que un aumento de una unidad en el área construida se relaciona con un aumento estimado de $776 mil pesos en el precio de la vivienda, adicional a esto, este coeficiente es estadísticamente significativo (alto) un p-value < 2e-16.

5.parqueaderos: El coeficiente estimado para el número de parqueaderos (parquea) es 29.95. Esto sugiere que un aumento de una unidad en el número de parqueaderos se asocia con un aumento estimado de $29.95 millones en el precio de la vivienda, y este coeficiente es estadísticamente significativo (alto) un p-value = 1.15e-07.

6.estrato: El coeficiente para el estrato es 77.54. Esto indica que un aumento de una unidad en el estrato se relaciona con un aumento estimado de $77.54 millones en el precio de la vivienda, y este coeficiente es estadísticamente significativo (alto) un p-value < 2e-16.

7.R-cuadrado (Multiple R-squared): El R-cuadrado es 0.66, lo que significa que aproximadamente el 66.4% de la variabilidad en el precio de la vivienda se explica por las variables independientes incluidas en el modelo.

Recomendaciones para la mejora del modelo: Inicialmente se podria aplicar un logaritmo a alguna de las variable que se presente poca correlación con la variable precio. Por otro lado, se puede mejorar la estimación del modelo mediante el uso de metodológica de estimación de manera gradual, con procesos de paso a paso o Steppwise.
####Steppwise
# Se aplica el proceso forward stepwise regression

forward <- step(modelo_in, direction='forward', scope=formula(modelo_all), trace=0)

# Visualización de los resultados 
forward$anova
##             Step Df   Deviance Resid. Df Resid. Dev      AIC
## 1                NA         NA       721   51926104 8076.348
## 2    + areaconst -1 27773709.6       720   24152394 7525.701
## 3      + estrato -1  5069011.9       719   19083382 7357.623
## 4 + parqueaderos -1  1102855.8       718   17980526 7316.643
## 5       + banios -1   542097.1       717   17438429 7296.541
#resultado final del modelo
summary(forward)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios, 
##     data = base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -880.26  -77.15  -15.62   44.25 1030.06 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -217.6489    26.1749  -8.315 4.59e-16 ***
## areaconst       0.7774     0.0426  18.247  < 2e-16 ***
## estrato        77.3230     7.0200  11.015  < 2e-16 ***
## parqueaderos   29.9787     5.5862   5.367 1.08e-07 ***
## banios         21.6248     4.5804   4.721 2.82e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 156 on 717 degrees of freedom
## Multiple R-squared:  0.6642, Adjusted R-squared:  0.6623 
## F-statistic: 354.5 on 4 and 717 DF,  p-value: < 2.2e-16

Este resultado lo que nos indica es que debemos realizar de nuevo el modelo de regresión lienal teniendo en cuenta las variables areaconst, estrato, paruqeaderos y banios.

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

Supuesto de Normalidad

plot(modelo_all$fitted.values, resid(modelo_all), xlab = "Valores Ajustados", ylab = "Residuos", main = "Gráfico de Residuos vs. Valores Ajustados")

plot(modelo_all$fitted.values, sqrt(abs(resid(modelo_all)/sd(resid(modelo_all)))), xlab = "Valores Ajustados", ylab = "Raíz Cuadrada de los Residuos Estandarizados", main = "Gráfico de Homocedasticidad")

autoplot(modelo_all)

shapiro.test(resid(modelo_all))
## 
##  Shapiro-Wilk normality test
## 
## data:  resid(modelo_all)
## W = 0.84168, p-value < 2.2e-16
vif(modelo_all)
## habitaciones       banios    areaconst parqueaderos      estrato 
##     1.622464     1.952212     1.573739     1.422341     1.496057
datos_sin_atipicos <- base1[-which(abs(resid(modelo_all)) > 2 * sd(resid(modelo_all))), ]

De manera resumida podemos encontrar que el valor que nos da en W, el cual es relativamente bajo, sugiere que los residuos no siguen una distribución Normal, por otro lado el El p-valor es extremadamente bajo, mucho menor que cualquier umbral típico (como 0.05 o 0.01). Esto significa que hay evidencia muy fuerte para rechazar la hipótesis nula del test, que es que los residuos siguen una distribución normal.

Supuesto de independencia de errores:

dwtest(modelo_all)
## 
##  Durbin-Watson test
## 
## data:  modelo_all
## DW = 1.6278, p-value = 2.202e-07
## alternative hypothesis: true autocorrelation is greater than 0

Esto que encontramos en este supuesto, queire decir que hay autocorrelación positiva significativa en los residuos del modelo, lo que sugiere que podría ser necesario ajustar el modelo o considerar otros enfoques para manejar esta autocorrelación.

Supuesto de varianza de los errores

gqtest(modelo_all)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_all
## GQ = 1.1129, df1 = 355, df2 = 355, p-value = 0.1571
## alternative hypothesis: variance increases from segment 1 to 2

En este supuesto encontramos que la varianza de los errores no varía significativamente entre los segmentos, lo que indica que no hay heterocedasticidad significativa en el modelo.

Supuesto de Linealidad:

g3=ggplot(base1, aes(preciom, areaconst)) + geom_point() + geom_smooth(method = "lm",  level = 0.95, formula = y ~ x)
g4=ggplot(base1, aes(preciom, banios)) + geom_point() + geom_smooth(method = "lm",  level = 0.95, formula = y ~ x)

grid.arrange(g3, g4, ncol = 2)

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

A continuación se crea un dataframe con las caracteristicas y los requisitos de la vivienda 1

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

requerimientos_cliente1
##   estrato areaconst parqueaderos banios habitaciones
## 1       4       200            1      2            4
## 2       5       200            1      2            4

Ahora ejecutaremos el modelo sin ajustes tal como lo detalla el ejercicio:

Precio_1<-predict(modelo_all,data.frame(requerimientos_cliente1),type="response")

print(paste("Precio de la  casa : ", as.character(Precio_1)))
## [1] "Precio de la  casa :  320.69136594713" 
## [2] "Precio de la  casa :  398.241293159088"
base1_viviendas_e4<- base1 %>% 
    dplyr::filter(estrato==4,areaconst>=200,parqueaderos>=1,banios>=2,habitaciones==4,preciom<=350) %>% 
    mutate(promedio_reg=320.6913,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=350-preciom) %>% 
    arrange("areaconst")

base1_viviendas_e4
## # A tibble: 10 × 17
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  7471 Zona … <NA>        4     330      240             1      4            4
##  2  4458 Zona … 02          4     315      270             2      4            4
##  3  2837 Zona … <NA>        4     340      207             1      4            4
##  4  3352 Zona … <NA>        4     335      300             3      4            4
##  5  4727 Zona … 02          4     296      232             1      6            4
##  6   937 Zona … 02          4     350      280             2      3            4
##  7  1108 Zona … 02          4     330      260             1      3            4
##  8  1144 Zona … <NA>        4     320      200             2      4            4
##  9  2544 Zona … 01          4     340      264.            2      4            4
## 10  1822 Zona … <NA>        4     340      295             2      2            4
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## #   diferencia_cupo <dbl>
base1_viviendas_e5<- base1 %>% 
    dplyr::filter(estrato==5,areaconst>=200,parqueaderos>=1,banios>=2,habitaciones==4,preciom<=350) %>% 
    mutate(promedio_reg=398.2412,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=350-preciom) %>% 
    arrange("areaconst")

base1_viviendas_e5
## # A tibble: 11 × 17
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  4210 Zona … 01          5     350       200            3      3            4
##  2  4800 Zona … 01          5     340       250            2      4            4
##  3   852 Zona … <NA>        5     340       208            2      6            4
##  4   819 Zona … 02          5     350       264            2      3            4
##  5  1343 Zona … 02          5     320       200            2      4            4
##  6  3053 Zona … 02          5     320       230            2      4            4
##  7  1163 Zona … <NA>        5     350       216            2      2            4
##  8  1849 Zona … <NA>        5     330       246            2      4            4
##  9  1887 Zona … 01          5     340       203            2      3            4
## 10  1842 Zona … 02          5     350       240            2      3            4
## 11  1943 Zona … <NA>        5     350       346            1      2            4
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## #   diferencia_cupo <dbl>
Casas <-rbind(base1_viviendas_e4,base1_viviendas_e5)

map <- leaflet(Casas) %>%
  addTiles() %>%
  addMarkers(
    lng = ~longitud,
    lat = ~latitud,
    popup = ~paste("Barrio:", barrio, "<br>",
                            "Tipo:", tipo, "<br>",
                            "Latitud:", latitud, "<br>",
                            "Longitud:", longitud, "<br>",
                            
                            "Precio:", preciom) # Puedes personalizar el contenido del popup aquí
  )

map # Muestra el mapa

BASE 2 VIVIENDAS TIPO APARTAMENTO EN EL SUR

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

Inicialmente realizamos el filtro de las viviendas tipo Casa de la zona Norte de la ciudad de Cali

base2 <- datavivienda %>%
  filter(tipo=="Apartamento",zona=="Zona Sur")
dim(base2)
## [1] 2787   14
head(base2,3)
## # A tibble: 3 × 14
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  5098 Zona S… 05          4     290        96            1      2            3
## 2   698 Zona S… 02          3      78        40            1      1            2
## 3  8199 Zona S… <NA>        6     875       194            2      5            3
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   zona_numeric <dbl>

Ahora procederemos a realizar el mapa con la base 2 filtrado.

Es necesario estandarizar los datos de longitud y latitud, en este caso toca dividir el valor puesto entre 1000

# Crea un mapa
map <- leaflet(base2) %>%
  addTiles() %>%
  addMarkers(
    lng = ~longitud,
    lat = ~latitud,
    popup = ~paste("Barrio:", barrio, "<br>",
                            "Tipo:", tipo, "<br>",
                            "Latitud:", latitud, "<br>",
                            "Longitud:", longitud, "<br>",
                            
                            "Precio:", preciom) # Puedes personalizar el contenido del popup aquí
  )

map # Muestra el mapa

Exploración Variable Área Construida Vs Precio

cor(x=base2$areaconst,y=base2$preciom)
## [1] 0.7579955
scatter_price_area2 <- plot_ly(data = base2, x = ~areaconst, y = ~preciom,
                               type = "scatter", mode = "markers",
                               marker = list(size = 8, opacity = 0.7),
                               text = ~paste("Zona:", zona),
                               colors = ~zona)

scatter_price_area2 <- scatter_price_area2 %>%
  layout(title = "Relación entre Precio y Área Construida",
         xaxis = list(title = "Área Construida"),
         yaxis = list(title = "Precio"))

scatter_price_area2
modelo_2_areaconst <- lm(preciom ~ areaconst, data = base1)
# Resumen del modelo
summary(modelo_2_areaconst)
## 
## Call:
## lm(formula = preciom ~ areaconst, data = base1)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1455.63   -93.96   -30.63    56.17   953.92 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 134.9491    12.7768   10.56   <2e-16 ***
## areaconst     1.1741     0.0408   28.77   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 183.2 on 720 degrees of freedom
## Multiple R-squared:  0.5349, Adjusted R-squared:  0.5342 
## F-statistic:   828 on 1 and 720 DF,  p-value: < 2.2e-16

Correlación : El valor de 0.7579 sugiere una correlación moderada aportando un 53.5% de variabilidad lo que significa que este procentaje de area construida explica el precio de la vivienda, teniendo en cuneta esto se peude concluir, que hay una relación positiva significativa entre estas dos variables, pero no es extremadamente fuerte, lo que nos lleva a concluir que si el área construida es mayor, es más probable que el precio de la vivienda aumente.

Exploración Estrato Vs Precio

cor(x=base2$areaconst,y=base2$estrato)
## [1] 0.4815593
scatter_price_nse2 <- plot_ly(data = base2, x = ~areaconst, y = ~estrato,
                               type = "scatter", mode = "markers",
                               marker = list(size = 8, opacity = 0.7),
                               text = ~paste("Zona:", zona),
                               colors = ~zona)

scatter_price_nse2 <- scatter_price_nse2 %>%
  layout(title = "Relación entre Precio y Estrato",
         xaxis = list(title = "Estrato"),
         yaxis = list(title = "Precio"))

scatter_price_nse2
modelo_2_nse <- lm(preciom ~ estrato, data = base1)
# Resumen del modelo
summary(modelo_2_nse)
## 
## Call:
## lm(formula = preciom ~ estrato, data = base1)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -454.3 -124.9  -44.6   70.7 1387.9 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -256.710     34.718  -7.394 3.96e-13 ***
## estrato      167.201      8.045  20.783  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 212.3 on 720 degrees of freedom
## Multiple R-squared:  0.375,  Adjusted R-squared:  0.3741 
## F-statistic:   432 on 1 and 720 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,48 lo cual indica que el precio con la variable estrati tiene cierta relación pero muy debil y adicional a esto solo el 37.5% de la variabilida de los precios esta representada por la variable estrato, al final de esto podemos concluir que no hay una relación directa entre el precio y el estrato

Exploración Estrato Vs Numero de baños

cor(x=base2$banios,y=base2$preciom)
## [1] 0.7196705
scatter_price_bathrooms2 <- plot_ly(data = base2, x = ~banios, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   text = ~paste("Zona:", zona),
                                   colors = ~zona)

scatter_price_bathrooms2 <- scatter_price_bathrooms2 %>%
  layout(title = "Relación entre Precio y Número de Baños",
         xaxis = list(title = "Número de Baños"),
         yaxis = list(title = "Precio"))

scatter_price_bathrooms2
modelo_2_banios<- lm(preciom ~ banios, data = base1)
# Resumen del modelo
summary(modelo_2_banios)
## 
## Call:
## lm(formula = preciom ~ banios, data = base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -455.54 -142.55  -59.38   71.57 1313.12 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  118.228     21.631   5.466 6.36e-08 ***
## banios        92.163      5.593  16.479  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 228.8 on 720 degrees of freedom
## Multiple R-squared:  0.2739, Adjusted R-squared:  0.2729 
## F-statistic: 271.6 on 1 and 720 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,71 lo cual indica que el precio con la variable numero de baños tiene relación y adicional a esto solo el 27.39% de la variabilida de los precios esta representada por la variable numero de baños, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de baños.

Exploración Estrato Vs Numero de habitaciones

cor(x=base2$habitaciones,y=base2$preciom)
## [1] 0.3317538
scatter_price_rooms2 <- plot_ly(data = base2, x = ~habitaciones, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   colors = ~zona)

scatter_price_rooms2 <- scatter_price_rooms2 %>%
  layout(title = "Relación entre Precio y Número de habitaciones",
         xaxis = list(title = "Número de Habitaciones"),
         yaxis = list(title = "Precio"))

scatter_price_rooms2
modelo_2_rooms<- lm(preciom ~ habitaciones, data = base2)
# Resumen del modelo
summary(modelo_2_rooms)
## 
## Call:
## lm(formula = preciom ~ habitaciones, data = base2)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -447.15 -104.98  -50.29   39.25 1449.25 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    -0.641     16.415  -0.039    0.969    
## habitaciones  100.464      5.413  18.559   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 180.7 on 2785 degrees of freedom
## Multiple R-squared:  0.1101, Adjusted R-squared:  0.1097 
## F-statistic: 344.4 on 1 and 2785 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,33 lo cual indica que el precio con la variable numero de habitaciones tiene baja relación y adicional a esto solo el 11.01% de la variabilida de los precios esta representada por la variable numero de habitaciones, al final de esto podemos concluir que no hay una relación directa entre el precio y el numero de habitaciones.

Exploración Estrato Vs Zona

En este caso como la zona esta filtrada lo mas seguro es no salga logico el ejercicio, de igual manera se realizara para comprobar esto, pero posteriormente se relizara con la base de datos completa e identifiar la correlación.

cor(x=base2$habitaciones,y=base2$zona_numeric)
## [1] NA
scatter_price_zone2 <- plot_ly(data = base1, x = ~zona_numeric, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   colors = ~zona_numeric)

scatter_price_zone2 <- scatter_price_zone2 %>%
  layout(title = "Relación entre Precio y Número de habitaciones",
         xaxis = list(title = "Número de Habitaciones"),
         yaxis = list(title = "Precio"))

scatter_price_zone2
modelo_2_zone<- lm(preciom ~ zona_numeric, data = base2)
# Resumen del modelo
summary(modelo_2_zone)
## 
## Call:
## lm(formula = preciom ~ zona_numeric, data = base2)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -222.29 -122.29  -52.29   37.71 1452.71 
## 
## Coefficients: (1 not defined because of singularities)
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   297.292      3.628   81.94   <2e-16 ***
## zona_numeric       NA         NA      NA       NA    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 191.6 on 2786 degrees of freedom

Realizaremos la correlación entre precio y zona con la base completa.

cor(x=datavivienda$habitaciones,y=datavivienda$zona_numeric)
## [1] 0.02696498
scatter_price_zone2 <- plot_ly(data = datavivienda, x = ~zona_numeric, y = ~preciom,
                                   type = "scatter", mode = "markers",
                                   marker = list(size = 8, opacity = 0.7),
                                   colors = ~zona_numeric)

scatter_price_zone2 <- scatter_price_zone2 %>%
  layout(title = "Relación entre Precio y Número de habitaciones",
         xaxis = list(title = "Número de Habitaciones"),
         yaxis = list(title = "Precio"))

scatter_price_zone2
modelo_1_zone2<- lm(preciom ~ zona_numeric, data = datavivienda)
# Resumen del modelo
summary(modelo_1_zone2)
## 
## Call:
## lm(formula = preciom ~ zona_numeric, data = datavivienda)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -560.44 -203.15  -93.15  101.85 1596.85 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   263.824      8.415   31.35   <2e-16 ***
## zona_numeric   79.324      3.569   22.23   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 319.3 on 8317 degrees of freedom
## Multiple R-squared:  0.05607,    Adjusted R-squared:  0.05595 
## F-statistic:   494 on 1 and 8317 DF,  p-value: < 2.2e-16

Correlación: El valor es 0,026 lo cual indica que el precio con la variable Zona tiene baja relación, casi inexistente a esto solo el 5.61% de la variabilida de los precios esta representada por la variable zona, al final de esto podemos concluir que no hay una relación directa entre el precio y la zona.

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

Primero se evaluara de manera conjunta todas las variabes solicitadas.

cor_2 <-base2[,c("preciom","areaconst","estrato","banios","habitaciones","parqueaderos")]
#cor_2
library(GGally)
ggpairs(cor_2, title=" ") 

Ahora si realizaremos el modelo:

modelo_in2<- lm(preciom ~ 1, data=base2)

modelo_all2 <- lm(preciom ~ habitaciones + banios + areaconst  + parqueaderos+ estrato, data = base2)
summary(modelo_all2)
## 
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos + 
##     estrato, data = base2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1201.45   -42.25    -1.60    36.71   935.81 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -215.05601   13.40840 -16.039  < 2e-16 ***
## habitaciones  -22.67919    3.37020  -6.729 2.06e-11 ***
## banios         47.93433    3.01751  15.885  < 2e-16 ***
## areaconst       1.40640    0.04902  28.693  < 2e-16 ***
## parqueaderos   57.18042    3.29246  17.367  < 2e-16 ***
## estrato        54.35821    2.80476  19.381  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 94.47 on 2781 degrees of freedom
## Multiple R-squared:  0.7572, Adjusted R-squared:  0.7568 
## F-statistic:  1735 on 5 and 2781 DF,  p-value: < 2.2e-16
Coeficientes de variables predictoras:

1.habitac: Un incremento de una unidad en el número de habitaciones se asocia con una disminución de aproximadamente $22.67 millones en el precio de la vivienda, manteniendo constantes las otras variables.

2.banios: Un aumento de una unidad en el número de baños está relacionado con un aumento de proximadamente $47.93 millones en el precio de la vivienda, manteniendo constantes las otras variables.

3.areaconst: Un incremento de una unidad en el área construida está relacionado con un aumento de aproximadamente $1.40 millones en el precio de la vivienda, manteniendo constantes las otras variables.

4.parquea: Un aumento de una unidad en el número de parqueaderos se asocia con un aumento de aproximadamente $57.18 millones en el precio de la vivienda, manteniendo constantes las otras variables.

5.estrato: Un aumento de una unidad en el estrato se asocia con un aumento de aproximadamente $54.35 millones en el precio de la vivienda, manteniendo constantes las otras variables.

6.R-squared (R-cuadrado): El R-cuadrado mide la proporción de la variabilidad en el precio de la vivienda que es explicada por el modelo. Un R-cuadrado de 0.7572 indica que alrededor del 75.72% de la variabilidad en el precio de la vivienda es explicada por las variables independientes incluidas en el modelo.

autoplot(modelo_all2)

#### 4. Supuestos del modelo para e segundo modelo, entrenado con las viviendas tipo apartamento de la zona sur.

Supuesto de Normalidad

plot(modelo_all2$fitted.values, resid(modelo_all2), xlab = "Valores Ajustados", ylab = "Residuos", main = "Gráfico de Residuos vs. Valores Ajustados")

plot(modelo_all2$fitted.values, sqrt(abs(resid(modelo_all2)/sd(resid(modelo_all2)))), xlab = "Valores Ajustados", ylab = "Raíz Cuadrada de los Residuos Estandarizados", main = "Gráfico de Homocedasticidad")

autoplot(modelo_all2)

shapiro.test(resid(modelo_all2))
## 
##  Shapiro-Wilk normality test
## 
## data:  resid(modelo_all2)
## W = 0.7846, p-value < 2.2e-16
vif(modelo_all2)
## habitaciones       banios    areaconst parqueaderos      estrato 
##     1.418807     2.481899     2.072688     1.944476     1.741592
datos_sin_atipicos <- base1[-which(abs(resid(modelo_all2)) > 2 * sd(resid(modelo_all2))), ]

De manera resumida podemos encontrar que el valor que nos da en W, esta por debajo de 1, sugiere que los residuos no siguen una distribución Normal, por otro lado el El p-valor es extremadamente bajo, mucho menor que cualquier umbral típico (como 0.05 o 0.01). Esto significa que hay evidencia muy fuerte para rechazar la hipótesis nula del test, que es que los residuos siguen una distribución normal.

Supuesto de independencia de errores:

dwtest(modelo_all2)
## 
##  Durbin-Watson test
## 
## data:  modelo_all2
## DW = 1.5063, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

Para este caso podemos identificar que existe autocorrelación positiva en los residuos de tu modelo. Esto puede afectar la validez de tus resultados, por lo que sería recomendable ajustar tu modelo para manejar este problema.

Supuesto de varianza de los errores

gqtest(modelo_all2)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo_all2
## GQ = 0.9188, df1 = 1388, df2 = 1387, p-value = 0.9426
## alternative hypothesis: variance increases from segment 1 to 2

En este supuesto encontramos que no hay heterocedasticidad en tu modelo de regresión, lo que significa que la varianza de los residuos es constante a lo largo de las observaciones. Esto es positivo para la validez del modelo.

Supuesto de Linealidad:

g3=ggplot(base2, aes(preciom, areaconst)) + geom_point() + geom_smooth(method = "lm",  level = 0.95, formula = y ~ x)
g4=ggplot(base2, aes(preciom, banios)) + geom_point() + geom_smooth(method = "lm",  level = 0.95, formula = y ~ x)

grid.arrange(g3, g4, ncol = 2)

Ahora vamos a validar si el ajuste al modelo anterior tambien se puede proponer para este modelo entrenado con apartamentos de la Zona Sur

datos_sin_atipicos <- base2[-which(abs(resid(modelo_all2)) > 2 * sd(resid(modelo_all2))), ]

Vamos a aplicar el proceso de Forward Stepwise para confirmar cuales podrian ser las mejores variables a usar en este caso.

forward <- step(modelo_in2, direction='forward', scope=formula(modelo_all2), trace=0)

# Visualización de los resultados 
forward$anova
##             Step Df   Deviance Resid. Df Resid. Dev      AIC
## 1                NA         NA      2786  102222866 29293.22
## 2    + areaconst -1 58732885.4      2785   43489980 26913.38
## 3      + estrato -1 12599342.2      2784   30890638 25962.01
## 4 + parqueaderos -1  3811022.8      2783   27079615 25597.04
## 5       + banios -1  1858794.2      2782   25220821 25400.85
## 6 + habitaciones -1   404098.3      2781   24816723 25357.83
#resultado final del modelo
summary(forward)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios + 
##     habitaciones, data = base2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1201.45   -42.25    -1.60    36.71   935.81 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -215.05601   13.40840 -16.039  < 2e-16 ***
## areaconst       1.40640    0.04902  28.693  < 2e-16 ***
## estrato        54.35821    2.80476  19.381  < 2e-16 ***
## parqueaderos   57.18042    3.29246  17.367  < 2e-16 ***
## banios         47.93433    3.01751  15.885  < 2e-16 ***
## habitaciones  -22.67919    3.37020  -6.729 2.06e-11 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 94.47 on 2781 degrees of freedom
## Multiple R-squared:  0.7572, Adjusted R-squared:  0.7568 
## F-statistic:  1735 on 5 and 2781 DF,  p-value: < 2.2e-16

De acuerdo al modelo de Steppwise se puede evidenciar que la variable mas relvente para explicar el precio, luego esta el areaconstruida,estrato, parqueaderos, baños y numero de habitaciones.

Estimación del modelo con la base 2 usando, teniendo en cuenta lo detallado en las necesidades de Vivienda2.

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

requerimientos_vivienda2
##   estrato areaconst parqueaderos banios habitaciones
## 1       5       300            3      3            5
## 2       6       300            3      3            5
Precio_1_sur<-predict(modelo_all2,data.frame(requerimientos_vivienda2),type="response")

print(paste("Precio del apartamento :", as.character(Precio_1_sur)))
## [1] "Precio del apartamento : 680.603654796031"
## [2] "Precio del apartamento : 734.961864917186"
base2_viviendas_e5<- base2 %>% dplyr::filter(estrato==5,areaconst>=100,parqueaderos>=3,banios>=3,habitaciones>=5,preciom<=850) %>% mutate(promedio_reg=680.6036,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=850-preciom) %>% arrange("areaconst")

base2_viviendas_e5
## # A tibble: 3 × 17
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  7182 Zona S… <NA>        5     730       573            3      8            5
## 2  7512 Zona S… <NA>        5     670       300            3      5            6
## 3  8036 Zona S… <NA>        5     530       256            3      5            5
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## #   diferencia_cupo <dbl>
base2_viviendas_e6<- base2 %>% dplyr::filter(estrato==6,areaconst>=100,parqueaderos>=2,banios>=3,habitaciones>=5,preciom<=850) %>% mutate(promedio_reg=734.9618,diferencia_promedio=promedio_reg-preciom,diferencia_cupo=850-preciom) %>% arrange("areaconst")

base2_viviendas_e6
## # A tibble: 1 × 17
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  4266 Zona S… 05          6     700       250            2      4            5
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   zona_numeric <dbl>, promedio_reg <dbl>, diferencia_promedio <dbl>,
## #   diferencia_cupo <dbl>
aptos<- rbind(base2_viviendas_e5,base2_viviendas_e6)
map <- leaflet(aptos) %>%
  addTiles() %>%
  addMarkers(
    lng = ~longitud,
    lat = ~latitud,
    popup = ~paste("Barrio:", barrio, "<br>",
                            "Tipo:", tipo, "<br>",
                            "Latitud:", latitud, "<br>",
                            "Longitud:", longitud, "<br>",
                            
                            "Precio:", preciom) # Puedes personalizar el contenido del popup aquí
  )

map # Muestra el mapa

Ahora como parte del ejericio del documento adjunto se realizara par la base 1 y base 2 la separación de los datos en 70% entrenamiento y 30% test

Iniciaremos con base 1

set.seed(1234)
n <- nrow(base1)
print(n)
## [1] 722
train_indices <- sample(1:n, size = 0.7 * n)
#print(train_indices)
train_base1 <- base1[train_indices, ]
test_base1 <- base1[-train_indices, ]

dim(train_base1)
## [1] 505  14
dim(test_base1)
## [1] 217  14

Ya con este proceso tenemos separada la base de entrenamiento y prueba, ya con esto procederemos a entrenar el modelo, usando esta base:

modelo_train_b1 <- lm(preciom ~ habitaciones + banios + areaconst  + parqueaderos+ estrato, data = train_base1)
summary(modelo_train_b1)
## 
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos + 
##     estrato, data = train_base1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -773.91  -81.34  -17.62   40.56  984.01 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -205.96052   36.55256  -5.635 2.94e-08 ***
## habitaciones    3.15010    5.18225   0.608   0.5436    
## banios         17.82037    6.91665   2.576   0.0103 *  
## areaconst       0.87613    0.05711  15.342  < 2e-16 ***
## parqueaderos   28.87205    7.22893   3.994 7.48e-05 ***
## estrato        69.54357    9.04626   7.688 8.03e-14 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 162.7 on 499 degrees of freedom
## Multiple R-squared:  0.6681, Adjusted R-squared:  0.6647 
## F-statistic: 200.9 on 5 and 499 DF,  p-value: < 2.2e-16

Ahora realizare la ejecución del modelo para las predicciones de la base 1, este con la base de test:

Seteamos una nueva variable para a NA precionm para posteriormente asignarle el valor de la vivienda calculado por el modelo

# Asignar NA a la variable precio en test_base1
test_base1$preciomn <- NA

Ejecutamos el modelo y le asigans el valor a la variable precio mn

test_base1$preciomn <- predict(modelo_train_b1,test_base1,type="response")

Lo que se puede observar es que el modelo predice valores cercanos al valor encontrado en la base de datos de test para algunos casos y para otros no, es claro que como se evidencio en los anteriores ejericios este modelo requiere ajustes, posiblemente en la selección de las variables del modelo.

Iniciaremos con base 2

set.seed(1234)
n <- nrow(base2)
print(n)
## [1] 2787
train_indices <- sample(1:n, size = 0.7 * n)
#print(train_indices)
train_base2 <- base2[train_indices, ]
test_base2 <- base2[-train_indices, ]

dim(train_base2)
## [1] 1950   14
dim(test_base2)
## [1] 837  14

Ya con este proceso tenemos separada la base de entrenamiento y prueba, ya con esto procederemos a entrenar el modelo, usando esta base:

modelo_train_b2 <- lm(preciom ~ habitaciones + banios + areaconst  + parqueaderos+ estrato, data = train_base2)
summary(modelo_train_b2)
## 
## Call:
## lm(formula = preciom ~ habitaciones + banios + areaconst + parqueaderos + 
##     estrato, data = train_base2)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -490.19  -38.65    1.10   36.75  807.42 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -202.2336    14.4093 -14.035  < 2e-16 ***
## habitaciones  -28.2615     3.6218  -7.803 9.78e-15 ***
## banios         38.2155     3.3163  11.523  < 2e-16 ***
## areaconst       2.0717     0.0634  32.674  < 2e-16 ***
## parqueaderos   38.3821     3.5355  10.856  < 2e-16 ***
## estrato        51.7985     3.0221  17.140  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 86.24 on 1944 degrees of freedom
## Multiple R-squared:  0.7956, Adjusted R-squared:  0.7951 
## F-statistic:  1513 on 5 and 1944 DF,  p-value: < 2.2e-16

Ahora realizare la ejecución del modelo para las predicciones de la base 1, este con la base de test:

Seteamos una nueva variable para a NA precionm para posteriormente asignarle el valor de la vivienda calculado por el modelo

# Asignar NA a la variable precio en test_base1
test_base2$preciomn <- NA

Ejecutamos el modelo y le asigans el valor a la variable precio mn

test_base2$preciomn <- predict(modelo_train_b2,test_base2,type="response")

Lo que se puede observar es que el modelo predice valores cercanos al valor encontrado en la base de datos de test para algunos casos y para otros no, es claro que como se evidencio en los anteriores ejericios este modelo requiere ajustes, posiblemente en la selección de las variables del modelo.

Ahora se procedera a calcular el error cuadrático medio, el error absoluto medio y el R2.

Error cuadratico medio base 1:

mse_base1 <- mean((test_base1$preciom - test_base1$preciomn)^2)
print(mse_base1)
## [1] 20359.49

Este resultado de MSE 20359.49 indica que, en promedio, el cuadrado de los errores de predicción es 20359.49, un MSE más bajo es preferible, ya que indica que las predicciones del modelo están más cerca de los valores reales.

Error cuadratico medio base 2:

mse_base2 <- mean((test_base2$preciom - test_base2$preciomn)^2)
print(mse_base2)
## [1] 14411.17

Este MSE aun cuando es mejor que con la base 1 sigue siendo alto, es importante definitivamente hacer ajustes al medelo porque los valores que arroja la predicción siguen siendo lejanos del los reales.

Error absoluto medio base 1:

mae_base1 <- mean(abs(test_base1$preciom - test_base1$preciomn))
print(mae_base1)
## [1] 94.33283

Esto quiere decir que en promedio cada predio se esta alejando del valor real 94.33, el cual es un valor considrable teniendo en cuenta el valor de los precios de las viviendas.

Conclusiones

Se puede observar en la base 1 que con las condiciones de vivienda solicitadas en el ejercicio, según la predicción de precio del modelo se pueden encontrar viviendas desde 320 millones para estrato 4 y 398 millones para estrato 5, ahora bien teniendo en cuenta el presupuesto de 350 millones inicialmente por el resultado del modelo solo se tendría la opción de casa en estrato 4, pero si buscamos en promedio con el valor que dio el modelo si se encuentran casas de estrato 5 con estas condiciones

Para la base 2 con las condiciones de vivienda solicitadas en el ejercicio, según la predicción del modelo se pueden encontrar viviendas, exactamente 3 apartamentos con estas condiciones y valor de 680 millones para estrato 5 y de 735 millones para estrato 6, aproximadamente, para este caso el valor máximo que es el de estrato 6 podemos tener el presupuesto suficiente para seleccionar los apartmentos que encontremos en la base, que para este caso con esas condiciones en estrato 5 encontramos 3 y para estrato 6 no se encontró ninguno con las condiciones originales, por esto optamos por hacer una oferta con 2 parqueaderos, para la cual encontramos un apartamento.

Viéndolo desde el punto de vista técnico encontramos que los modelos que se desarrollaron no obtuvieron un buen performance de predicción en ninguno de los casos, donde obtuvo un mejor comportamiento fue con la base de viviendas del Sur, pero tal como lo propusimos en el contenido del ejercicio es importante hacer unos ajustes, tales como Steppwise para seleccionar las mejores variables predictoras para este caso, donde para cada base se detallo y se evidenciaron cuales eran.

Me queda de experiencia de haber realizado los puntos del otro ejercicio donde entrenamos con el 70% de los datos de cada una de las bases y hacemos el test con el 30, que es mas diciente hacer este tipo de ejercicios y por medio de los errores cuadráticos ver las diferencias Vs los datos reales y de esta forma poder llegar a una buena predicción en un modelo de este estilo.