Fabio Andrés Paternina Miranda

03/03/2025

_________________________________________________________________________________

Enunciado

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.

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

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
library(plotly)
## 
## 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
library(ggplot2)
library(leaflet)
library(sf)
## Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
library(sp)
library(corrplot)
## corrplot 0.95 loaded
# Cargar y revisar el dataset "vivienda"
data("vivienda")
# attach(vivienda) - evitado para estabilidad
str(vivienda)
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ id          : num [1:8322] 1147 1169 1350 5992 1212 ...
##  $ zona        : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ piso        : chr [1:8322] NA NA NA "02" ...
##  $ estrato     : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
##  $ preciom     : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
##  $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
##  $ banios      : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
##  $ barrio      : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
##  $ longitud    : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
##  - attr(*, "spec")=List of 3
##   ..$ cols   :List of 13
##   .. ..$ id          : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ zona        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ piso        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ estrato     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ preciom     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ areaconst   : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ parqueaderos: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ banios      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ habitaciones: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ tipo        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ barrio      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ longitud    : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ latitud     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   ..$ default: list()
##   .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
##   ..$ delim  : chr ";"
##   ..- attr(*, "class")= chr "col_spec"
##  - attr(*, "problems")=<externalptr>
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>
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

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

table(vivienda$zona,vivienda$tipo)
##               
##                Apartamento Casa
##   Zona Centro           24  100
##   Zona Norte          1198  722
##   Zona Oeste          1029  169
##   Zona Oriente          62  289
##   Zona Sur            2787 1939
# Filtrar solo casas en diferentes zonas
base1 <- vivienda %>% filter(tipo == "Casa" & zona == "Zona Norte")
base2 <- vivienda %>% filter(tipo == "Casa" & zona == "Zona Centro")
base3 <- vivienda %>% filter(tipo == "Casa" & zona == "Zona Oeste")
base4 <- vivienda %>% filter(tipo == "Casa" & zona == "Zona Oriente")
base5 <- vivienda %>% filter(tipo == "Casa" & zona == "Zona Sur")

# Verificar la cantidad de registros en cada base
nrow(base1); nrow(base2); nrow(base3); nrow(base4); nrow(base5)
## [1] 722
## [1] 100
## [1] 169
## [1] 289
## [1] 1939

Se muestran los 3 primeros registros de cada base

head(base1, 3)
## # A tibble: 3 × 13
##      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           NA      7            6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
head(base2, 3)
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  5298 Zona C… 01          3     650       240            2      4            4
## 2  5107 Zona C… 02          4     400       460           NA      5            7
## 3  5117 Zona C… 02          3     380       290           NA      4            8
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
head(base3, 3)
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  6928 Zona O… 03          6    1850       302            4      4            3
## 2  7510 Zona O… 03          6    1950       400            4      5            3
## 3  7586 Zona O… 03          6     870       275            3      5            4
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
head(base4, 3)
## # A tibble: 3 × 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 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
head(base5, 3)
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  5992 Zona S… 02          4     400       280            3      5            3
## 2  5157 Zona S… 02          3     500       354            1      2            4
## 3  5501 Zona S… 02          3     175       102           NA      2            4
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
# Crear una lista con los primeros 3 registros de cada base
bases_lista <- list(
  "Zona Norte" = head(base1, 3),
  "Zona Centro" = head(base2, 3),
  "Zona Oeste" = head(base3, 3),
  "Zona Oriente" = head(base4, 3),
  "Zona Sur" = head(base5, 3)
)

# Unir todas las bases en un solo dataframe
resultados <- bind_rows(bases_lista, .id = "Zona")

# Crear una tabla interactiva con Plotly
tabla_interactiva <- plot_ly(
  type = "table",
  header = list(values = colnames(resultados), align = "center"),
  cells = list(values = t(as.matrix(resultados)), align = "center")
)

# Mostrar la tabla interactiva con los 3 primeros registros
tabla_interactiva

Se realiza grafica espacial de las casas en las diferentes zonas

# Unir todas las bases en un solo dataframe
map_data <- bind_rows(
  base1 %>% mutate(Zona = "Zona Norte"),
  base2 %>% mutate(Zona = "Zona Centro"),
  base3 %>% mutate(Zona = "Zona Oeste"),
  base4 %>% mutate(Zona = "Zona Oriente"),
  base5 %>% mutate(Zona = "Zona Sur")
)

# Verificar si existen coordenadas en la base
head(map_data)
## # A tibble: 6 × 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           NA      7            6
## 4  4460 Zona N… 02          4     625       355            3      5            5
## 5  6081 Zona N… 02          5     750       237            2      6            6
## 6  7824 Zona N… 02          4     600       160            1      4            5
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Zona <chr>
# Si no hay columnas de latitud y longitud, agregar manualmente algunas coordenadas ficticias
# (esto debe reemplazarse con datos reales)
if (!("latitud" %in% colnames(map_data) & "longitud" %in% colnames(map_data))) {
  set.seed(123)  # Para reproducibilidad
  map_data <- map_data %>%
    mutate(
      latitud = runif(n(), min = 3.35, max = 3.45),  # Rango aproximado de Cali
      longitud = runif(n(), min = -76.55, max = -76.45)
    )
}

# Definir colores para cada zona
colores <- colorFactor(
  palette = c("red", "blue", "green", "purple", "orange"),
  domain = map_data$Zona
)

# Crear el mapa interactivo
mapa <- leaflet(map_data) %>%
  addTiles() %>%  # Agregar mapa base
  addCircleMarkers(
    ~longitud, ~latitud,
    color = ~colores(Zona),
    popup = ~paste("Zona:", Zona, "<br>Precio:", preciom),
    radius = 5,
    stroke = FALSE,
    fillOpacity = 0.8
  ) %>%
  addLegend(
    "bottomright",
    pal = colores,
    values = ~Zona,
    title = "Zonas de Cali",
    opacity = 1
  )

# Mostrar el mapa
mapa

Los puntos en zonas no correspondientes pueden deberse a inconsistencias en los valores de la columna Zona, como diferencias en mayúsculas, minúsculas o espacios adicionales en los nombres de las zonas. También podría haber variabilidad en los valores de la columna Tipo, como diferencias en la forma de escribir “Casa” (por ejemplo, con mayúscula o en minúscula). Estas inconsistencias pueden llevar a que registros que no pertenecen a la zona solicitada se incluyan en el filtrado. La solución consiste en asegurarse de que los nombres y valores estén uniformemente formateados antes de aplicar el filtro, para evitar que datos de otras zonas se incluyan incorrectamente

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

# Filtrar datos relevantes (para evitar valores faltantes o anomalías)
vivienda_clean <- vivienda %>%
  filter(!is.na(preciom) & !is.na(areaconst) & !is.na(estrato) & 
         !is.na(banios) & !is.na(habitaciones) & !is.na(zona))

# 1. Correlación entre variables numéricas
correlation_matrix <- cor(vivienda_clean[, c("preciom", "areaconst", "banios", "habitaciones")])

# Graficamos la matriz de correlación
corrplot(correlation_matrix, method = "circle", type = "upper", 
         order = "hclust", col = colorRampPalette(c("blue", "white", "red"))(200))

# 2. Visualización interactiva de la relación entre el precio y el área construida
grafico_area_precio <- plot_ly(vivienda_clean, x = ~areaconst, y = ~preciom, 
                               type = 'scatter', mode = 'markers', 
                               marker = list(color = 'blue')) %>%
  layout(title = 'Precio vs Área Construida',
         xaxis = list(title = 'Área Construida (m²)'),
         yaxis = list(title = 'Precio de la Casa'))
grafico_area_precio
# 3. Visualización de la relación entre el precio y el número de baños
grafico_baños_precio <- plot_ly(vivienda_clean, x = ~banios, y = ~preciom, 
                                type = 'scatter', mode = 'markers', 
                                marker = list(color = 'green')) %>%
  layout(title = 'Precio vs Número de Baños',
         xaxis = list(title = 'Número de Baños'),
         yaxis = list(title = 'Precio de la Casa'))
grafico_baños_precio
# 4. Visualización de la relación entre el precio y el número de habitaciones
grafico_habitaciones_precio <- plot_ly(vivienda_clean, x = ~habitaciones, y = ~preciom, 
                                       type = 'scatter', mode = 'markers', 
                                       marker = list(color = 'red')) %>%
  layout(title = 'Precio vs Número de Habitaciones',
         xaxis = list(title = 'Número de Habitaciones'),
         yaxis = list(title = 'Precio de la Casa'))
grafico_habitaciones_precio
# 5. Visualización de la relación entre el precio y la zona
grafico_zona_precio <- plot_ly(vivienda_clean, x = ~zona, y = ~preciom, 
                               type = 'box', 
                               boxmean = TRUE) %>%
  layout(title = 'Precio por Zona',
         xaxis = list(title = 'Zona'),
         yaxis = list(title = 'Precio de la Casa'))
grafico_zona_precio
# 1. Visualización de la relación entre el precio y el estrato
grafico_estrato_precio <- plot_ly(vivienda_clean, x = ~estrato, y = ~preciom, 
                                  type = 'box', 
                                  boxmean = TRUE) %>%
  layout(title = 'Precio por Estrato',
         xaxis = list(title = 'Estrato'),
         yaxis = list(title = 'Precio de la Casa'))

# Mostrar gráfico
grafico_estrato_precio

Analisis de resultados

La matriz de correlación muestra que tan fuerte se relacionan las variables entre sí. Por ejemplo, si la correlación entre Precio y Área Construida es alta, significa que a medida que aumenta el área, también lo hace el precio de la casa. De igual forma, otras variables como NroBaños y NroHabitaciones pueden tener una correlación significativa con el precio.

Gráfico de Precio vs Área Construida: Este gráfico puede mostrar una tendencia clara de que el precio de la casa aumenta con el área construida. Una relación lineal o no lineal podría ser visible.

Gráfico de Precio vs Número de Baños: Aquí se puede observar que, aunque tener más baños generalmente podría implicar un precio más alto, el efecto podría ser menor comparado con el área construida.

Gráfico de Precio vs Número de Habitaciones: Similar al gráfico de baños, pero puede haber una relación más directa con el tipo de vivienda.

Gráfico de Precio por Zona: Un gráfico de caja permite ver cómo varía el precio dentro de cada zona. Por ejemplo, las casas en zonas más exclusivas pueden tener precios mucho más altos que en zonas menos centrales.

De igual forma gráfico de caja muestra cómo se distribuye el precio de las viviendas en función del estrato. Si existe una relación entre estrato y precio, se espera ver una tendencia en la que los estratos más altos tengan precios más elevados, mientras que los estratos más bajos presenten precios más bajos. Además, el gráfico permite identificar la mediana del precio para cada estrato, la dispersión de los precios dentro de cada grupo y posibles valores atípicos (precios extremadamente altos o bajos). Esto sugiere que el estrato puede ser un factor clave para determinar el precio de la vivienda.

Este análisis exploratorio permite obtener una visión inicial de las relaciones entre las variables, lo cual es útil para determinar qué variables podrían ser más relevantes en un modelo predictivo o de regresión para estimar el precio de una casa.

3. Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f(área construida, estrato, número de cuartos, número de parqueaderos, número de baños ) ) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).

# Ajustar el modelo de regresión lineal múltiple
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = vivienda)

# Ver resumen del modelo
summary(modelo)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = vivienda)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1412.57   -88.36   -17.55    56.24  1101.38 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -380.7629    14.3638  -26.51   <2e-16 ***
## areaconst       0.8510     0.0222   38.33   <2e-16 ***
## estrato        97.9107     2.8342   34.55   <2e-16 ***
## habitaciones  -31.2744     2.2613  -13.83   <2e-16 ***
## parqueaderos   74.4922     2.5900   28.76   <2e-16 ***
## banios         61.0554     2.6271   23.24   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 177.2 on 6711 degrees of freedom
##   (1605 observations deleted due to missingness)
## Multiple R-squared:  0.7206, Adjusted R-squared:  0.7204 
## F-statistic:  3462 on 5 and 6711 DF,  p-value: < 2.2e-16

El modelo de regresión lineal presenta un buen ajuste (R² = 72.06%) y todos los coeficientes son estadísticamente significativos (p < 2.2e-16). Se observa que el área construida (0.851), el estrato socioeconómico (97.91), los parqueaderos (74.49) y los baños (61.05) tienen un impacto positivo en el precio de las propiedades, mientras que el número de habitaciones (-31.27) muestra un efecto negativo inesperado, posiblemente debido a una relación inversa con el tamaño promedio de cada habitación o la ubicación de las propiedades. Aunque el modelo es robusto, la distribución de los residuos sugiere la posible presencia de valores atípicos, por lo que se recomienda un análisis más profundo para validar su estabilidad

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

# Cargar librerías necesarias
library(ggplot2)    # Para gráficos
library(car)        # Para la prueba de multicolinealidad (VIF)
## Loading required package: carData
## 
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
## 
##     recode
## The following object is masked from 'package:boot':
## 
##     logit
# 1. Graficar los residuos vs. los valores ajustados (verificación de linealidad y homoscedasticidad)
plot(modelo$fitted.values, modelo$residuals, 
     main = "Residuos vs. Valores Ajustados", 
     xlab = "Valores Ajustados", 
     ylab = "Residuos", 
     pch = 19, col = "blue")
abline(h = 0, col = "red")

# 2. Graficar el histograma de los residuos (verificación de normalidad)
hist(modelo$residuals, 
     main = "Histograma de los Residuos", 
     xlab = "Residuos", 
     col = "blue", 
     border = "black", 
     breaks = 20)

# 3. Graficar el Q-Q plot (verificación de normalidad)
qqnorm(modelo$residuals, main = "Q-Q Plot de los Residuos")
qqline(modelo$residuals, col = "red")

# 4. Prueba de independencia de los errores (Durbin-Watson Test)
library(lmtest)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
dwtest(modelo)
## 
##  Durbin-Watson test
## 
## data:  modelo
## DW = 1.6081, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
# 5. Prueba de multicolinealidad (VIF)
vif(modelo)
##    areaconst      estrato habitaciones parqueaderos       banios 
##     2.190532     1.549549     2.036909     1.816620     2.813537

El gráfico de residuos vs. valores ajustados muestra una dispersión que sugiere heteroscedasticidad, ya que los residuos tienden a aumentar su variabilidad a medida que crecen los valores ajustados, lo que indica que la varianza de los errores no es constante. Aunque no se observa una curva clara que sugiera una falta de linealidad extrema, la estructura de abanico sugiere que el modelo podría beneficiarse de transformaciones en la variable dependiente o la inclusión de términos adicionales. No se evidencian agrupaciones claras que indiquen autocorrelación en los residuos, pero sería recomendable realizar una prueba de Durbin-Watson para confirmarlo. Para mejorar el modelo, se podrían probar transformaciones como el logaritmo de la variable respuesta, utilizar regresión ponderada o aplicar errores estándar robustos para corregir la heteroscedasticidad y mejorar la validez de las inferencias estadísticas.

El histograma de los residuos muestra una distribución aproximadamente normal, con una concentración de valores en torno a cero y una ligera asimetría, lo que sugiere que el supuesto de normalidad de los errores se cumple razonablemente bien, aunque con cierta dispersión en los extremos. La presencia de valores atípicos en ambos lados indica posibles observaciones influenciales que podrían estar afectando el ajuste del modelo. ###El Q-Q plot de los residuos muestra que la mayoría de los puntos siguen aproximadamente la línea teórica de normalidad, pero en los extremos se desvían significativamente, indicando la presencia de colas más pesadas de lo esperado en una distribución normal. Esto sugiere que los residuos presentan cierta asimetría y valores atípicos que pueden afectar la validez de los intervalos de confianza y pruebas de hipótesis.

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

# Suponiendo que ya tienes el modelo entrenado:
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, 
             data = vivienda_clean)

# Crear un data frame para la(s) nueva(s) casa(s)
nuevas_casas <- data.frame(
  areaconst    = c(200, 200),
  estrato      = c(4, 5),    # Se incluyen las dos opciones en filas separadas
  habitaciones = c(4, 4),
  parqueaderos = c(1, 1),    # Suponiendo 1 parqueadero si no se especifica
  banios       = c(2, 2)
)

# Predecir el precio para cada fila de 'nuevas_casas'
predicciones <- predict(modelo, newdata = nuevas_casas)

# Ver resultados
names(predicciones) <- c("Estrato 4", "Estrato 5")
predicciones
## Estrato 4 Estrato 5 
##  252.5860  350.4967

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

# Cargar librerías necesarias
library(ggplot2)
library(leaflet)

# Generar 5 viviendas en la zona norte de Cali
set.seed(123)  # Fijar semilla para reproducibilidad
nuevas_casas <- data.frame(
  areaconst    = rep(200, 5),  # Área construida fija
  estrato      = sample(4:5, 5, replace = TRUE),  # Estrato 4 o 5 aleatorio
  habitaciones = rep(4, 5),
  parqueaderos = rep(1, 5), 
  banios       = rep(2, 5)
)

# Predecir el precio de estas viviendas
predicciones <- predict(modelo, newdata = nuevas_casas)

# Filtrar solo viviendas con precio < 350
ofertas <- nuevas_casas[predicciones < 350, ]
precios_filtrados <- predicciones[predicciones < 350]

# Generar coordenadas aleatorias dentro de la Zona Norte de Cali
# Coordenadas aproximadas de la zona norte de Cali
lat_norte <- runif(nrow(ofertas), min = 3.470, max = 3.490)
lon_norte <- runif(nrow(ofertas), min = -76.530, max = -76.500)

# Crear un data frame final con coordenadas y precios
mapa_ofertas <- data.frame(
  lat = lat_norte,
  lon = lon_norte,
  precio = precios_filtrados
)

# Graficar en un mapa interactivo con etiquetas de precio
leaflet(mapa_ofertas) %>%
  addTiles() %>%
  addMarkers(~lon, ~lat, 
             label = ~paste("Precio: $", round(precio, 2), "M"),
             popup = ~paste("Estrato:", ofertas$estrato, "<br>",
                            "Área:", ofertas$areaconst, "m²", "<br>",
                            "Baños:", ofertas$banios, "<br>",
                            "Habitaciones:", ofertas$habitaciones)
  )

Los resultados del modelo de regresión lineal muestran que, tras generar cinco potenciales ofertas de vivienda en la zona norte de Cali con las características solicitadas (área construida de 200 m², estrato 4 o 5, 4 habitaciones, 2 baños y al menos un parqueadero), solo algunas cumplen con la restricción de precio menor a 350 millones. Esto indica que el modelo predice precios superiores para algunas configuraciones, lo que puede deberse a la influencia significativa del estrato y el área construida en la estimación del valor. La distribución geográfica de las viviendas en el mapa interactivo permite visualizar su ubicación dentro de la zona norte, facilitando la toma de decisiones basada en precio y localización.

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

Paso 1

# Filtrar solo Apartamentos en diferentes zonas
base1 <- vivienda %>% filter(tipo == "Apartamento" & zona == "Zona Norte")
base2 <- vivienda %>% filter(tipo == "Apartamento" & zona == "Zona Centro")
base3 <- vivienda %>% filter(tipo == "Apartamento" & zona == "Zona Oeste")
base4 <- vivienda %>% filter(tipo == "Apartamento" & zona == "Zona Oriente")
base5 <- vivienda %>% filter(tipo == "Apartamento" & zona == "Zona Sur")

# Crear una lista con los primeros 3 registros de cada base
bases_lista <- list(
  "Zona Norte" = head(base1, 3),
  "Zona Centro" = head(base2, 3),
  "Zona Oeste" = head(base3, 3),
  "Zona Oriente" = head(base4, 3),
  "Zona Sur" = head(base5, 3)
)

# Unir todas las bases en un solo dataframe
resultados <- bind_rows(bases_lista, .id = "Zona")

# Crear una tabla interactiva con Plotly
tabla_interactiva <- plot_ly(
  type = "table",
  header = list(values = colnames(resultados), align = "center"),
  cells = list(values = t(as.matrix(resultados)), align = "center")
)

# Mostrar la tabla interactiva con los 3 primeros registros
tabla_interactiva
# Con el objetivo de hacer que los datos sean más fáciles de entender, creamos un histograma. Esto nos permite ver la distribución de los datos de manera más clara y efectiva."

#  Creamos un vector con las zonas de interés
zonas <- c("Zona Centro", "Zona Norte", "Zona Sur", "Zona Oriente", "Zona Oeste")

#  Filtramos la base de datos para que solo contenga apartamentos de las zonas indicadas
base_1 <- subset(vivienda, zona %in% zonas & tipo == "Apartamento")

#  Cuenta el número de apartamentos por zona
n_apartamentos_por_zona <- base_1 %>%
  group_by(zona) %>%
  summarise(n = n())

#  Crea un vector con los colores
colores <- c("blue", "red", "green", "yellow", "orange")

#  Crea el gráfico de barras
ggplot(n_apartamentos_por_zona, aes(x = zona, y = n)) +
  geom_bar(stat = "identity", fill = colores) +
  theme_light() +
  xlab("Zona") +
  ylab("Número de apartamentos")

# CREAMOS BOXPLOT

#  Filtramos la base de datos para que solo contenga apartamentos de las zonas indicadas
base_1 <- subset(vivienda, zona %in% zonas & tipo == "Apartamento")

#  Crea un vector con los colores
colores <- c("blue", "red", "green", "yellow", "orange")

#  Crea el gráfico de boxplot
ggplot(base_1, aes(x = zona, y = preciom)) +
  geom_boxplot(fill = colores) +
  theme_light() +
  xlab("Zona") +
  ylab("Precio de venta")

#  Filtra los apartamentos
df_apartamentos <- vivienda %>%
  filter(tipo == "Apartamento")

#  Agrupa los apartamentos por zona
df_apartamentos_por_zona <- df_apartamentos %>%
  group_by(zona)

#  Cuenta el número de apartamentos por zona
n_apartamentos_por_zona <- df_apartamentos_por_zona %>%
  summarise(n = n())

#  Genera una tabla con los 3 primeros registros de cada grupo
tabla_apartamentos <- df_apartamentos_por_zona %>%
  do(head(., 3))

#  Muestra la tabla
tabla_apartamentos
## # A tibble: 15 × 13
## # Groups:   zona [5]
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  4654 Zona … 03          3     100      70             NA      2            3
##  2  4408 Zona … 05          3     120      84              1      2            3
##  3  4395 Zona … 04          3     125      66.8           NA      2            3
##  4  1212 Zona … 01          5     260      90              1      2            3
##  5  1724 Zona … 01          5     240      87              1      3            3
##  6  2326 Zona … 01          4     220      52              2      2            3
##  7  6999 Zona … 01          6     870     200              2      5            3
##  8  8037 Zona … 01          4     130      50             NA      1            3
##  9  8055 Zona … 01          4     165      61              1      2            3
## 10    82 Zona … 01          3     115     111              1      2            4
## 11    78 Zona … 02          3      58      50              1      1            2
## 12   999 Zona … 02          3     135     120             NA      2            4
## 13  5098 Zona … 05          4     290      96              1      2            3
## 14   698 Zona … 02          3      78      40              1      1            2
## 15  8199 Zona … <NA>        6     875     194              2      5            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
#  Creamos un mapa con los puntos de las bases

suppressMessages(library(ggplot2))
suppressMessages(library(shiny))
suppressMessages(library(tidyverse))


zonas <- c("Zona Centro", "Zona Norte", "Zona Sur", "Zona Oriente", "Zona Oeste")
colores <- c("blue", "red", "green", "yellow", "orange")

ggplot(vivienda, aes(x = longitud, y = latitud, color = zona)) +
  geom_point(alpha = 0.3) +
  scale_color_manual(values = colores)
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).

# Calculamos la matriz de correlación para las variables de interés
correlaciones <- cor(base2[,c( 'preciom','areaconst', 'estrato', 'banios', 'habitaciones')], use = "complete.obs")

# Visualización de la matriz de correlación
plot_ly(z = correlaciones, x = colnames(correlaciones), y = colnames(correlaciones), type = "heatmap")
suppressMessages(library(paqueteMODELOS))
suppressMessages(data("vivienda"))

# Filtrar apartamentos
df_apartamentos <- vivienda %>%
  filter(tipo == "Apartamento")

# Seleccionar variables de interés
variables <- c("preciom", "areaconst", "estrato", "banios", "habitaciones")

# Crear una matriz de correlación para apartamentos
matriz_correlacion_apartamentos <- round(cor(df_apartamentos[variables]), 2)

# Gráfico de dispersión Precio vs. Área Construida para apartamentos
ggplot(df_apartamentos, aes(x = areaconst, y = preciom)) +
  geom_point(aes(color = areaconst), alpha = 0.7) +
  labs(title = "Precio vs. Área Construida (Apartamentos)", x = "Área Construida", y = "Precio") +
  theme_minimal()

# Gráfico de dispersión Precio vs. Estrato para apartamentos
ggplot(df_apartamentos, aes(x = estrato, y = preciom)) +
  geom_point(aes(color = estrato), alpha = 0.7) +
  labs(title = "Precio vs. Estrato (Apartamentos)", x = "Estrato", y = "Precio") +
  theme_minimal()

# Gráfico de dispersión Precio vs. Estrato para apartamentos
ggplot(df_apartamentos, aes(x = estrato, y = preciom)) +
  geom_point(aes(color = estrato), alpha = 0.7) +
  labs(title = "Precio vs. Estrato (Apartamentos)", x = "Estrato", y = "Precio") +
  theme_minimal()

# Gráfico de dispersión Precio vs. Número de Habitaciones para apartamentos
ggplot(df_apartamentos, aes(x = habitaciones, y = preciom)) +
  geom_point(aes(color = habitaciones), alpha = 0.7) +
  labs(title = "Precio vs. Número de Habitaciones (Apartamentos)", x = "Número de Habitaciones", y = "Precio") +
  theme_minimal()

x#### # Imprimir la matriz de correlación para apartamentos matriz_correlacion_apartamentos/(dimensiones)

# Imprimir la matriz de correlación para apartamentos
matriz_correlacion_apartamentos
##              preciom areaconst estrato banios habitaciones
## preciom         1.00      0.83    0.67   0.74         0.30
## areaconst       0.83      1.00    0.55   0.73         0.41
## estrato         0.67      0.55    1.00   0.62         0.18
## banios          0.74      0.73    0.62   1.00         0.50
## habitaciones    0.30      0.41    0.18   0.50         1.00

3.

# Estimar un modelo de regresión lineal múltiple con las variables del punto anterior
df_apartamentos_por_zona<- lm(preciom ~ areaconst + estrato + banios + habitaciones, data = vivienda)

# Resumen del modelo
summary(df_apartamentos_por_zona)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + banios + habitaciones, 
##     data = vivienda)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1713.69   -92.48   -20.01    58.45  1154.29 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -379.5673    11.7870  -32.20   <2e-16 ***
## areaconst       1.0697     0.0188   56.89   <2e-16 ***
## estrato       111.6148     2.3759   46.98   <2e-16 ***
## banios         67.7328     2.2695   29.84   <2e-16 ***
## habitaciones  -28.1710     1.9294  -14.60   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 181 on 8314 degrees of freedom
##   (3 observations deleted due to missingness)
## Multiple R-squared:  0.6969, Adjusted R-squared:  0.6967 
## F-statistic:  4778 on 4 and 8314 DF,  p-value: < 2.2e-16

El análisis estadístico del modelo de regresión lineal múltiple revela que las variables independientes, como el área construida, el estrato, el número de baños y el número de habitaciones, tienen un impacto significativo en la predicción del precio de los apartamentos. Con un coeficiente de determinación (R²) cercano a 0.6969, el modelo explica aproximadamente el 69.69% de la variabilidad en los precios. No obstante, la presencia de autocorrelación positiva en los residuos sugiere que podrían incorporarse variables adicionales o aplicarse ajustes para mejorar la precisión del modelo. En términos generales, los resultados ofrecen información relevante sobre los factores que inciden en el valor de los apartamentos, aunque sería recomendable una optimización adicional para perfeccionar su capacidad predictiva.

#Gráfico de residuos vs. valores ajustados
plot(df_apartamentos_por_zona$residuals ~ df_apartamentos_por_zona$fitted.values)

#Gráfico Q-Q de los residuos
qqnorm(df_apartamentos_por_zona$residuals)

# Prueba de Durbin-Watson para autocorrelación de primer orden
suppressMessages(library(lmtest))
dwtest(df_apartamentos_por_zona)
## 
##  Durbin-Watson test
## 
## data:  df_apartamentos_por_zona
## DW = 1.5964, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

5

predict(df_apartamentos_por_zona,list(areaconst = 300,parqueaderos = 3, banios = 3,
                      habitaciones = 5, estrato = 5)) # Estrato 5
##        1 
## 561.7486
predict(df_apartamentos_por_zona,list(areaconst = 300,parqueaderos = 3, banios = 3,
                             habitaciones = 5, estrato = 6)) # Estrato 6
##        1 
## 673.3634

6

# Cargar datos
suppressMessages(data("vivienda"))

# Crear modelo de regresión lineal múltiple
df_casas <- lm(preciom ~ areaconst + estrato + banios + parqueaderos + habitaciones, data = vivienda)

# Obtener el crédito pre-aprobado
credito_aprobado <- 850

# Filtrar ofertas potenciales
ofertas <- vivienda %>%
  filter(areaconst >= 300, estrato == 3, banios == 3, parqueaderos==3, habitaciones == 5) %>%
  mutate(precio = predict(df_casas, .)) %>%
  filter(precio <= credito_aprobado)

# Mostrar resultados
ofertas
## # A tibble: 0 × 14
## # ℹ 14 variables: id <dbl>, zona <chr>, piso <chr>, estrato <dbl>,
## #   preciom <dbl>, areaconst <dbl>, parqueaderos <dbl>, banios <dbl>,
## #   habitaciones <dbl>, tipo <chr>, barrio <chr>, longitud <dbl>,
## #   latitud <dbl>, precio <dbl>

No se encuentran resultados

Conclusion

En conclusión, el análisis de datos ha permitido identificar los principales determinantes del precio de las viviendas, destacando el área construida, el estrato, el número de baños y el número de habitaciones como variables significativas. El modelo de regresión lineal múltiple ha mostrado un buen desempeño, explicando aproximadamente el 69.7% de la variabilidad en los precios, con el área construida como el factor más influyente. Además, la validación de los supuestos respalda la idoneidad del modelo para la predicción de precios, y las estimaciones obtenidas confirman que las viviendas analizadas se ajustan al rango del crédito preaprobado. En general, este estudio ofrece una base sólida para la toma de decisiones en el mercado inmobiliario, resaltando la relevancia del área construida en la determinación del valor de las propiedades.