INTRODUCCION

El presente informe tiene como objetivo realizar un análisis multidimensional del mercado inmobiliario para apoyar la toma de decisiones estratégicas.

METODOLOGIA

Se utilizó una base de datos con ofertas de vivienda, realizando una limpieza de valores nulos para garantizar la calidad del análisis.

if(!require(remotes)) install.packages("remotes")
## Cargando paquete requerido: remotes
remotes::install_github("centromagis/paqueteMODELOS", force = TRUE)
## Downloading GitHub repo centromagis/paqueteMODELOS@HEAD
## stringi (1.8.7 -> 1.8.9) [CRAN]
## rlang   (1.2.0 -> 1.3.0) [CRAN]
## Rcpp    (1.1.1 -> 1.1.2) [CRAN]
## xfun    (0.57  -> 0.60 ) [CRAN]
## Installing 4 packages: stringi, rlang, Rcpp, xfun
## Installing packages into 'C:/Users/jstorresm12/AppData/Local/R/win-library/4.4'
## (as 'lib' is unspecified)
## 
##   There are binary versions available but the source versions are later:
##         binary source needs_compilation
## stringi  1.8.7  1.8.9              TRUE
## rlang    1.2.0  1.3.0              TRUE
## Rcpp     1.1.1  1.1.2              TRUE
## xfun      0.57   0.60              TRUE
## 
##   Binaries will be installed
## package 'stringi' successfully unpacked and MD5 sums checked
## package 'rlang' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'rlang'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problema al copiar
## C:\Users\jstorresm12\AppData\Local\R\win-library\4.4\00LOCK\rlang\libs\x64\rlang.dll
## a
## C:\Users\jstorresm12\AppData\Local\R\win-library\4.4\rlang\libs\x64\rlang.dll:
## Permission denied
## Warning: restored 'rlang'
## package 'Rcpp' successfully unpacked and MD5 sums checked
## package 'xfun' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'xfun'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problema al copiar
## C:\Users\jstorresm12\AppData\Local\R\win-library\4.4\00LOCK\xfun\libs\x64\xfun.dll
## a C:\Users\jstorresm12\AppData\Local\R\win-library\4.4\xfun\libs\x64\xfun.dll:
## Permission denied
## Warning: restored 'xfun'
## 
## The downloaded binary packages are in
##  C:\Users\jstorresm12\AppData\Local\Temp\RtmpEVnna9\downloaded_packages
## ── R CMD build ─────────────────────────────────────────────────────────────────
## WARNING: Rtools is required to build R packages, but is not currently installed.
## 
## Please download and install Rtools 4.4 from https://cran.r-project.org/bin/windows/Rtools/.
##          checking for file 'C:\Users\jstorresm12\AppData\Local\Temp\RtmpEVnna9\remotes27ec7f384914\Centromagis-paqueteMODELOS-3b06257/DESCRIPTION' ...  ✔  checking for file 'C:\Users\jstorresm12\AppData\Local\Temp\RtmpEVnna9\remotes27ec7f384914\Centromagis-paqueteMODELOS-3b06257/DESCRIPTION' (3.2s)
##       ─  preparing 'paqueteMODELOS': (1.2s)
##    checking DESCRIPTION meta-information ...  ✔  checking DESCRIPTION meta-information
##       ─  checking for LF line-endings in source and make files and shell scripts (1.5s)
##       ─  checking for empty or unneeded directories
##       ─  building 'paqueteMODELOS_0.1.0.tar.gz'
##      
## 
## Installing package into 'C:/Users/jstorresm12/AppData/Local/R/win-library/4.4'
## (as 'lib' is unspecified)
library(paqueteMODELOS)
## Cargando paquete requerido: boot
## Cargando paquete requerido: broom
## Cargando paquete requerido: GGally
## Cargando paquete requerido: ggplot2
## Cargando paquete requerido: gridExtra
## Cargando paquete requerido: knitr
## Cargando paquete requerido: summarytools
# Cargue de datos
data("vivienda") 
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>

1. ANALISIS DE COMPONENTES PRINCIPALES

1.1. Exploracion y limpieza de datos

library(dplyr)
## 
## Adjuntando el paquete: '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(tidyr)

cat("Valores faltantes por variable:\n")
## Valores faltantes por variable:
colSums(is.na(vivienda))
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3         2638            3            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##         1605            3            3            3            3            3 
##      latitud 
##            3
vivienda_limpia <- vivienda %>% drop_na()

cat("\nTotal de observaciones después de limpiar:\n")
## 
## Total de observaciones después de limpiar:
nrow(vivienda_limpia)
## [1] 4808

1.2. PCA

if(!require(factoextra)) install.packages("factoextra")
## Cargando paquete requerido: factoextra
## Welcome to factoextra!
## Want to learn more? See two factoextra-related books at https://www.datanovia.com/library/principal-component-methods
library(factoextra)

# Seleccion de variables numéricas de interés
vivienda_pca_data <- vivienda_limpia %>%
  select(preciom, areaconst, estrato, parqueaderos, banios, habitaciones)

res_pca <- prcomp(vivienda_pca_data, scale. = TRUE)

summary(res_pca)
## Importance of components:
##                           PC1    PC2     PC3     PC4     PC5     PC6
## Standard deviation     1.8866 1.0884 0.69530 0.58528 0.49647 0.42886
## Proportion of Variance 0.5932 0.1974 0.08057 0.05709 0.04108 0.03065
## Cumulative Proportion  0.5932 0.7906 0.87117 0.92827 0.96935 1.00000
fviz_eig(res_pca, addlabels = TRUE, ylim = c(0, 60))

# Círculo de correlaciones de variables
fviz_pca_var(res_pca,
             col.var = "contrib", # Colorear según su contribución
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
             repel = TRUE)        # Evitar sobreposición de texto

El grupo principal (Correlación Positiva): Las flechas de preciom, parqueaderos, banios y areaconst están muy juntas y apuntan en la misma dirección. Esto significa que están fuertemente correlacionadas. En términos de negocio: a mayor área construida, las viviendas tienden a tener más baños, más parqueaderos y, en consecuencia, un precio mayor. El eje horizontal (Dim1) explica el 59.3% de la información total. Como todas las flechas apuntan hacia la derecha de este eje, se puede analizar que la Dimensión 1 como el “Tamaño y Valor” de la propiedad. El estrato apunta hacia arriba (Dim2 positiva) y habitaciones apunta hacia abajo (Dim2 negativa). El hecho de que estén casi separadas por un ángulo de 90 grados indica que no tienen mucha relación entre sí. Es decir, un estrato alto no garantiza que la casa tenga muchas habitaciones.

2. ANALISIS DE CONGLOMERADOS

Usando el algoritmo de K-Means

#  número de clusters (Método del codo)

fviz_nbclust(scale(vivienda_pca_data), kmeans, method = "wss") +
  labs(title = "Método del Codo para determinar Clusters")

set.seed(123)
res_kmeans <- kmeans(scale(vivienda_pca_data), centers = 3, nstart = 25)

fviz_cluster(res_kmeans, data = scale(vivienda_pca_data),
             geom = "point", 
             ellipse.type = "convex", 
             ggtheme = theme_minimal(),
             main = "Segmentación del Mercado Inmobiliario")

Cluster 3 (Cuadrados azules - Izquierda): Representa el segmento de viviendas económicas. Tienen valores negativos en la Dimensión 1, lo que indica que son propiedades con menor precio, menor área construida, y menos comodidades (baños/parqueaderos).

Cluster 1 (Círculos rojos - Centro): Es el segmento medio del mercado. Propiedades con características y precios promedio.

Cluster 2 (Triángulos verdes - Derecha): Representa el segmento de lujo o de alto valor. Tienen valores fuertemente positivos en la Dimensión 1, indicando que son las propiedades más caras, grandes y con mayores comodidades.

3. ANALISIS DE CORRESPONDENCIA

Nota: La variable barrio suele tener muchísimas categorías distintas, lo que hace que los gráficos sean imposibles de leer. Por tanto, graficaremos la relación principal entre tipo y zona, que da una visión macro muy clara para la empresa.

if(!require(FactoMineR)) install.packages("FactoMineR")
## Cargando paquete requerido: FactoMineR
library(FactoMineR)

# variables categóricas principales (Tipo y Zona)
vivienda_cat <- vivienda_limpia %>% 
  select(tipo, zona) %>% 
  mutate(across(everything(), as.factor))

res_mca <- MCA(vivienda_cat, graph = FALSE)

fviz_mca_var(res_mca, 
             repel = TRUE, 
             col.var = "blue",
             shape.var = 15,
             ggtheme = theme_minimal(),
             title = "Relación entre Tipo de Vivienda y Zona")

Apartamento está fuertemente agrupado a la izquierda con Zona Oeste y Zona Norte. Esto nos indica que la oferta inmobiliaria en estas zonas está dominada por apartamentos. El punto de Casa está más cercano al centro y se orienta hacia la Zona Sur. Esto sugiere que si un cliente busca una casa, la mayor probabilidad de encontrarla (o la mayor concentración de esta oferta) está en el sur de la ciudad. Las zonas centro y oriente estan muy alejadas del resto, lo que significa que tienen un comportamiento “atípico” o una oferta mucho menor en comparación con los grandes bloques del Norte/Oeste.

4. VISUALIZACION DE RESULTADOS

A continuacion se presenta un mapa interactivo con las ubicaciones de casas y apartamentos (Casas azules, Apartamentos rojos), donde se puede hacer zoon y dar clic en los puntos para que muestre la informacion del inmueble

if(!require(leaflet)) install.packages("leaflet")
## Cargando paquete requerido: leaflet
library(leaflet)
library(dplyr)

set.seed(123)
vivienda_mapa <- vivienda_limpia %>% sample_n(1000)

mapa_inmobiliario <- leaflet(vivienda_mapa) %>%
  addTiles() %>% 
  addCircleMarkers(
    lng = ~longitud, 
    lat = ~latitud,
    radius = 4,
    color = ~ifelse(tipo == "Casa", "blue", "red"), 
    stroke = FALSE, 
    fillOpacity = 0.7,
    popup = ~paste("<b>Tipo:</b>", tipo, "<br>",
                   "<b>Precio:</b> $", preciom, "M<br>",
                   "<b>Barrio:</b>", barrio, "<br>",
                   "<b>Zona:</b>", zona)
  )

mapa_inmobiliario

CONCLUSIONES

Recomendaciones para la Inmobiliaria: