Evaluación de la oferta inmobiliaria urbana

Problema

Una empresa inmobiliaria líder en una gran ciudad está buscando comprender en profundidad el mercado de viviendas urbanas para tomar decisiones estratégicas más informadas. La empresa posee una base de datos extensa que contiene información detallada sobre diversas propiedades residenciales disponibles en el mercado. Se requiere realizar un análisis holístico de estos datos para identificar patrones, relaciones y segmentaciones relevantes que permitan mejorar la toma de decisiones en cuanto a la compra, venta y valoración de propiedades.

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

Retos:

El reto principal consisten en realizar un análisis integral y multidimensional de la base de datos para obtener una comprensión del mercado inmobiliario urbano. Se requiere aplicar diversas técnicas de análisis de datos, incluyendo:

  • Análisis de Componentes Principales: Reducir la dimensionalidad del conjunto de datos y visualizar la estructura de las variables en componentes principales para identificar características clave que influyen en la variación de precios y oferta del mercado.

  • Análisis de Conglomerados: Agrupar las propiedades residenciales en segmentos homogéneos con características similares para entender las dinámicas de las ofertas específicas en diferentes partes de la ciudad y en diferentes estratos socioeconómicos.

  • Análisis de Correspondencia : Examinar la relación entre las variables categóricas (tipo de vivienda, zona y barrio), para identificar patrones de comportamiento de la oferta en mercado inmobiliario.

  • Visualización de resultados: Presentar gráficos, mapas y otros recursos visuales para comunicar los hallazgos de manera clara y efectiva a la dirección de la empresa.

El informe final debe incluir análisis detallados de los resultados obtenidos, las conclusiones clave y las recomendaciones específicas para guiar las decisiones estratégicas de la empresa inmobiliaria. Se espera que este análisis de datos proporcione ventajas competitivas en el mercado, optimizando la inversión y maximizando los beneficios en un entorno altamente competitivo y en constante cambio.

Exploración de datos

## 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>
##        id           zona               piso              estrato     
##  Min.   :   1   Length:8322        Length:8322        Min.   :3.000  
##  1st Qu.:2080   Class :character   Class :character   1st Qu.:4.000  
##  Median :4160   Mode  :character   Mode  :character   Median :5.000  
##  Mean   :4160                                         Mean   :4.634  
##  3rd Qu.:6240                                         3rd Qu.:5.000  
##  Max.   :8319                                         Max.   :6.000  
##  NA's   :3                                            NA's   :3      
##     preciom         areaconst       parqueaderos        banios      
##  Min.   :  58.0   Min.   :  30.0   Min.   : 1.000   Min.   : 0.000  
##  1st Qu.: 220.0   1st Qu.:  80.0   1st Qu.: 1.000   1st Qu.: 2.000  
##  Median : 330.0   Median : 123.0   Median : 2.000   Median : 3.000  
##  Mean   : 433.9   Mean   : 174.9   Mean   : 1.835   Mean   : 3.111  
##  3rd Qu.: 540.0   3rd Qu.: 229.0   3rd Qu.: 2.000   3rd Qu.: 4.000  
##  Max.   :1999.0   Max.   :1745.0   Max.   :10.000   Max.   :10.000  
##  NA's   :2        NA's   :3        NA's   :1605     NA's   :3       
##   habitaciones        tipo              barrio             longitud     
##  Min.   : 0.000   Length:8322        Length:8322        Min.   :-76.59  
##  1st Qu.: 3.000   Class :character   Class :character   1st Qu.:-76.54  
##  Median : 3.000   Mode  :character   Mode  :character   Median :-76.53  
##  Mean   : 3.605                                         Mean   :-76.53  
##  3rd Qu.: 4.000                                         3rd Qu.:-76.52  
##  Max.   :10.000                                         Max.   :-76.46  
##  NA's   :3                                              NA's   :3       
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.381  
##  Median :3.416  
##  Mean   :3.418  
##  3rd Qu.:3.452  
##  Max.   :3.498  
##  NA's   :3
##           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
## 
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur 
##          124         1920         1198          351         4726
## 
## Apartamento        Casa 
##        5100        3219

Vemos la distribución de precios de la oferta de viviendas:

Tratamiento de valores faltantes

##           id         zona      estrato      preciom    areaconst parqueaderos 
##            3            3            3            2            3         1605 
##       banios habitaciones         tipo       barrio     longitud      latitud 
##            3            3            3            3            3            3
## 
##  iter imp variable
##   1   1  parqueaderos
##   2   1  parqueaderos
##   3   1  parqueaderos
##   4   1  parqueaderos
##   5   1  parqueaderos
##   6   1  parqueaderos
##   7   1  parqueaderos
##   8   1  parqueaderos
##   9   1  parqueaderos
##   10   1  parqueaderos
##           id         zona      estrato      preciom    areaconst parqueaderos 
##            0            0            0            0            0            0 
##       banios habitaciones         tipo       barrio     longitud      latitud 
##            0            0            0            0            0            0
##      estrato      preciom    areaconst parqueaderos       banios habitaciones 
##    "numeric"    "numeric"    "numeric"    "numeric"    "numeric"    "numeric" 
##     longitud      latitud 
##    "numeric"    "numeric"
## $Tablas
## $Tablas$Antes
## x_antes
##    1    2    3    4    5    6    7    8    9   10 <NA> 
## 3155 2475  520  384   68   68   18   17    4    8 1605 
## 
## $Tablas$Despues
## x_mice
##    1    2    3    4    5    6    7    8    9   10 
## 4342 2778  573  423   74   73   23   18    5   10 
## 
## 
## $Proporciones
## $Proporciones$Antes
## x_antes
##     1     2     3     4     5     6     7     8     9    10  <NA> 
## 37.91 29.74  6.25  4.61  0.82  0.82  0.22  0.20  0.05  0.10 19.29 
## 
## $Proporciones$Despues
## x_mice
##     1     2     3     4     5     6     7     8     9    10 
## 52.19 33.39  6.89  5.08  0.89  0.88  0.28  0.22  0.06  0.12 
## 
## 
## $Medias
##    Antes  Despues 
## 1.835194 1.751052 
## 
## $Medianas
##   Antes Despues 
##       2       1 
## 
## $Varianzas
##    Antes  Despues 
## 1.265420 1.206231
## $Medianas
## $Medianas$Antes
## Apartamento        Casa 
##           1           2 
## 
## $Medianas$Despues
## Apartamento        Casa 
##           1           2 
## 
## 
## $Medias
## $Medias$Antes
## Apartamento        Casa 
##    1.567714    2.290426 
## 
## $Medias$Despues
## Apartamento        Casa 
##    1.496471    2.154396

Despues de tratar los datos faltantes revisamos que los datos conserven su distribución y no se haya generado un cambio sustancial:

## Análisis de Componentes principales

## Rows: 8,319
## Columns: 12
## $ id           <dbl> 1147, 1169, 1350, 5992, 1212, 1724, 2326, 4386, 1209, 159…
## $ zona         <chr> "Zona Oriente", "Zona Oriente", "Zona Oriente", "Zona Sur…
## $ estrato      <dbl> 3, 3, 3, 4, 5, 5, 4, 5, 5, 5, 6, 4, 5, 6, 4, 5, 5, 4, 5, …
## $ preciom      <dbl> 250, 320, 350, 400, 260, 240, 220, 310, 320, 780, 750, 62…
## $ areaconst    <dbl> 70, 120, 220, 280, 90, 87, 52, 137, 150, 380, 445, 355, 2…
## $ parqueaderos <dbl> 1, 1, 2, 3, 1, 1, 2, 2, 2, 2, 2, 3, 2, 2, 1, 4, 2, 2, 2, …
## $ banios       <dbl> 3, 2, 2, 5, 2, 3, 2, 3, 4, 3, 7, 5, 6, 2, 4, 4, 4, 3, 2, …
## $ habitaciones <dbl> 6, 3, 4, 3, 3, 3, 3, 4, 6, 3, 6, 5, 6, 2, 5, 5, 4, 3, 3, …
## $ tipo         <chr> "Casa", "Casa", "Casa", "Casa", "Apartamento", "Apartamen…
## $ barrio       <chr> "20 de julio", "20 de julio", "20 de julio", "3 de julio"…
## $ longitud     <dbl> -76.51168, -76.51237, -76.51537, -76.54000, -76.51350, -7…
## $ latitud      <dbl> 3.43382, 3.43369, 3.43566, 3.43500, 3.45891, 3.36971, 3.4…

## Análisis de Conglomerados (Clustering)

Análisis de Correspondencia (Múltiple)

## **Interpretacion (MCA).** Categorias con mayor aporte a Dim 1: 6, Zona Oeste, santa teresita, 3, normandía, Zona Norte, los cristales, Zona Oriente, Otros, Casa. Categorias con mayor aporte a Dim 2: 3, valle del lili, Zona Sur, Zona Oriente, 4, Zona Oeste, Otros, Zona Norte, el caney, santa teresita.

Visualización geográfica

CONCLUSIONES Y ANALISIS DE LOS RESULTADOS:

1) Comportamiento de precios y métrica precio/m²

La distribución de precio trabajada en escala logarítmica aparece asimétrica a la derecha (cola alta), típica de portales de oferta con muchos listados en rangos medios y pocos muy altos. Esto justifica:

  • usar log-precio para algunos modelos (lineales) y

  • priorizar precio/m² para comparar categorías, ya que reduce el efecto del tamaño.

Al derivar precio/m² (precio/área), la variabilidad entre categorías (p. ej. zona, tipo) se vuelve más interpretable y estable para contrastes y segmentación.

2) Relaciones clave (EDA)

Área vs. precio: relación positiva clara; en dispersión se ve la pendiente creciente (y también mucha dispersión para áreas pequeñas, normal en apartamentos tipo estudio/1 hab.).

Amenidades (baños, habitaciones, parqueaderos) se correlacionan con precio y (sobre todo) con área; conviene tratarlas como “paquete de tamaño/atributos”.

La heterogeneidad por barrio/zona es marcada: en boxplots y comparativos se observa cómo ciertas categorías se ubican consistentemente por encima o debajo de la mediana global (ver gráfico de diferencias por categoría).

3) PCA (Componentes Principales)

El PCA resume la estructura de las variables numéricas (tras estandarizar):

  • PC1 captura un gradiente de tamaño/amenidades (área, baños, habitaciones y, a menudo, parqueaderos). En el biplot, estas variables “empujan” en una dirección común, describiendo “viviendas más grandes y equipadas” vs. “compactas”.

  • PC2 suele recoger un segundo eje que separa configuraciones distintas (p. ej., densidad de parqueo vs. área o efectos de precio/m² una vez controlado el tamaño).

  • El biplot muestra grupos de observaciones que se alinean con esos ejes; no es raro ver que algunos barrios/zona queden más cargados en la dirección de precio/m² alto y otros en la de tamaño.

4) Clustering (K-means sobre variables estandarizadas)

Se elige k con silhouette (2–10), y luego se ajusta K-means.

Proyectado sobre las dos primeras PCs, los clusters aparecen compactos y bien separados (elipses al 90%), lo que sugiere segmentaciones interpretables:

  • Cluster “premium-espacioso”: mayor área, más baños/habitaciones y precio/m² alto; suele concentrarse en barrios/zonas específicas.

  • Cluster “compacto-eficiente”: áreas reducidas, menos parqueaderos, precio total más bajo, pero a veces precio/m² competitivo (por ubicación).

  • Cluster “medio”: perfiles intermedios con dispersión moderada en precio/m² y tamaño.

La tabla de perfiles por cluster (medianas) confirma cuáles variables más distinguen a cada grupo (las de mayor rango entre clusters). Esto es clave para producto/marketing.

5) MCA (Correspondencias, variables categóricas)

Con zona / tipo / estrato / barrio (agrupado Top-N + “Otros”):

  • El mapa de individuos por zona (con elipses 90%) evidencia agrupación clara: las categorías de zona/estrato tienden a ocupar regiones distintas del plano.

  • El gráfico de categorías (Top-20 por contribución) resalta los niveles que explican mejor las dos dimensiones (p. ej., tipos de vivienda/estratos/barrios que “tiran” con fuerza en un eje).

Lectura práctica: ciertas combinaciones (p. ej. apartamento + zonas centrales de estrato medio/alto) coaparecen; casas se asocian más a subzonas específicas. Sirve para posicionamiento y portafolio.

6) Mapa de puntos y densidad

El mapa de lat/long muestra nudos de alta densidad (hot spots) donde se concentran avisos.

Superpuesto por cluster, se observan patrones espaciales: el cluster premium tiende a focalizarse en ciertos sectores, mientras el cluster compacto es más extendido en corredores con acceso/servicios.

La capa de densidad (contornos) ayuda a priorizar captación y pauta geolocalizada.

7) Diferencia de precios por categoría (ej. zona)

El gráfico lollipop (mediana por categoría vs. mediana global) deja claro qué zonas quedan por encima y por debajo del mercado:

  • Útil para tasación inicial (anclar en la mediana global y ajustar por la diferencia de la categoría) y para pricing dinámico por zona/tipo.

El gráfico de IQR (q25–q75) por categoría revela volatilidad: categorías con IQR ancho requieren bandas de precio más amplias y mayor control de atípicos.

Recomendaciones

  • Se recomienda usar la mediana de precio por m² por zona × tipo como base de tasación y ajustar según área, baños y parqueaderos (más atributos que el promedio de la zona = ajuste al alza; menos = juste a la baja).

  • Se recomienda establecer un control de valores atípicos y revisión de tasación para los anuncios cuyo precio o precio/m² queden por fuera de q25–q75 ± 1.5×IQR en su zona.

  • Se recomienda priorizar la captación en los puntos de mayor densidad del mapa (hot spots) y en zonas por encima de la mediana de precio/m², donde hay mayor disposición a pagar.

  • Se recomienda mantener variedad de producto por zona (tamaños y configuraciones) para atender distintos segmentos y mejorar la rotación del inventario.

  • Se recomienda destacar en la ficha del inmueble los atributos que más influyen en el precio (área, baños, parqueaderos) y mostrar el precio por m² además del precio total, para facilitar la comparación.

  • Se recomienda aprovechar la segmentación por clusters para orientar acciones:

    • En clusters “premium”: resaltar amenidades y localización estratégica.

    • En clusters “compactos”: resaltar accesibilidad, eficiencia del espacio y cercanía a servicios.

  • Se recomienda realizar un seguimiento mensual de:

    • Medianas e IQR de precio/m² por zona × tipo.

    • k óptimo y tamaño/perfil de los clusters.

    • Cambios en los puntos calientes del mapa (densidad de oferta).

  • Se recomienda implementar alertas automáticas para detectar anuncios con precio fuera de rango de su zona y proponer ajustes.

  • Se recomienda estandarizar y validar los datos operativos (por ejemplo: área > 0, coherencia entre variables) y calcular de forma consistente el precio por m² en todo el portafolio.