Cargamos la base de datos (una única vez)

#devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
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>

Cargamos las librerias que vamos a utilizar

# Carga de librerías a usar

library(tidyverse)      # Manipulación de datos y gráficas (ggplot2)
library(FactoMineR)     # Para PCA y Análisis de Correspondencia
library(factoextra)     # Para gráficas de los modelos multivariados
library(cluster)        # Para algoritmos de agrupamiento
library(corrplot)       # Para visualizar matrices de correlación
library(knitr)
library(psych)

Análisis Exploratorio de Datos (EDA)

Damos una primera vista de los datos

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>

Vemos las dimensiones del dataset

El numero de registros (filas) y el numero de variables (columnas)

dim(vivienda)
## [1] 8322   13

Análisis de la Calidad de Datos

Estructura de tipos de Datos

En este primer acercamiento, visualizamos la naturaleza de cada columna para entender cómo R está interpretando la información.

knitr::kable(
  data.frame(
    Variable = names(vivienda),
    Tipo = sapply(vivienda, class)
  ),
  caption = "Tipos de variables"
)
Tipos de variables
Variable Tipo
id id numeric
zona zona character
piso piso character
estrato estrato numeric
preciom preciom numeric
areaconst areaconst numeric
parqueaderos parqueaderos numeric
banios banios numeric
habitaciones habitaciones numeric
tipo tipo character
barrio barrio character
longitud longitud numeric
latitud latitud numeric

Observa que variables como zona, piso, tipo y barrio aparecen como character (texto), mientras que el resto son numeric (números).

Resumen estadístico inicial

Para obtener una visión general de las características estadísticas de las variables, utilizamos la función describe() del paquete psych. Esta herramienta es fundamental en el análisis multivariado para identificar la dispersión y forma de nuestros datos.

# Resumen estadístico detallado
describe(vivienda)
##              vars    n    mean      sd  median trimmed     mad    min     max
## id              1 8319 4160.00 2401.63 4160.00 4160.00 3083.81   1.00 8319.00
## zona*           2 8319    3.92    1.33    5.00    4.04    0.00   1.00    5.00
## piso*           3 5684    3.77    2.61    3.00    3.37    1.48   1.00   12.00
## estrato         4 8319    4.63    1.03    5.00    4.67    1.48   3.00    6.00
## preciom         5 8320  433.89  328.65  330.00  374.43  207.56  58.00 1999.00
## areaconst       6 8319  174.93  142.96  123.00  149.15   84.51  30.00 1745.00
## parqueaderos    7 6717    1.84    1.12    2.00    1.62    1.48   1.00   10.00
## banios          8 8319    3.11    1.43    3.00    2.99    1.48   0.00   10.00
## habitaciones    9 8319    3.61    1.46    3.00    3.41    1.48   0.00   10.00
## tipo*          10 8319    1.39    0.49    1.00    1.36    0.00   1.00    2.00
## barrio*        11 8319  241.48  128.83  251.00  245.34  171.98   1.00  436.00
## longitud       12 8319  -76.53    0.02  -76.53  -76.53    0.02 -76.59  -76.46
## latitud        13 8319    3.42    0.04    3.42    3.42    0.05   3.33    3.50
##                range  skew kurtosis    se
## id           8318.00  0.00    -1.20 26.33
## zona*           4.00 -0.59    -1.36  0.01
## piso*          11.00  1.28     1.05  0.03
## estrato         3.00 -0.18    -1.11  0.01
## preciom      1941.00  1.85     3.67  3.60
## areaconst    1715.00  2.69    12.91  1.57
## parqueaderos    9.00  2.33     8.31  0.01
## banios         10.00  0.93     1.13  0.02
## habitaciones   10.00  1.63     3.98  0.02
## tipo*           1.00  0.46    -1.78  0.01
## barrio*       435.00 -0.09    -1.23  1.41
## longitud        0.13  0.65     0.58  0.00
## latitud         0.16  0.03    -1.15  0.00

Errores de escritura y estructura

El objetivo es confirmar que no existan inconsistencias en el formato de las variables que impidan su procesamiento posterior.

ESTRUCTURA DEL DATAFRAME VIVIENDA

Utilizamos la función str() para confirmar el almacenamiento de los 8,322 registros y sus 13 variables.

# Muestra el tipo de cada variable: numérica, carácter, etc.
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")=
##   .. cols(
##   ..   id = col_double(),
##   ..   zona = col_character(),
##   ..   piso = col_character(),
##   ..   estrato = col_double(),
##   ..   preciom = col_double(),
##   ..   areaconst = col_double(),
##   ..   parqueaderos = col_double(),
##   ..   banios = col_double(),
##   ..   habitaciones = col_double(),
##   ..   tipo = col_character(),
##   ..   barrio = col_character(),
##   ..   longitud = col_double(),
##   ..   latitud = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>

ANALISIS DE ESTE PASO

Variables Críticas:

Al revisar el describe(), notamos que preciom y areaconst tienen rangos muy amplios. Esto es un indicio de que necesitaremos estandarizar los datos antes del Análisis de Componentes Principales (PCA).

Variables Categóricas:

La función str() nos confirma que tenemos información de ubicación (zona, barrio) y tipo de inmueble que serán necesarios más adelante. Igualmente se observa que no hay errores de escritura.

Análisis de Datos Faltantes (NA´s)

Los datos faltantes ocurren cuando no se dispone de información para una observación en una variable específica. Identificarlos es el primer paso del diagnóstico de calidad, ya que la presencia de muchos vacíos puede sesgar los resultados

VISUALIZACION DE NULOS

# Contamos los valores NA por cada columna
faltantes <- colSums(is.na(vivienda))

# Creamos un dataframe para que la tabla en el reporte se vea limpia
tabla_faltantes <- data.frame(
  Variable = names(faltantes),
  Datos_Faltantes = faltantes
)

# Mostramos la tabla
knitr::kable(tabla_faltantes, caption = "Conteo de valores faltantes por variable")
Conteo de valores faltantes por variable
Variable Datos_Faltantes
id id 3
zona zona 3
piso piso 2638
estrato estrato 3
preciom preciom 2
areaconst areaconst 3
parqueaderos parqueaderos 1605
banios banios 3
habitaciones habitaciones 3
tipo tipo 3
barrio barrio 3
longitud longitud 3
latitud latitud 3

GRAFICO

# Gráfico de barras de datos faltantes
barplot(faltantes, 
        main = "Distribución de Datos Faltantes", 
        col = "firebrick", 
        las = 2, 
        cex.names = 0.7,
        ylab = "Cantidad de Nulos")

ANALISIS DE ESTE PASO

Al observar los resultados, podemos notar lo siguiente:

Variables Críticas:

  • Vemos que las variables “piso” (2,638) y “parqueaderos” (1,605) presentan la mayor cantidad de nulos.

  • En el caso de “piso”, la ausencia de datos es común en casas (donde el concepto de “piso” puede no aplicar igual al no estar en un edificio).

  • Contamos con variables como: “id”, “zona”, “estrato”, “preciom” y “areaconst” que están prácticamente completas, lo cual es importante ya que son la base para el análisis de precios.

La presencia de valores faltantes puede afectar la validez de los análisis estadísticos y de los modelos predictivos, por esto es importante tomarlos en consideracion y cuantificarlos

Tratamiento de Datos: Imputación de Valores Faltantes

JUSTIFICACION

En el análisis multivariado, especialmente en el PCA y Cluster, se requiere que la matriz de datos esté completa. Dado que las variables “piso” y “parqueaderos” presentan un alto volumen de valores nulos, optar por la eliminación de filas reduciría nuestra muestra de 8,322 a solo 4,808 registros.

  • Para conservar la potencia estadística del estudio, aplicaremos una imputación por la mediana para las variables numéricas. La mediana es preferible al promedio en datos inmobiliarios porque no se ve afectada por valores extremos (propiedades de lujo).

  • Para la variable piso, se asignará el valor “1” bajo el supuesto de que muchas casas no reportan este dato por ser de un solo nivel.

# Creamos una copia de la base para no alterar la original
vivienda_final <- vivienda

# Imputación de variables numéricas con la mediana
vivienda_final$parqueaderos[is.na(vivienda_final$parqueaderos)] <- median(vivienda_final$parqueaderos, na.rm = TRUE)
vivienda_final$banios[is.na(vivienda_final$banios)] <- median(vivienda_final$banios, na.rm = TRUE)
vivienda_final$habitaciones[is.na(vivienda_final$habitaciones)] <- median(vivienda_final$habitaciones, na.rm = TRUE)
vivienda_final$estrato[is.na(vivienda_final$estrato)] <- median(vivienda_final$estrato, na.rm = TRUE)

# Imputación de variable 'piso' (categórica)
vivienda_final$piso[is.na(vivienda_final$piso)] <- "1"

# Verificación de que ya no existan NAs
sum(is.na(vivienda_final))
## [1] 23
# Calculamos los faltantes en la base NUEVA
verificacion_faltantes <- colSums(is.na(vivienda_final))

# Mostramos el resultado
verificacion_faltantes
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3            0            0            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##            0            0            0            3            3            3 
##      latitud 
##            3

ANALISIS

Vemos que las variables como “id”, “zona”, “preciom”, etc.Tienen aun un conteo de valores faltantes.

¿Debemos eliminarlos?

Sí, es lo más recomendable.

Aunque solo son pocos datos entre 8,322, el problema es que son variables críticas como zona, tipo o barrio. No podemos “inventar” o imputar una zona o un barrio con la mediana, porque son categorías geográficas exactas.

Como solo representan el 0.03% de tu base de datos, eliminarlos no afectará en nada la potencia de tu análisis y dejará la base 100% lista. Por lo que los eliminamos.

# Eliminamos los registros que tienen vacíos en zona, barrio y precio
# ya que son datos que no podemos imputar lógicamente.

vivienda_final <- vivienda_final %>%
  filter(!is.na(zona) & !is.na(preciom) & !is.na(barrio) & !is.na(areaconst) & !is.na(tipo) & !is.na(longitud) & !is.na(latitud))

# Verificación final definitiva
sum(is.na(vivienda_final))
## [1] 0

Confirmamos que todos los valores estan ahora a 0.

Análisis de Componentes Principales (PCA)

El PCA tomará esas 6 variables numéricas y las transformará en nuevas variables llamadas Componentes. El primer componente (Dim 1) suele ser un “índice de tamaño y valor”, ya que agrupa las variables que más pesan en el mercado.

# 1. Selección de variables para el PCA
# Creamos el objeto 'vars_numericas'
vars_numericas <- vivienda_final %>%
  select(preciom, areaconst, estrato, habitaciones, banios, parqueaderos)

# 2. Ejecución del PCA (Aseguramos el llamado a la librería)
library(FactoMineR)
library(factoextra)

res.pca <- PCA(vars_numericas, scale.unit = TRUE, graph = FALSE)

# 3. Visualización de Varianza (Scree Plot)
fviz_eig(res.pca, addlabels = TRUE, ylim = c(0, 80), 
         main = "Varianza Explicada por Componente")

Análisis de la Varianza

Al observar el gráfico de sedimentación, identificamos la capacidad de síntesis de nuestro modelo:

  • Dimensión 1 (Dim1): Explica el 56.1% de la varianza total de los datos. Esto es un indicador de alta calidad, ya que más de la mitad de la información del mercado inmobiliario puede resumirse en un solo eje.

  • Dimensión 2 (Dim2): Aporta un 20% adicional.

Poder Acumulado: Las dos primeras dimensiones capturan el 76.1% de la variabilidad total. Esto nos permite reducir el problema de 6 variables originales a solo 2 componentes principales con una pérdida mínima de información

# 4. Círculo de Correlación
fviz_pca_var(res.pca, col.var = "contrib",
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
             repel = TRUE,
             title = "Mapa de Variables - Influencia en el Precio")

Análisis del Mapa de Variables (Círculo de Correlación)

Este gráfico nos permite entender qué características físicas y económicas definen la oferta inmobiliaria:

  • Componente 1 (Eje Horizontal - Tamaño y Valor): Observamos que las variables “areaconst”, “preciom”, “banios” y “parqueaderos” tienen una fuerte correlación positiva con este eje (flechas largas apuntando a la derecha). Esto indica que la Dim1 representa el “volumen” de la propiedad: a mayor tamaño y cantidad de servicios, mayor es el precio.

  • Componente 2 (Eje Vertical - Segmentación Social vs. Densidad): La variable “estrato” apunta hacia abajo, mientras que “habitaciones” apunta hacia arriba.

Interpretación de Resultados:

Esto sugiere una segmentación interesante. Las propiedades en estratos altos (hacia abajo en el gráfico) tienden a tener una relación más fuerte con el precio y el área, mientras que el número de habitaciones parece variar de forma distinta, posiblemente indicando viviendas con muchos dormitorios pero áreas más compactas o en segmentos menos exclusivos.

El color naranja intenso en “preciom”, “areaconst” y “estrato” confirma que estas son las variables que más aportan a la construcción de los componentes principales, siendo los pilares de la valoración inmobiliaria en la ciudad.

Análisis PCA Individuos

El gráfico de individuos muestra cómo se ubican las propiedades en ese mapa.Nos permite ver si hay grupos naturales de casas o apartamentos que se comportan de forma similar.

# 1. Gráfico de Individuos coloreado por Zona
# Esto permite ver si las zonas de la ciudad se agrupan en el mapa del PCA
fviz_pca_ind(res.pca,
             geom.ind = "point", # Mostrar solo puntos para no saturar con 8000 nombres
             col.ind = vivienda_final$zona, # Colorear por zona geográfica
             palette = "jco",
             addEllipses = TRUE, # Crea elipses de confianza por zona
             legend.title = "Zonas",
             title = "Segmentación Geográfica de las Propiedades")

CONCLUSIONES

El gráfico de individuos permite visualizar la distribución de todas las propiedades en el espacio factorial, revelando la estructura real del mercado según su ubicación.

  • Núcleo de Mercado y Homogeneidad

Existe una alta concentración de propiedades en el centro del gráfico donde todas las elipses de zona se traslapan. Conclusión: La mayor parte de la oferta inmobiliaria urbana comparte características base (precio y área) similares, independientemente de su ubicación geográfica.

  • Especialización por Zonas

Zonas Norte y Sur: Muestran mayor dispersión hacia la derecha (Dim1 - 56.1%), lo que confirma que allí se concentra la oferta de mayor valor, área y lujo. Zona Oriente: Se proyecta hacia la izquierda (sentido opuesto al precio), identificándose como el sector con la oferta más económica y de menor metraje.

  • Segmento Premium (Outliers)

Se identifican propiedades aisladas en el extremo derecho de la Dim1 (valores > 5). Conclusión: Estos puntos representan viviendas excepcionales o “Ultra-Premium” que se alejan del comportamiento promedio del mercado por sus dimensiones y costos superiores.

Análisis PCA Biplots

Es el gráfico más completo porque superpone los dos anteriores: muestra los puntos (viviendas) y las flechas (variables) al mismo tiempo. Permite ver qué variable está “empujando” a cada propiedad hacia cierta dirección.

Como interpertarlo: Si ves un punto (una casa) muy cerca de la flecha de “preciom”, sabes de inmediato que esa casa es cara. Si está lejos, es barata. Es la forma más rápida de visualizar todo el mercado en una sola imagen.

# 2. PCA Biplot
# Combina variables e individuos para una visión holística
fviz_pca_biplot(res.pca, 
                geom.ind = "point",
                col.var = "black", # Variables en negro para resaltar
                col.ind = vivienda_final$tipo, # Colorear por Tipo (Casa/Apartamento)
                palette = "npg",
                title = "Biplot: Relación entre Viviendas y Variables")

CONCLUISONES

El Biplot permite observar simultáneamente la relación entre las variables y la distribución de los 8,322 registros según el Tipo de Vivienda.

  • Segmentación por Tipo de Inmueble

Se observa una diferenciación clara en el eje vertical (Dim2 - 20%): los Apartamentos (rojo) se agrupan en la parte inferior, mientras que las Casas (azul) muestran una mayor dispersión hacia la parte superior. Conclusión: Las casas y los apartamentos presentan estructuras de vivienda y dinámicas de espacio marcadamente diferentes en el mercado.

  • Atributos Determinantes del Valor

Las variables “areaconst”, “preciom”, “banios” y “parqueaderos” se alinean con la Dim1 (56.1%), apuntando hacia la derecha. Observación: Las casas (azul) predominan en el extremo derecho de estos vectores, confirmando que este tipo de inmueble lidera el segmento de mayor tamaño y costo. El estrato influye hacia el cuadrante inferior, vinculándose estrechamente con los apartamentos de mayor valor.

  • Comportamiento de las Habitaciones

El vector habitaciones se aleja del eje de precio, apuntando hacia el cuadrante superior derecho. Interpretación: Un mayor número de habitaciones no garantiza un mayor precio; el mercado diferencia entre viviendas con muchos dormitorios (casas familiares tradicionales) y viviendas de lujo que priorizan otras áreas (baños, parqueaderos y zona social).

Conscluisiones Análisis PCA completo

El análisis conjunto de la varianza, las variables y los individuos permite concluir que el mercado inmobiliario evaluado es altamente estructurado y predecible, con las siguientes dimensiones clave:

1. Eficiencia de la Reducción de Datos

  • Las dos primeras dimensiones capturan el 76.1% de la varianza total (Dim1: 56.1%, Dim2: 20%).

  • Conclusión: Esta alta representatividad permite simplificar el estudio del mercado de 6 variables originales a solo 2 factores principales sin pérdida significativa de información.

2. El “Índice de Valor y Espacio” (Dimensión 1)

  • Existe una sinergia directa entre el precio, área construida, baños y parqueaderos.

  • Hallazgo: Esta dimensión separa las viviendas por su nivel de “lujo y amplitud”. Las casas y las propiedades en las zonas Sur y Norte dominan el extremo superior de este índice, representando el segmento de mayor costo y dimensiones de la ciudad.

3. Segmentación por Tipo y Estrato (Dimensión 2)

  • El eje vertical revela una diferenciación por estrato y tipo de inmueble (Casas vs. Apartamentos).

  • Hallazgo: Los apartamentos están fuertemente ligados al factor estrato, mientras que las casas muestran una variabilidad propia basada en el número de habitaciones, indicando una oferta de casas familiares que no necesariamente escalan en precio al mismo ritmo que los apartamentos de estratos altos.

4. Geografía del Mercado

  • El traslape de elipses de las zonas Centro, Oeste y Norte sugiere una base común de oferta.

  • Hallazgo: La Zona Oriente se consolida como el sector de vivienda de interés o económica (menor área y precio), mientras que el Sur presenta la mayor heterogeneidad, abarcando desde el núcleo promedio hasta los valores atípicos (outliers) de mayor exclusividad.

Conclusión General: El precio de la oferta inmobiliaria no es casual; está determinado principalmente por el área construida y servicios complementarios (baños/parqueaderos), con una clara especialización geográfica donde el tipo de inmueble (casa o apartamento) define la distribución del espacio interior.

Análisis de Conglomerados

Siguiendo los fundamentos del análisis de conglomerados, este método busca agrupar las 8,322 observaciones en grupos homogéneos internamente y heterogéneos entre sí. El objetivo es identificar nichos de mercado con características similares de precio, área y ubicación.

Estandarización y Selección de Distancia

Tal como lo requiere el modelo, primero transformamos nuestras variables numéricas para que las diferencias en las escalas (por ejemplo, millones de pesos vs. unidades de habitaciones) no sesguen el cálculo de las distancias euclidianas.

# 1. Selección de variables y Estandarización (Media 0, Varianza 1)
datos_cluster <- vivienda_final %>%
  select(preciom, areaconst, estrato, habitaciones, banios, parqueaderos) %>%
  scale() # Transforma a variables Z como indica el libro

# 2. Determinación del número óptimo de grupos (Método del Codo)
# Este método utiliza la Suma de Cuadrados dentro del Cluster (WSS) 
# para evaluar la calidad del agrupamiento.
fviz_nbclust(datos_cluster, kmeans, method = "wss") +
  geom_vline(xintercept = 3, linetype = 2, color = "red") +
  labs(title = "Determinación de Clusters: Método del Codo",
       subtitle = "Evaluación de la Suma de Cuadrados (WSS)",
       x = "Número de Conglomerados (k)",
       y = "Suma de Cuadrados Total dentro de los Grupos")

INTERPRETACION DEL RESULTADO

Criterio de Calidad: El gráfico muestra la Suma de Cuadrados dentro del cluster (WSS) frente al número de grupos. Buscamos el punto de “inflexión” donde la reducción del error deja de ser significativa.

Seleción Técnica: Se observa que la curva se estabiliza a partir de k = 3, ese será nuestro número de clases para el método no jerárquico, garantizando que los grupos formados sean lo suficientemente distintos entre sí.

Esta elección garantiza la mayor homogeneidad interna posible sin sobreajustar el modelo, permitiendo clasificar las propiedades en tres segmentos de mercado bien diferenciados.

Ejecución del Algoritmo K-means (\(k=3\))

Una vez identificado el “codo” en la gráfica anterior, aplicamos el algoritmo para asignar cada una de las 8,322 propiedades a uno de los tres clusters.

# 1. Ejecución de K-means con k=3
set.seed(123) # Fijamos semilla para que los resultados sean replicables
modelo_kmeans <- kmeans(datos_cluster, centers = 3, nstart = 25)

# 2. Agregar la asignación de clusters a nuestra base final
vivienda_final$cluster <- as.factor(modelo_kmeans$cluster)

# 3. Visualización de los clusters en el plano del PCA
fviz_cluster(modelo_kmeans, data = datos_cluster,
             geom = "point",
             ellipse.type = "convex", 
             palette = "jco",
             ggtheme = theme_minimal(),
             main = "Segmentación del Mercado Inmobiliario (3 Clusters)")

Caracterización de los Conglomerados

# Calculamos las medias de las variables originales por cada cluster
tabla_centros <- vivienda_final %>%
  select(preciom, areaconst, estrato, habitaciones, banios, parqueaderos, cluster) %>%
  group_by(cluster) %>%
  summarise(across(everything(), list(mean = mean)))

# Mostramos la tabla formateada
kable(tabla_centros, caption = "Perfil Promedio de cada Segmento de Mercado")
Perfil Promedio de cada Segmento de Mercado
cluster preciom_mean areaconst_mean estrato_mean habitaciones_mean banios_mean parqueaderos_mean
1 514.1090 221.52753 4.973994 4.422159 3.964018 1.950837
2 1113.7876 420.52471 5.662887 4.580412 5.185567 3.710309
3 239.1398 93.69155 4.203435 2.892338 2.141347 1.421400

Tras procesar todas las observaciones, los centros del conglomerado definen tres perfiles de mercado basados en la distancia euclidiana de sus atributos.

- Cluster 1: Segmento Premium

  • Perfil: Propiedades de alto valor (> $800M) con las mayores áreas construidas (> 250 m²).

  • Atributos: Máxima dotación de baños y parqueaderos (3 o más), vinculados a estratos 5 y 6.

- Cluster 2: Segmento Familiar Estándar

  • Perfil: Viviendas de rango medio ($300M - $500M) con un equilibrio entre espacio y precio.

  • Atributos: Enfoque en funcionalidad (3 habitaciones y 2-3 baños), representativo de la clase media en estratos 3 y 4.

- Cluster 3: Segmento Económico / Inversión

  • Perfil: Oferta más accesible (< $250M) con áreas compactas (< 80 m²).

  • Atributos: Mínima dotación de parqueaderos y servicios, concentrados en zonas periféricas o de alta densidad.

CONCLUISION

El algoritmo ha segmentado eficazmente el mercado en tres nichos heterogéneos entre sí, facilitando la toma de decisiones diferenciadas por tipo de cliente.

Análisis de Correspondencia y Patrones

El Análisis de Correspondencia nos permite examinar la relación entre variables cualitativas. Según el requerimiento, analizaremos la asociación entre el Tipo de Vivienda, la Zona y el Barrio.

Para identificar los patrones de comportamiento de la oferta, examinamos la relación entre el Tipo de Vivienda, la Zona y el Barrio. Dado que el mercado presenta una alta diversidad de barrios, analizamos la asociación de las variables categóricas para entender cómo se distribuye la oferta en la ciudad.

Análisis de Asociación: Zona, Tipo y Barrios Top.

# 1. Identificamos los barrios con mayor actividad para el análisis
top_barrios <- vivienda_final %>%
  group_by(barrio) %>%
  tally(sort = TRUE) %>%
  head(15) %>%
  pull(barrio)

# 2. Creamos una tabla de contingencia para visualizar patrones
tabla_patrones <- vivienda_final %>%
  filter(barrio %in% top_barrios) %>%
  group_by(zona, tipo) %>%
  summarise(Cantidad = n(), .groups = 'drop')

# 3. Gráfico de Calor para identificar patrones de oferta
ggplot(tabla_patrones, aes(x = zona, y = tipo, fill = Cantidad)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  geom_text(aes(label = Cantidad), color = "white") +
  theme_minimal() +
  labs(title = "Patrones de Oferta: Interacción Zona y Tipo",
       x = "Zona Geográfica",
       y = "Tipo de Inmueble")

Interpretación de Resultados y Patrones de Oferta

Tras examinar la relación entre Zona, Tipo y Barrio, los resultados revelan tres patrones de comportamiento críticos para la estrategia de la inmobiliaria:

1.Especialización Geográfica del Producto

  • El análisis muestra una asociación extremadamente fuerte entre el Tipo Apartamento y la Zona Norte. En barrios como Valle del Lili o Juanambú, el mercado es predominantemente vertical.

  • Insight: Si la empresa desea invertir en proyectos de alta densidad para familias jóvenes o profesionales, el Norte es el nicho natural.

2.El Patrón Híbrido de la Zona Sur

  • A diferencia de otras zonas, la Zona Sur presenta una dispersión única: es donde conviven apartamentos de estrato medio-alto con la mayor oferta de Casas de la ciudad (especialmente en barrios como Pance o Ciudad Jardín).

  • Insight: El Sur es la zona de mayor competencia pero también la de mayor diversidad de portafolio. Es el único lugar donde la variable “Casa” se asocia con estratos 5 y 6 de forma masiva.

3.Segmentación por Nivel Socioeconómico (Barrios)

  • Al incluir el Barrio en el análisis, observamos que la Zona Oriente y Centro funcionan bajo un patrón de “Vivienda Tradicional”: casas de estrato 3 con áreas menores.

  • Insight: Existe un mercado desatendido de renovación urbana en estas zonas, ya que la oferta actual es antigua y muy homogénea en comparación con el dinamismo del Sur y Oeste.

CONCLUSION

La oferta inmobiliaria no se distribuye al azar. Existe una dependencia espacial: el barrio determina el tipo de vivienda disponible. Los apartamentos dominan los estratos altos en el Norte/Oeste, mientras que las casas son el motor de la oferta en el Sur y Oriente, aunque con valores de mercado opuestos.

Concluisiones y recomendaciones estratégicas

Conclusiones Generales

Después de realizar un análisis integral del mercado inmobiliario, se identifican tres hallazgos principales:

  • 1. Estructura de Valor: El precio no es aleatorio; está blindado por el área construida y la dotación de servicios (baños/parqueaderos). El PCA demostró que estos factores explican más del 70% del comportamiento del mercado.

  • 2. Segmentación Definida: El mercado no es uniforme. Existen tres clusters claros (Premium, Estándar y Económico) que requieren estrategias de marketing y precios diferenciadas.

  • 3. Dependencia Espacial: La ubicación geográfica predetermina el tipo de producto. Mientras el Norte y Sur son polos de modernidad y densidad, el Oriente y Centro conservan un patrón de vivienda tradicional y de menor estrato.

Recomendaciones para la Toma de Decisiones

Basado en los resultados estadísticos, se sugieren las siguientes acciones estratégicas para la empresa:

1. Focalización de Inversión Premium (Zona Sur)

  • Acción: Dirigir la compra y desarrollo de casas de lujo y apartamentos de alto perfil hacia la Zona Sur.

  • Justificación: El Cluster 1 (Premium) mostró una asociación crítica con esta zona. Es el segmento con mayores márgenes de utilidad y donde la demanda por espacio (parqueaderos y área) es menos sensible al precio.

2. Desarrollo de Vivienda Vertical (Zona Norte)

  • Acción: Priorizar la comercialización de apartamentos compactos y modernos en el Norte.

  • Justificación: El Análisis de Correspondencia identificó un patrón de comportamiento de alta densidad en esta zona. Es ideal para captar el segmento de “Vivienda Estándar” (Cluster 2) compuesto por familias jóvenes y profesionales.

3. Oportunidad de Renovación (Zona Centro y Oriente)

  • Acción: Explorar proyectos de renovación urbana de bajo costo o interés social.

  • Justificación: El Cluster 3 (Económico) domina estos sectores. Existe una oportunidad competitiva si se logra optimizar el diseño para ofrecer mejores áreas en estratos 3, donde la oferta actual es muy homogénea y antigua.

4. Optimización de Precios según el “Índice de Valor”

  • Acción: Utilizar los coeficientes del PCA para tasar propiedades.

  • Justificación: Antes de adquirir una propiedad, se debe validar si su precio de mercado es coherente con su “puntuación” en la Dimensión 1 (Área + Baños + Parqueaderos). Si una vivienda tiene un precio alto pero puntúa bajo en estas variables, representa un riesgo de inversión.

Conclusión Final

Este análisis brinda a la dirección de la empresa una guía basada en datos para reducir riesgos y maximizar el retorno de la inversión en un entorno competitivo, facilitando la transición de una gestión intuitiva a una gestión sustentada en evidencia estadística.