Caso C&A

Informe Ejecutivo Bogotá, 01 de Septiembre de 2025

Señores INMOBILIARIA C&A

Referencia: Informe Selección de inmueble partiendo de modelo lineal multivariado.

Respetados Señores,

A continuación, el informe de las conclusiones en la elaboracion del modelo de precios de inmuebles de la ciudad de cali:

Requerimiento: Con base en la informacions de ofertas de vivienda descargadas de la base de datos, requieren el apoyo en la construcción de un modelo que les oriente sobre los precios de los inmuebles para la compañia C&A que desea ubicar a dos de sus empleados con sus familias en la ciudad de Cali.

Revisión de la data Disponible: Se recibe un dataset (o base de datos) en formato R con 8.322 filas y 13 variables disponibles para evaluar entre ellas: Zona , Estrato, Precio M2, Área Construida, Tipo de Inmueble, etc.

Frente a los requermientos del cliente evaluamos estas como las mejores opciones:

Solicitud del Cliente

Vivienda No. 1: Tipo CASA, Precio de Venta < $350 Millones, area construida 200 m2, parqueaderos 1, baños 2, habitaciones 4, estrato 4 o 5, zona Norte

Vivienda No. 2: Tipo APARTAMENTO, Precio de Venta < $850 Millones, area construida 300 m2, parqueaderos 3, baños 3, habitaciones 5, estrato 5 o 6, zona Sur

Se hace análisis de la data identificando que habian inmuebles marcados en zonas que no correspondía, para lo cual se realizo un cre de información con un shp de cali que contiene los barrio y las comunas, de esta manera se remarco la zonas de cada casa y apartamento.

Conclusiones del Modelo Evaluado.

Frente a la definición del problema inicial en la construcción de un modelo que les oriente sobre los precios de los inmuebles con la data evaluada y los diferentes modelos se puede concluir que se sugiere que se debe buscar otro tipo de modelo diferentes a los evaluados que permitan explicar esa variable de precio debido a que esta no es explicada en buena medida solo por el área construida y estrato en su gran medida.

Se adjuntan documento R-Mark Down con las líneas de código de las variables y funciones evaluadas que acompañan cada una de las interpretaciones de los gráficos y tablas relacionadas en este informe, todas realizadas en el programa R estudio.

Quedo atento a sus comentarios,

Mario Fernando Barbosa Rodriguez Cientifico de Datos.

ANEXO

Solicitud del cliente

## |                    |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 |

Proceso:

  1. Se Realiza un filtro a la base de datos y se incluya solo las ofertas de: base1: casas, de la zona norte de la ciudad.

INFORME

Se carga la base de datos, se verifica si hay “NA” y pone como dato faltante.

data("vivienda")
vivienda <- as.data.frame(vivienda)

Tabla con Faltantes

tabla_na <- data.frame(Variable = names(vivienda),  NAs = colSums(is.na(vivienda)))
tabla_na %>%  gt() %>% tab_header(title = "Valores Faltantes por Cada Variable")
Valores Faltantes por Cada Variable
Variable NAs
id 3
zona 3
piso 2638
estrato 3
preciom 2
areaconst 3
parqueaderos 1605
banios 3
habitaciones 3
tipo 3
barrio 3
longitud 3
latitud 3

Se verifica si hay “NA” y pone como dato faltante.

Se quita el campo Piso porque presenta muchos faltantes y no puede ser deducible por ningun calculo adicional.

vivienda_1 <- vivienda[,-3]

Se rellena el campo del numero de paqueaderos con 0 indicando que no tiene

vivienda_1$parqueaderos <- ifelse(is.na(vivienda_1$parqueaderos),
                              0,
                              as.numeric(vivienda_1$parqueaderos))
vivienda_1 <- na.omit(vivienda_1)

Con el fin de identificar si esta correctamente marcado la zona donde se ubica el inmueble se descargo un archivo en formato de datos vectoriales de los barrios de Cali, tomado de https://datos.cali.gov.co/es/dataset/capa-de-barrios-de-santiago-de-cali?utm_source=chatgpt.com y se carga para ser confrontado con la base a estudiar.

# Ruta al archivo .shp
shapefile_path <- "C:/Users/Admin/Downloads/barrios_cali/mc_barrios.shp"
barrios <- st_read(shapefile_path) 
## Reading layer `mc_barrios' from data source 
##   `C:\Users\Admin\Downloads\barrios_cali\mc_barrios.shp' using driver `ESRI Shapefile'
## Simple feature collection with 337 features and 5 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1054098 ymin: 860192.1 xmax: 1068492 ymax: 879000.7
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
vivienda_sf <- st_as_sf(vivienda_1, coords = c("longitud", "latitud"), crs = 4326)
vivienda_sf <- st_transform(vivienda_sf, st_crs(barrios))

Se crea un data.frame que contiene toda la información de las viviendas, los nombres de barrios originales y del join, la comuna, y las coordenadas longitud y latitud, listo para análisis o mapas sin mantener la geometría de sf.

vivienda_join <- st_join(vivienda_sf, barrios[, c("barrio", "comuna")])
vivienda_geo <- st_transform(vivienda_join, 4326)
vivienda_1 <- vivienda_geo %>%
  mutate(
    longitud = st_coordinates(.)[,1],
    latitud  = st_coordinates(.)[,2],
    barrio_old = barrio.x,
    barrio     = barrio.y
  ) %>%
  st_drop_geometry()
vivienda_1 <- vivienda_1[, -c(10, 11)]

Se consulta la url https://www.cali.gov.co/planeacion/publicaciones/115924/mapas-comunas-idesc/ para identificar que comunas se encuentran al norte, sur, oriente, occidente y centro, y se marca cada inmueble del data.frame en la columna barrio, comuna y zona_n.

vivienda_1 <- vivienda_1 %>%
  mutate(
    zona_n = case_when(
      comuna %in% c("03", "08", "09", "10", "11", "12") ~ "CENTRO",
      comuna %in% c("02", "04", "05", "06") ~ "NORTE",
      comuna %in% c("07", "13", "14", "15", "21") ~ "ORIENTE",
      comuna %in% c("01") ~ "OCCIDENTE",
      comuna %in% c("16", "17", "18", "19", "20", "22") ~ "SUR",
      TRUE ~ "OTRO"   # por si alguna comuna no está en la lista
    )
  )
vivienda_1[] <- lapply(vivienda_1, function(x) {
  if (is.character(x)) enc2utf8(x) else x
})

Presenta el tipo de datos

glimpse_tbl <- data.frame(
  Variable = names(vivienda_1),
  Tipo = sapply(vivienda_1, class),
  Ejemplo = sapply(vivienda_1, function(x) paste0(head(x, 3), collapse = ", "))
)

glimpse_tbl %>%
  gt() %>%
  tab_header(title = "Estructura resumida de la base 'vivienda'")
Estructura resumida de la base 'vivienda'
Variable Tipo Ejemplo
id numeric 1147, 1169, 1350
zona character Zona Oriente, Zona Oriente, Zona Oriente
estrato numeric 3, 3, 3
preciom numeric 250, 320, 350
areaconst numeric 70, 120, 220
parqueaderos numeric 1, 1, 2
banios numeric 3, 2, 2
habitaciones numeric 6, 3, 4
tipo character Casa, Casa, Casa
comuna character 11, 11, 11
longitud numeric -76.51168, -76.51237, -76.51537
latitud numeric 3.43382, 3.43369, 3.43566
barrio_old character 20 de julio, 20 de julio, 20 de julio
barrio character 20 de Julio, 20 de Julio, El Prado
zona_n character CENTRO, CENTRO, CENTRO
library(DataExplorer)
## Warning: package 'DataExplorer' was built under R version 4.4.3
introduce(vivienda_1)
##   rows columns discrete_columns continuous_columns all_missing_columns
## 1 8319      15                6                  9                   0
##   total_missing_values complete_rows total_observations memory_usage
## 1                    0          8319             124785      1054376
plot_intro(vivienda_1)

Aproximadamente el 40% de las columnas son discretas (estrato, barrio, tipo), es decir, categorías o variables cualitativas.

El 60% restante son columnas continuas (preciom, areaconst, longitud, latitud), variables numéricas que pueden tomar cualquier valor dentro de un rango.

Ninguna columna está completamente vacía.

Todas las filas están completas, no hay filas totalmente vacías. Esto es muy bueno para modelado y análisis. Se considera como una data limpia.

Tabla de frecuencias absolutas por zona

cbind(table(vivienda_1$zona),prop.table(table(vivienda_1$zona))*100)
##              [,1]      [,2]
## Zona Centro   124  1.490564
## Zona Norte   1920 23.079697
## Zona Oeste   1198 14.400769
## Zona Oriente  351  4.219257
## Zona Sur     4726 56.809713

Se identifica que la mayor parte de los datos se concentran en Zona Sur, seguida por Zona Norte y Zona Oeste. Las zonas con menor representación son Oriente y Centro. Pero nos objeto de estudio porque no se haran comparaciones entre zonas.

Se aplica el Filtro Zona Norte

base1 <- vivienda_1 %>% 
  filter(zona == "Zona Norte")
head(base1, 3)
##     id       zona estrato preciom areaconst parqueaderos banios habitaciones
## 1 1212 Zona Norte       5     260        90            1      2            3
## 2 1724 Zona Norte       5     240        87            1      3            3
## 3 2326 Zona Norte       4     220        52            2      2            3
##          tipo comuna  longitud latitud barrio_old       barrio zona_n
## 1 Apartamento     04 -76.51350 3.45891      acopi     Porvenir  NORTE
## 2 Apartamento     17 -76.51700 3.36971      acopi         Lili    SUR
## 3 Apartamento     11 -76.51974 3.42627      acopi El Jard\xedn CENTRO

Estadisctca Unifica datos Zona Norte

tabla_zona <- base1 %>%
  group_by(zona, tipo, estrato) %>%
  summarise(n_registros = n()) %>%
  arrange(desc(n_registros))
## `summarise()` has grouped output by 'zona', 'tipo'. You can override using the
## `.groups` argument.
tabla_zona
## # A tibble: 8 × 4
## # Groups:   zona, tipo [2]
##   zona       tipo        estrato n_registros
##   <chr>      <chr>         <dbl>       <int>
## 1 Zona Norte Apartamento       5         498
## 2 Zona Norte Apartamento       3         337
## 3 Zona Norte Casa              5         271
## 4 Zona Norte Apartamento       4         246
## 5 Zona Norte Casa              3         235
## 6 Zona Norte Casa              4         161
## 7 Zona Norte Apartamento       6         117
## 8 Zona Norte Casa              6          55

Con el fin de identificar visualmente los datos filtrados, se procede a ubicarlos en un mapa de Cali

base1[] <- lapply(base1, function(x) {
  if (is.character(x)) {
    iconv(x, from = "latin1", to = "UTF-8", sub = "")
  } else {
    x
  }
})


# Crear el mapa
leaflet(base1) %>%
  addProviderTiles("CartoDB.Positron") %>% 
  setView(lng = -76.532, lat = 3.4516, zoom = 12) %>%
  addCircleMarkers(
    lng = ~longitud, lat = ~latitud,
    popup = ~paste0(
      "<b>Barrio:</b> ", barrio, "<br>",
      "<b>Tipo:</b> ", tipo, "<br>",
      "<b>Estrato:</b> ", estrato, "<br>",
      "<b>Precio (millones):</b> ", preciom
    ),
    radius = 6,
    color = "red",
    fillOpacity = 0.7
  )

Se identifica que hay puntos por todos lados, apesar que se aplico e filtro en el campo original Zona, y se dejaron solo los que tenian Zona Norte, esta variacion se puede deber a mala clasificación en la fuente y se hace necesario hacer una reclasificacion partiendo del campo Zona_N que fue el reclasificado con el el archivo shp que contenia los barrios.

shapefile_path <- "C:/Users/Admin/Downloads/barrios_cali/mc_barrios.shp"
barrios <- st_read(shapefile_path)
## Reading layer `mc_barrios' from data source 
##   `C:\Users\Admin\Downloads\barrios_cali\mc_barrios.shp' using driver `ESRI Shapefile'
## Simple feature collection with 337 features and 5 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1054098 ymin: 860192.1 xmax: 1068492 ymax: 879000.7
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
head(barrios)
## Simple feature collection with 6 features and 5 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1060939 ymin: 876841.6 xmax: 1066056 ymax: 879000.7
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
##   id_barrio                   barrio comuna shape_leng shape_area
## 1      0610       Ciudadela Floralia     06   4062.458   768879.6
## 2      0216                    Menga     02   3209.059   510671.1
## 3      0603        Paso del Comercio     06   3573.425   395204.9
## 4      0608            Los Guaduales     06   2572.876   364831.8
## 5      0298     Senderos de La Flora     02   2543.263   383903.1
## 6      0295 Urbanizaci\xf3n La Flora     02   3508.308   764278.0
##                         geometry
## 1 POLYGON ((1065621 878388, 1...
## 2 POLYGON ((1061113 878524.7,...
## 3 POLYGON ((1065906 878375.7,...
## 4 POLYGON ((1064226 877369.6,...
## 5 POLYGON ((1062233 878014.3,...
## 6 POLYGON ((1063068 877720.7,...
plot(barrios["geometry"])

Crea data.frame nueva solo con barrios del norte, clasificando solo las comunas 2, 4, 5 y 6 ubicadas al norte del municpio de Cali.

puntos_sf <- st_as_sf(base1, coords = c("longitud", "latitud"), crs = 4326) 
puntos_sf_trans <- st_transform(puntos_sf, st_crs(barrios))
puntos_sf_trans <- st_transform(puntos_sf, st_crs(barrios))
base1_con_barrios <- st_join(puntos_sf_trans, barrios)
base_comunas_sel <- base1_con_barrios %>%
  filter(comuna.x %in% c("02", "04", "05", "06"))
head(base_comunas_sel)
## Simple feature collection with 6 features and 18 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 1062325 ymin: 874247.4 xmax: 1065290 ymax: 877376.8
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
##     id       zona estrato preciom areaconst parqueaderos banios habitaciones
## 1 1212 Zona Norte       5     260        90            1      2            3
## 2 1209 Zona Norte       5     320       150            2      4            6
## 3 1592 Zona Norte       5     780       380            2      3            3
## 4  509 Zona Norte       6     820       377            1      4            4
## 5  238 Zona Norte       5     430       105            0      3            3
## 6  504 Zona Norte       3     180       120            0      3            3
##          tipo comuna.x barrio_old                     barrio.x zona_n id_barrio
## 1 Apartamento       04      acopi                     Porvenir  NORTE      0403
## 2        Casa       02      acopi       Urbanización La Merced  NORTE      0293
## 3        Casa       02      acopi        Urbanización La Flora  NORTE      0295
## 4 Apartamento       05      acopi     Los Parques Barranquilla  NORTE      0594
## 5 Apartamento       05      acopi Villa del Prado - El Guabito  NORTE      0599
## 6        Casa       05      acopi                    Los Andes  NORTE      0502
##                       barrio.y comuna.y shape_leng shape_area
## 1                     Porvenir       04   2216.520   292584.9
## 2    Urbanizaci\xf3n La Merced       02   2388.010   365166.2
## 3     Urbanizaci\xf3n La Flora       02   3508.308   764278.0
## 4     Los Parques Barranquilla       05   2527.581   292401.6
## 5 Villa del Prado - El Guabito       05   3913.389   786440.3
## 6                    Los Andes       05   2587.242   358874.9
##                   geometry
## 1 POINT (1062685 874247.4)
## 2 POINT (1062695 876544.1)
## 3 POINT (1062325 877376.8)
## 4 POINT (1064429 876206.9)
## 5 POINT (1065290 875273.6)
## 6 POINT (1064443 875540.1)

……………………………..

barrios <- st_read("C:/Users/Admin/Downloads/barrios_cali/mc_barrios.shp")
## Reading layer `mc_barrios' from data source 
##   `C:\Users\Admin\Downloads\barrios_cali\mc_barrios.shp' using driver `ESRI Shapefile'
## Simple feature collection with 337 features and 5 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1054098 ymin: 860192.1 xmax: 1068492 ymax: 879000.7
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
puntos_sf <- st_as_sf(base1, coords = c("longitud", "latitud"), crs = 4326)
puntos_sf <- st_transform(puntos_sf, st_crs(barrios))
base1_con_barrios <- st_join(puntos_sf, barrios)
base1_con_barrios$comuna.x <- as.character(base1_con_barrios$comuna.x)
base_comunas_sel <- base1_con_barrios %>%
  filter(comuna.x %in% c("02", "04", "05", "06"))
nrow(base_comunas_sel)        # Cantidad de puntos filtrados
## [1] 1488
head(base_comunas_sel)        # Primeras filas
## Simple feature collection with 6 features and 18 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 1062325 ymin: 874247.4 xmax: 1065290 ymax: 877376.8
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
##     id       zona estrato preciom areaconst parqueaderos banios habitaciones
## 1 1212 Zona Norte       5     260        90            1      2            3
## 2 1209 Zona Norte       5     320       150            2      4            6
## 3 1592 Zona Norte       5     780       380            2      3            3
## 4  509 Zona Norte       6     820       377            1      4            4
## 5  238 Zona Norte       5     430       105            0      3            3
## 6  504 Zona Norte       3     180       120            0      3            3
##          tipo comuna.x barrio_old                     barrio.x zona_n id_barrio
## 1 Apartamento       04      acopi                     Porvenir  NORTE      0403
## 2        Casa       02      acopi       Urbanización La Merced  NORTE      0293
## 3        Casa       02      acopi        Urbanización La Flora  NORTE      0295
## 4 Apartamento       05      acopi     Los Parques Barranquilla  NORTE      0594
## 5 Apartamento       05      acopi Villa del Prado - El Guabito  NORTE      0599
## 6        Casa       05      acopi                    Los Andes  NORTE      0502
##                       barrio.y comuna.y shape_leng shape_area
## 1                     Porvenir       04   2216.520   292584.9
## 2    Urbanizaci\xf3n La Merced       02   2388.010   365166.2
## 3     Urbanizaci\xf3n La Flora       02   3508.308   764278.0
## 4     Los Parques Barranquilla       05   2527.581   292401.6
## 5 Villa del Prado - El Guabito       05   3913.389   786440.3
## 6                    Los Andes       05   2587.242   358874.9
##                   geometry
## 1 POINT (1062685 874247.4)
## 2 POINT (1062695 876544.1)
## 3 POINT (1062325 877376.8)
## 4 POINT (1064429 876206.9)
## 5 POINT (1065290 875273.6)
## 6 POINT (1064443 875540.1)
base_comunas_sel_df <- base_comunas_sel %>% st_set_geometry(NULL)
print(dim(base_comunas_sel))
## [1] 1488   19

Se crea un mapa nuevo para verificar si la corrección que se realizó por barrio y por comuna es correcto.

base_comunas_sel_wgs <- st_transform(base_comunas_sel, crs = 4326)
base_comunas_sel_wgs <- base_comunas_sel_wgs %>%
  mutate(
    barrio.y = iconv(barrio.y, from = "", to = "UTF-8", sub = ""),
    tipo = iconv(tipo, from = "", to = "UTF-8", sub = "")
  )
pal <- colorFactor(palette = "Set1", domain = base_comunas_sel_wgs$comuna.x)

leaflet(base_comunas_sel_wgs) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(
    radius = 5,
    color = ~pal(comuna.x),
    fillOpacity = 0.8,
    popup = ~paste0(
      "ID: ", id, "<br>",
      "Tipo: ", tipo, "<br>",
      "Barrio: ", barrio.y, "<br>",
      "Comuna: ", comuna.x
    )
  ) %>%
  addLegend(
    "bottomright",
    pal = pal,
    values = ~comuna.x,
    title = "Comuna",
    opacity = 1
  )

Listados de barrios del Norte de Cali que se encuentra en la base.

base_comunas_sel$barrio.y <- iconv(base_comunas_sel$barrio.y,
                                   from = "latin1", to = "UTF-8")
conteo_barrios <- base_comunas_sel %>%
  st_set_geometry(NULL) %>%  # quitamos geometría para simplificar
  group_by(barrio = barrio.y) %>%
  summarise(n_registros = n()) %>%
  arrange(desc(n_registros))
conteo_barrios
## # A tibble: 69 × 2
##    barrio                       n_registros
##    <chr>                              <int>
##  1 La Flora                             127
##  2 Senderos de La Flora                 125
##  3 Urbanización La Flora                110
##  4 Prados del Norte                      92
##  5 Santa Mónica                          76
##  6 Villa del Prado - El Guabito          68
##  7 Brisas de Los Alamos                  66
##  8 San Vicente                           65
##  9 Torres de Comfandi                    60
## 10 Ciudad de Los Alamos                  51
## # ℹ 59 more rows

Correlación

  1. Se realiza 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.
datos_corr <- vivienda_1 %>%
  select(preciom, areaconst, estrato, banios, habitaciones, zona)
datos_corr$zona_num <- as.numeric(factor(datos_corr$zona))
matriz_corr <- cor(datos_corr %>% select(preciom, areaconst, estrato, banios, habitaciones), 
                   use = "complete.obs")
nombres_amigables <- c("Precio_Casa", "Area_Construida", "Estrato", "Banios", "Habitaciones")
colnames(matriz_corr) <- nombres_amigables
rownames(matriz_corr) <- nombres_amigables
print(matriz_corr)
##                 Precio_Casa Area_Construida     Estrato    Banios Habitaciones
## Precio_Casa       1.0000000       0.6873520  0.60980664 0.6691456   0.26409121
## Area_Construida   0.6873520       1.0000000  0.27432332 0.6484165   0.51691292
## Estrato           0.6098066       0.2743233  1.00000000 0.4203218  -0.07137615
## Banios            0.6691456       0.6484165  0.42032178 1.0000000   0.58990641
## Habitaciones      0.2640912       0.5169129 -0.07137615 0.5899064   1.00000000
corrplot(matriz_corr, method = "color", addCoef.col = "black", number.cex = 0.7)

Analisis de la data:

Precio_Casa: Se relaciona bastante con Area_Construida (0.69) y de manera moderada con Baños (0.67) y Estrato (0.61). Tiene poca relación con Habitaciones (0.26). El precio aumenta más según el tamaño y los baños que por el número de habitaciones.

Area_Construida: Se relaciona moderadamente con Baños (0.65) y Habitaciones (0.52). Relación baja con Estrato (0.27). Casas más grandes suelen tener más baños y habitaciones, pero no necesariamente un estrato más alto.

Estrato: Relación moderada con Precio_Casa (0.61) y Baños (0.42).Prácticamente no se relaciona con Habitaciones (-0.07). El estrato influye en el precio y los baños, pero no en las habitaciones.

Baños: Relación moderada con Habitaciones (0.59). Más baños suelen ir acompañados de más habitaciones.

Habitaciones: Se relaciona más con Baños (0.59) y Area_Construida (0.52).

Observación:

Se identifican en el momento que las variables más importantes para explicar el Precio_Casa son Area_Construida, Baños y Estrato.

Tambien las habitaciones tiene menor correlación con el precio, aunque se relaciona con área y baños.

No hay correlaciones extremadamente altas (>0.9), (No hay problema de multicolinealidad).

library(dplyr)
vivienda_1 %>%
  group_by(zona) %>%
  summarise(precio_prom = mean(preciom, na.rm = TRUE))
## # A tibble: 5 × 2
##   zona         precio_prom
##   <chr>              <dbl>
## 1 Zona Centro         310.
## 2 Zona Norte          346.
## 3 Zona Oeste          678.
## 4 Zona Oriente        229.
## 5 Zona Sur            427.

La Zona Oeste tiene el precio promedio más alto (678), mientras que la Zona Oriente es la más económica (229).

Las demás zonas (Centro, Norte y Sur) tienen precios intermedios, siendo la Zona Sur más cara, como se esperaba.

library(dplyr)
library(plotly)

plot_ly(
  data = vivienda_1,
  x = ~zona,
  y = ~preciom,
  type = "box",
  color = ~zona
) %>%
  layout(
    title = "Distribucion del Precio por Zona",
    xaxis = list(title = "Zona"),
    yaxis = list(title = "Precio (millones)")
  )

Observacion:

La zona Norte tiene muchos outliers, teniendo en cuenta que la mediana es de 300 millones, se visualizan viviendas de mas de 1800 millones.

Casi lo mismo le pasa en la zona sur, pero la mediana esta cerca de los 430 millones siendo mas costoso que el norte.

La zona oriente concentra los precios más bajos, mientras el centro esta en una promedio entre todas.

Estimacion del MOdelo para la Zona Norte, por regresión lineal múltiple

#vivienda_casas_N <-subset(base1, tipo=='Casa')
vivienda_casas_N <- subset(base1, tipo == "Casa" & zona_n == "NORTE")
mod_p1 <- lm(preciom ~ areaconst + estrato  + habitaciones + parqueaderos + banios, data= vivienda_casas_N)
summary(mod_p1)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = vivienda_casas_N)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -924.18  -66.95  -16.60   35.06 1107.53 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -170.84010   35.64048  -4.793 2.14e-06 ***
## areaconst       0.77882    0.05318  14.645  < 2e-16 ***
## estrato        71.49706    8.78042   8.143 2.87e-15 ***
## habitaciones    5.93136    5.12237   1.158  0.24742    
## parqueaderos   12.58900    4.77655   2.636  0.00865 ** 
## banios         14.28141    6.53460   2.186  0.02930 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 149.1 on 521 degrees of freedom
## Multiple R-squared:  0.6413, Adjusted R-squared:  0.6379 
## F-statistic: 186.3 on 5 and 521 DF,  p-value: < 2.2e-16

Información clave del modelo

Intercepto es de -170.81010, p < 0.001 (significativo), indicaria que si todas las variables al iniciar fueran 0 (cero) el valor seria -170 millones, que no tendria sentido, pero su finalidad es indicar un ajuste.

areaconst es el Área Construida de 0.77882 con un p < 0.001 (muy significativo), se podria interpretar como la pendiente de la variable de area, es decir por cada metro de area que aumente la construccion aumentaria 0.778 millones de pesos el valor del inmueble. Tiene a t con 14.645 siendo el predcitro mas fuerte.

estrato, con una estimador de 71.50 y p < 0.001 (muy significativo), indicaría que al aumentar el estrato del inmueble aumentaría su valor en 71.5 millones.

habitaciones, con un coeficiente de 5.93, p = 0.247 (no significativo), indicaría que por cada habitación que aumente, debería aumentar 5.93 millones su valor. Sin embargo, por ser poco significativo, se podria decir que el valor real esta es en el área y no en la cantidad de habitaciones aunque lo uno implique lo otro.

parqueaderos, coeficiente de 12.59, p = 0.0086 (significativo), indicaría que cada parqueadero adicional aumentaría el valor en 12.6 millones el valor del inmueble.

Baños, coeficiente 14.28, p = 0.029, (significativo), aumentaria el valor del inmueble 14.28 millones por cada baño adicional.

R² = 0.6413: Indica que aproximadamente el 64.13% de la variabilidad del precio se explica con las variables incluidas: areaconst (Area Construida), estrato, habitaciones, parqueaderos, banios (Baños).

R² ajustado = 0.6379, la diferencia entre el y R² es pequeña indicando que el modelo no está sobre ajustado.

Siendo asi, se puede decir que aun hay un 36% de la variablidad del precio que el modelo no explica.

Se podría estudiar mejoras al modelo ingresando mas variables com por ejemplo antiguedad de la construccion, los terminados, vias de acceso, parques.

Error estándar residual (RSE)

summary(mod_p1)$sigma  
## [1] 149.0795

Las predicciones del modelo se equivocan alrededor de 149 millones de pesos respecto al valor real. Mostraria que el modelo no es muy eficiente, teniendo en cuenta que la mayoría de las casas tienen precios entre 100 y 300 millones

MAE (Mean Absolute Error)

library(Metrics)
## Warning: package 'Metrics' was built under R version 4.4.3
rmse(vivienda_casas_N$preciom, mod_p1$fitted.values)
## [1] 148.2284

Las predicciones del modelo para las casas del Norte se desvían alrededor de 148 millones de pesos frente al precio real

Validación de supuestos del modelo e interpetación de resultados.

graficos <- plot(mod_p1, which = 1:2)

Grafico de Residuals vs Fitted:

La mayoría de los residuos están cerca de 0, entonces el modelo predice razonablemente bien para la mayoría de casas.

Hay pocos outliers con residuos grandes, que podrían influir mucho en los coeficientes.

Hay unos índices de la observación en los datos que tiene ese residuo específico alto, correspondientes a son posiblemente valores atípicas o outliers

Grafico de Q-Q plot (Quantile-Quantile plot):

La mayoría de los puntos siguen bastante bien la línea, entonces los residuales se comportan aproximadamente normales en el centro de la distribución.

Se ve que los residuales no cumplen perfectamente la normalidad, sobre todo en los extremos.

Test de Shapiro-Wilk

shapiro.test(mod_p1$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  mod_p1$residuals
## W = 0.78594, p-value < 2.2e-16

Se confirma lo que ya se veía en el Q-Q plot, los residuales no son normales, sobre todo por colas pesadas y outliers, pero como el objetivo es predicción, no es necesario hacer mas ajustes (Transformaciones, elimnar valores atipicos, etc.).

Test de Breusch-Pagan

bptest(mod_p1)
## 
##  studentized Breusch-Pagan test
## 
## data:  mod_p1
## BP = 108.46, df = 5, p-value < 2.2e-16

Indicaría que rechaza la hipótesis nula de homocedasticidad, es decir, los errores de tu modelo no tienen varianza constante, entonces existe heterocedasticidad.

La heterocedasticidad no sesga los coeficientes, afecta la precisión de los errores estándar, afectando solamente la inferencia.

Se podria trabajar una transformación logarítmica que estabilice la varianza.

Predicción del precio de la vivienda al Norte

Con los datos requeridos por el cliente se predice el precio de una vivienda al Norte con las siguientes caracteristicas: $ , Area =200 ,| ,parqueaderos=1,|,estrato = 4 ,o, 5,|, baños=2,|,habitaciones = 4 $.

## Prediccion
new_dat <- data.frame(
  areaconst = 200,
  parqueaderos = 1,
  estrato = c(4, 5),
  banios = 2,
  habitaciones = 4
)
predict(mod_p1,new_dat, level = 0.95, interval = "confidence")
##        fit      lwr      upr
## 1 335.7888 316.2518 355.3258
## 2 407.2858 378.6837 435.8880

Primera observación:

Valor estimado (fit) = 335.8

Intervalo de confianza al 95%: entre 316.3 y 355.3

Es decir: el modelo estima un precio alrededor de 335.8, y con 95% de confianza estaría en ese rango.

Segunda observación:

Valor estimado (fit) = 407.3

Intervalo de confianza al 95%: entre 378.7 y 435.9

Estimación más alta que la primera, pero también con un rango de incertidumbre.

Casas Valoradas según el Modelo
Estratos 4 y 5, con predicción > 350 y precio ≤ 350
id estrato preciom areaconst parqueaderos banios habitaciones comuna longitud latitud barrio_old barrio prediccion
4458 4 315.00 270.0 2 4 4 02 -76.53176 3.48780 el bosque El Bosque 431.46
2544 4 340.00 264.5 2 4 4 02 -76.52096 3.47665 vipasa Prados del Norte 427.17
952 4 330.00 275.0 2 3 5 04 -76.50647 3.47516 la merced Evaristo Garcia 427.00
937 4 350.00 280.0 2 3 4 04 -76.50603 3.46643 la merced Salomia 424.96
1822 4 340.00 295.0 2 2 4 02 -76.51777 3.48060 vipasa Vipasa 422.37
3101 5 340.00 355.0 2 5 8 02 -76.52377 3.46384 san vicente San Vicente 607.16
4209 5 350.00 300.0 3 5 6 02 -76.53010 3.48577 el bosque El Bosque 565.05
1943 5 350.00 346.0 1 2 4 02 -76.51847 3.47503 vipasa Prados del Norte 520.99
3453 5 340.00 240.0 2 5 6 02 -76.52640 3.48211 la campiña La Paz 505.73
3043 5 330.00 275.0 2 3 5 02 -76.52350 3.48329 la merced La Flora 498.50

Mapa con ofertas potenciales fruto de la prediccion

mapa <- st_read("C:/Users/Admin/Downloads/barrios_cali/mc_barrios.shp")
## Reading layer `mc_barrios' from data source 
##   `C:\Users\Admin\Downloads\barrios_cali\mc_barrios.shp' using driver `ESRI Shapefile'
## Simple feature collection with 337 features and 5 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1054098 ymin: 860192.1 xmax: 1068492 ymax: 879000.7
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
propuesta1 <- rbind(estrato4[1:5, ], estrato5[1:5, ])
puntos_sf <- st_as_sf(
  propuesta1,
  coords = c("longitud", "latitud"),   # 👈 pon aquí los nombres exactos
  crs = 4326
)
mapa <- st_transform(mapa, 4326)
ggplot() +
  geom_sf(data = mapa, fill = "white", color = "black", size = 0.2, alpha = 0.4) +
  geom_sf(data = puntos_sf, color = "red", size = 3) +
  ggtitle("Propuesta de casas en Zona norte")

CASO 2

library(tibble)
## Warning: package 'tibble' was built under R version 4.4.3
## 
## Adjuntando el paquete: 'tibble'
## The following object is masked from 'package:summarytools':
## 
##     view
viviendas <- tibble::tibble(
  Caracteristicas = c("Tipo", "Área construida", "Parqueaderos", "Baños", 
                      "Habitaciones", "Estrato", "Zona", "Crédito preaprobado"),
#  Vivienda_1 = c("Casa", "200", "1", "2", "4", "4 o 5", "Norte", "350 millones"),
  Vivienda_2 = c("Apartamento", "300", "3", "3", "5", "5 o 6", "Sur", "850 millones")
)
print(viviendas)
## # A tibble: 8 × 2
##   Caracteristicas     Vivienda_2  
##   <chr>               <chr>       
## 1 Tipo                Apartamento 
## 2 Área construida     300         
## 3 Parqueaderos        3           
## 4 Baños               3           
## 5 Habitaciones        5           
## 6 Estrato             5 o 6       
## 7 Zona                Sur         
## 8 Crédito preaprobado 850 millones

Se aplica FIltro ZOna Sur

base2 <- vivienda_1 %>% 
  filter(zona == "Zona Sur")
head(base2, 3)
##     id     zona estrato preciom areaconst parqueaderos banios habitaciones
## 1 5992 Zona Sur       4     400       280            3      5            3
## 2 5098 Zona Sur       4     290        96            1      2            3
## 3  698 Zona Sur       3      78        40            1      1            2
##          tipo comuna  longitud latitud barrio_old      barrio  zona_n
## 1        Casa     19 -76.54000 3.43500 3 de julio  3 de Julio     SUR
## 2 Apartamento     03 -76.53464 3.44987      acopi   La Merced  CENTRO
## 3 Apartamento     15 -76.50100 3.40000 aguablanca El Morichal ORIENTE
tabla_zona <- base2 %>%
  group_by(zona, tipo, estrato) %>%
  summarise(n_registros = n()) %>%
  arrange(desc(n_registros))
## `summarise()` has grouped output by 'zona', 'tipo'. You can override using the
## `.groups` argument.
tabla_zona
## # A tibble: 8 × 4
## # Groups:   zona, tipo [2]
##   zona     tipo        estrato n_registros
##   <chr>    <chr>         <dbl>       <int>
## 1 Zona Sur Apartamento       4        1091
## 2 Zona Sur Apartamento       5        1033
## 3 Zona Sur Casa              5         652
## 4 Zona Sur Casa              6         581
## 5 Zona Sur Casa              4         525
## 6 Zona Sur Apartamento       6         462
## 7 Zona Sur Apartamento       3         201
## 8 Zona Sur Casa              3         181

Mapeo de la Zona Sur

# Normalizar base
base_clean <- base2
base_clean[] <- lapply(base_clean, function(x) {
  if (is.character(x)) {
    # Forzar a UTF-8, 
    enc2utf8(iconv(x, from = "", to = "UTF-8", sub = ""))
  } else {
    x
  }
})

# Crear el mapa
leaflet(base_clean) %>%
  addProviderTiles("CartoDB.Positron") %>%
  setView(lng = -76.532, lat = 3.4516, zoom = 12) %>%
  addCircleMarkers(
    lng = ~longitud, lat = ~latitud,
    popup = ~paste0(
      "<b>Barrio:</b> ", barrio, "<br>",
      "<b>Tipo:</b> ", tipo, "<br>",
      "<b>Estrato:</b> ", estrato, "<br>",
      "<b>Precio (millones):</b> ", preciom
    ),
    radius = 6,
    color = "green",
    fillOpacity = 0.7
  )
puntos_sf <- st_as_sf(base2, coords = c("longitud", "latitud"), crs = 4326) 
puntos_sf_trans <- st_transform(puntos_sf, st_crs(barrios))
puntos_sf_trans <- st_transform(puntos_sf, st_crs(barrios))
base2_con_barrios <- st_join(puntos_sf_trans, barrios)
base_comunas_sel <- base2_con_barrios %>%
  filter(comuna.x %in% c("16", "17", "18", "22" ))
head(base_comunas_sel)
## Simple feature collection with 6 features and 18 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: 1058295 ymin: 864637.1 xmax: 1060407 ymax: 868286.1
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
##     id     zona estrato preciom areaconst parqueaderos banios habitaciones
## 1 7139 Zona Sur       3     240        75            0      3            5
## 2 6975 Zona Sur       4     220        75            1      2            3
## 3 7396 Zona Sur       3     115        58            1      2            2
## 4 6949 Zona Sur       4     220        84            0      2            3
## 5 7946 Zona Sur       3     230        63            1      2            2
## 6 4941 Zona Sur       5     500       320            2      8            9
##          tipo comuna.x       barrio_old                    barrio.x zona_n
## 1        Casa       18    alférez real Francisco Eladio Ram\xedrez    SUR
## 2 Apartamento       18    alférez real             Alf\xe9rez Real    SUR
## 3 Apartamento       18    alférez real             Alf\xe9rez Real    SUR
## 4 Apartamento       18     alferez real             Alf\xe9rez Real    SUR
## 5 Apartamento       18      alto jordán                  Polvorines    SUR
## 6        Casa       17 bella suiza alta             Primero de Mayo    SUR
##   id_barrio                    barrio.y comuna.y shape_leng shape_area
## 1      1807 Francisco Eladio Ram\xedrez       18   1560.608   121173.3
## 2      1813             Alf\xe9rez Real       18   2612.684   225908.0
## 3      1813             Alf\xe9rez Real       18   2612.684   225908.0
## 4      1813             Alf\xe9rez Real       18   2612.684   225908.0
## 5      1891                  Polvorines       18   4831.996   860023.6
## 6      1702             Primero de Mayo       17   2400.660   308867.3
##                   geometry
## 1 POINT (1058869 866452.8)
## 2   POINT (1059043 866748)
## 3 POINT (1058713 866761.3)
## 4 POINT (1059073 866627.5)
## 5 POINT (1058295 864637.1)
## 6 POINT (1060407 868286.1)
print(dim(base_comunas_sel))
## [1] 3259   19

Se crea un mapa nuevo para verificar si la corrección que se realizó por barrio y por comuna es correcto.

base_comunas_sel_wgs <- st_transform(base_comunas_sel, crs = 4326)
base_comunas_sel_wgs <- base_comunas_sel_wgs %>%
  mutate(
    barrio.y = iconv(barrio.y, from = "", to = "UTF-8", sub = ""),
    tipo = iconv(tipo, from = "", to = "UTF-8", sub = "")
  )
pal <- colorFactor(palette = "Set1", domain = base_comunas_sel_wgs$comuna.x)

leaflet(base_comunas_sel_wgs) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addCircleMarkers(
    radius = 5,
    color = ~pal(comuna.x),
    fillOpacity = 0.8,
    popup = ~paste0(
      "ID: ", id, "<br>",
      "Tipo: ", tipo, "<br>",
      "Barrio: ", barrio.y, "<br>",
      "Comuna: ", comuna.x
    )
  ) %>%
  addLegend(
    "bottomright",
    pal = pal,
    values = ~comuna.x,
    title = "Comuna",
    opacity = 1
  )

Se aplica el filtro de apartamento en el SUR y se crea el modelo

vivienda_casas_S <- subset(base2, tipo == "Apartamento" & zona_n == "SUR")
mod_p2 <- lm(preciom ~ areaconst + parqueaderos + estrato + banios + habitaciones, data= vivienda_casas_S)
summary(mod_p2)
## 
## Call:
## lm(formula = preciom ~ areaconst + parqueaderos + estrato + banios + 
##     habitaciones, data = vivienda_casas_S)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1140.93   -45.25    -2.62    36.71   943.17 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -226.3976    15.3773 -14.723  < 2e-16 ***
## areaconst       1.3310     0.0536  24.831  < 2e-16 ***
## parqueaderos   56.7177     3.5222  16.103  < 2e-16 ***
## estrato        57.2788     3.1609  18.121  < 2e-16 ***
## banios         50.6701     3.4345  14.753  < 2e-16 ***
## habitaciones  -23.0842     3.8126  -6.055 1.64e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 97.61 on 2328 degrees of freedom
## Multiple R-squared:  0.7467, Adjusted R-squared:  0.7462 
## F-statistic:  1373 on 5 and 2328 DF,  p-value: < 2.2e-16

Información clave del modelo

Intercepto es de -226.40, p < 0.001 (significativo), indicaria que si todas las variables al iniciar fueran 0 (cero) el valor seria -226.4 millones, que no tendria sentido, pero su finalidad es indicar un ajuste.

areaconst es el Área Construida de 1.33 con un p < 0.001 (muy significativo), se podria interpretar como la pendiente de la variable de area, es decir por cada metro de area que aumente la construcción aumentaría 1.33 millones de pesos el valor del inmueble. Tiene a t con 24.831 siendo el coeficiente mas fuerte.

estrato, con una estimador de 57.28 y p < 0.001 (muy significativo), indicaría que al aumentar el estrato del inmueble aumentaría su valor en 56.28 millones.

habitaciones, con un coeficiente de -23.08, p = 0.001 (significativo), indicaría que por cada habitación que disminuye, debería bajar 23.08 millones su valor. Sin embargo, se podría decir que el valor real baja si mantiene la misma area y hacer mas habitacines.

parqueaderos, coeficiente de 56.79, p = 0.001 (significativo), indicaría que cada parqueadero adicional aumentaría el valor en 56.79 millones el valor del inmueble.

Baños, coeficiente 50.67, p = 0.001, (significativo), aumentaria el valor del inmueble 50.67 millones por cada baño adicional.

R² = 0.747: Indica que aproximadamente el 74.7% de la variabilidad del precio se explica con las variables incluidas: areaconst (Area Construida), estrato, habitaciones, parqueaderos, banios (Baños).

R² ajustado = 0.7462, la diferencia entre el y R² es pequeña indicando que el modelo no está sobre ajustado.

Siendo asi, se puede decir que aun hay un 26% de la variablidad del precio que el modelo no explica.

Se podría estudiar mejoras al modelo ingresando mas variables com por ejemplo antiguedad de la construccion, los terminados, vias de acceso, parques.

Error estándar residual (RSE)

summary(mod_p2)$sigma  
## [1] 97.60691

Las predicciones del modelo se equivocan alrededor de 97.6 millones de pesos respecto al valor real. Mostraria que el modelo no es muy eficiente, teniendo en cuenta que la mayoria de las casas tienen precios entre 100 y 300 millones

MAE (Mean Absolute Error)

library(Metrics)
rmse(vivienda_casas_N$preciom, mod_p2$fitted.values)
## Warning in actual - predicted: longitud de objeto mayor no es múltiplo de la
## longitud de uno menor
## [1] 318.5021

Las predicciones del modelo para las casas del Norte se desvían alrededor de 318 millones de pesos frente al precio real

Validación de supuestos del modelo e interpetación de resultados.

graficos <- plot(mod_p2, which = 1:2)

Grafico de Residuals vs Fitted:

Se ve que para valores ajustados pequeños (izquierda) los residuos están bien distribuidos, pero a medida que el valor ajustado aumenta, aparece cierta curvatura y dispersión creciente. Esto sugiere heterocedasticidad (la varianza de los errores no es constante).

La leve curvatura ascendente al final, lo que indica que el modelo podría no estar captando toda la relación lineal en los precios más altos.

Hay pocos outliers con residuos grandes, que podrían influir mucho en los coeficientes.

Hay unos índices de la observación en los datos que tiene ese residuo específico alto, correspondientes a son posiblemente valores atípicas o outliers

Grafico de Q-Q plot (Quantile-Quantile plot):

En el centro (valores intermedios) los puntos siguen bastante bien la línea, lo que es positivo.

Las colas (extremos izquierdo y derecho), los puntos se alejan mucho de la recta, esto indica que los residuos tienen una distribución con colas más pesadas que la normal (probablemente curtosis alta).

Test de Shapiro-Wilk

shapiro.test(mod_p2$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  mod_p2$residuals
## W = 0.78755, p-value < 2.2e-16

La hipótesis nula del test es que los residuos siguen una distribución normal.

Como el p-valor es extremadamente bajo (< 0.05), rechazamos la normalidad → los residuos no son normales.

Esto confirma lo del gráfico Q-Q: los residuos se desvían de la línea recta en las colas, entonces hay colas pesadas y outliers.

Se debería hacer Transformacion de la variable dependiente

Test de Breusch-Pagan

bptest(mod_p2)
## 
##  studentized Breusch-Pagan test
## 
## data:  mod_p2
## BP = 796.04, df = 5, p-value < 2.2e-16

La hipótesis nula es que los residuos tienen varianza constante (homocedasticidad).

Como el p-valor es muy bajo, rechazamos H₀ → hay heterocedasticidad en tu modelo.

Se podria mejorar haciendo una transformación de la variable dependiente, usualmente se hace con unlogaritmo.

Predicción del precio de la vivienda al Norte

Con los datos requeridos por el cliente se predice el precio de una vivienda (apartamento) al Sur con las siguientes caracteristicas: $ , Area =300 ,| ,parqueaderos= 3,|,estrato = 5 ,o, 6,|, baños=3,|,habitaciones = 5 $.

## Prediccion 2
new_dat <- data.frame(
  areaconst = 300,
  parqueaderos = 3,
  estrato = c(5, 6),
  banios = 3,
  habitaciones = 5
)
predict(mod_p2,new_dat, level = 0.95, interval = "confidence")
##        fit      lwr      upr
## 1 666.0273 643.6098 688.4447
## 2 723.3061 700.6062 746.0059

Primera observación:

Valor estimado (fit) = 666.02

Intervalo de confianza al 95%: entre 643.6 y 688.4

Es decir: el modelo estima un precio alrededor de 666, y con 95% de confianza estaría en ese rango.

Segunda observación:

Valor estimado (fit) = 723.3

Intervalo de confianza al 95%: entre 700.6 y 746.0

El intervalo es más informativo que el valor puntual, porque refleja la incertidumbre en la estimación.

Intervalos relativamente estrechos (como estos) sugieren que el modelo tiene buena precisión para esas predicciones.

vivienda_casas_S$prediccion <- mod_p2$fitted.values
estrato5a <- vivienda_casas_S %>% 
  filter(preciom <= 850, prediccion > 850, estrato == 5, parqueaderos > 0) %>%
  select(-zona, -zona_n, -tipo) %>%
  arrange(desc(prediccion))

estrato6 <- vivienda_casas_S %>% 
  filter(preciom <= 850, prediccion > 850, estrato == 6, parqueaderos > 0) %>%
  select(-zona, -zona_n, -tipo) %>%
  arrange(desc(prediccion))

top_estrato5a <- head(estrato5a, 5)
top_estrato6 <- head(estrato6, 5)

tabla_final <- rbind(top_estrato5a, top_estrato6)

tabla_final %>%
  gt() %>%
  tab_header(
    title = "Casas Valoradas según el Modelo Sur",
    subtitle = "Estratos 5 y 6, con predicción > 850 y precio ≤ 850"
  ) %>%
  fmt_number(
    columns = c(preciom, prediccion),
    decimals = 2
  ) %>%
  tab_style(
    style = cell_fill(color = "lightblue", alpha = 0.3),
    locations = cells_body(columns = prediccion)
  )
Casas Valoradas según el Modelo Sur
Estratos 5 y 6, con predicción > 850 y precio ≤ 850
id estrato preciom areaconst parqueaderos banios habitaciones comuna longitud latitud barrio_old barrio prediccion
6121 5 299.00 932 1 3 3 17 -76.54087 3.37348 valle del lili Unicentro Cali 1,439.93
7182 5 730.00 573 3 8 5 19 -76.54800 3.40800 guadalupe Cuarto de Legua - Guadalupe 1,282.73
4952 5 650.00 600 2 4 5 17 -76.53400 3.38100 el ingenio El Ingenio 1,059.27
6472 5 170.00 605 1 2 2 17 -76.54294 3.39992 el limonar El Gran Limonar 977.12
4394 5 690.00 486 2 4 4 17 -76.53111 3.38292 el ingenio El Ingenio 930.62
5574 6 850.00 352 4 3 3 22 -76.53729 3.34265 pance Parcelaciones Pance 895.40

Mapa con ofertas potenciales fruto de la prediccion

mapa <- st_read("C:/Users/Admin/Downloads/barrios_cali/mc_barrios.shp")
## Reading layer `mc_barrios' from data source 
##   `C:\Users\Admin\Downloads\barrios_cali\mc_barrios.shp' using driver `ESRI Shapefile'
## Simple feature collection with 337 features and 5 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1054098 ymin: 860192.1 xmax: 1068492 ymax: 879000.7
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
propuesta2 <- rbind(estrato5a[1:5, ], estrato6[1:5, ])
propuesta2 <- propuesta2 %>%
  filter(!is.na(longitud), !is.na(latitud))
puntos_sf <- st_as_sf(
  propuesta2,
  coords = c("longitud", "latitud"),
  crs = 4326
)
mapa <- st_transform(mapa, 4326)
ggplot() +
  geom_sf(data = mapa, fill = "white", color = "black", size = 0.2, alpha = 0.4) +
  geom_sf(data = puntos_sf, color = "red", size = 3) +
  ggtitle("Propuesta de casas en Zona Sur")