Contexto

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.

Llamado de librerias

library(devtools)
library(mice)
library(tidyverse)
library(factoextra)
library(cluster)
library(dplyr)
library(FactoMineR)
library(gridExtra)
library(tcltk2)
devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
## 
## ── R CMD build ─────────────────────────────────────────────────────────────────
##      During startup - Warning messages:
##    1: Setting LC_TIME failed, using "C" 
##    2: Setting LC_MESSAGES failed, using "C" 
##    3: Setting LC_MONETARY failed, using "C" 
##      checking for file ‘/private/var/folders/f7/fh96nvx97hz525c07nbtj01r0000gn/T/Rtmpng3BMf/remotes1dc77642b386/Centromagis-paqueteMODELOS-3b06257/DESCRIPTION’ ...  ✔  checking for file ‘/private/var/folders/f7/fh96nvx97hz525c07nbtj01r0000gn/T/Rtmpng3BMf/remotes1dc77642b386/Centromagis-paqueteMODELOS-3b06257/DESCRIPTION’
##   ─  preparing ‘paqueteMODELOS’:
##    checking DESCRIPTION meta-information ...  ✔  checking DESCRIPTION meta-information
##   ─  checking for LF line-endings in source and make files and shell scripts
##   ─  checking for empty or unneeded directories
##   ─  building ‘paqueteMODELOS_0.1.0.tar.gz’
##      
## 
library(paqueteMODELOS)
library(psych)
library(ggplot2)
library(patchwork)
library(VIM)

Carga de la base de datos

data("vivienda")

Analisis exploratorio

Dimensiones del dataset

dim(vivienda)
## [1] 8322   13

Se cuenta con un dataset de 8322 registros descritos por 13 variables.

Reconocimiento de la base de datos, en la cual se identificaron 8 variables cuantitativas (4 discretas y 4 continuas) y 4 variables cuantitativas (nominales principalmente). Sin embargo se identifica a su vez que la variable piso tiene datos faltantes y realmente es una variable cuantitativa discreta.

Identificacion correcta de piso

par(cex = 0.8)
md.pattern(vivienda)

##      preciom id zona estrato areaconst banios habitaciones tipo barrio longitud
## 4808       1  1    1       1         1      1            1    1      1        1
## 1909       1  1    1       1         1      1            1    1      1        1
## 876        1  1    1       1         1      1            1    1      1        1
## 726        1  1    1       1         1      1            1    1      1        1
## 1          1  0    0       0         0      0            0    0      0        0
## 2          0  0    0       0         0      0            0    0      0        0
##            2  3    3       3         3      3            3    3      3        3
##      latitud parqueaderos piso     
## 4808       1            1    1    0
## 1909       1            1    0    1
## 876        1            0    1    1
## 726        1            0    0    2
## 1          0            0    0   12
## 2          0            0    0   13
##            3         1605 2638 4275
par(cex = 1)

Se observa que 4808 registros tienen los datos completos para cada atributo, 1909 registros les falta el dato de piso, 876 les falta eel dato de parqueaderos, 726 les faltan ambos datos, existe un registro con un unido dato de precio y dos registros sin datos.

sum(duplicated(vivienda))
## [1] 1

Se identifica un registro duplicado.

summary(vivienda[c("piso", "estrato", "preciom", "areaconst", "parqueaderos", "banios","habitaciones", "latitud", "longitud")])
##       piso           estrato         preciom         areaconst     
##  Min.   : 1.000   Min.   :3.000   Min.   :  58.0   Min.   :  30.0  
##  1st Qu.: 2.000   1st Qu.:4.000   1st Qu.: 220.0   1st Qu.:  80.0  
##  Median : 3.000   Median :5.000   Median : 330.0   Median : 123.0  
##  Mean   : 3.771   Mean   :4.634   Mean   : 433.9   Mean   : 174.9  
##  3rd Qu.: 5.000   3rd Qu.:5.000   3rd Qu.: 540.0   3rd Qu.: 229.0  
##  Max.   :12.000   Max.   :6.000   Max.   :1999.0   Max.   :1745.0  
##  NA's   :2638     NA's   :3       NA's   :2        NA's   :3       
##   parqueaderos        banios        habitaciones       latitud     
##  Min.   : 1.000   Min.   : 0.000   Min.   : 0.000   Min.   :3.333  
##  1st Qu.: 1.000   1st Qu.: 2.000   1st Qu.: 3.000   1st Qu.:3.381  
##  Median : 2.000   Median : 3.000   Median : 3.000   Median :3.416  
##  Mean   : 1.835   Mean   : 3.111   Mean   : 3.605   Mean   :3.418  
##  3rd Qu.: 2.000   3rd Qu.: 4.000   3rd Qu.: 4.000   3rd Qu.:3.452  
##  Max.   :10.000   Max.   :10.000   Max.   :10.000   Max.   :3.498  
##  NA's   :1605     NA's   :3        NA's   :3        NA's   :3      
##     longitud     
##  Min.   :-76.59  
##  1st Qu.:-76.54  
##  Median :-76.53  
##  Mean   :-76.53  
##  3rd Qu.:-76.52  
##  Max.   :-76.46  
##  NA's   :3
describe(vivienda[c("piso", "estrato", "preciom", "areaconst", "parqueaderos", "banios","habitaciones", "latitud", "longitud")])
##              vars    n   mean     sd median trimmed    mad    min     max
## piso            1 5684   3.77   2.61   3.00    3.37   1.48   1.00   12.00
## estrato         2 8319   4.63   1.03   5.00    4.67   1.48   3.00    6.00
## preciom         3 8320 433.89 328.65 330.00  374.43 207.56  58.00 1999.00
## areaconst       4 8319 174.93 142.96 123.00  149.15  84.51  30.00 1745.00
## parqueaderos    5 6717   1.84   1.12   2.00    1.62   1.48   1.00   10.00
## banios          6 8319   3.11   1.43   3.00    2.99   1.48   0.00   10.00
## habitaciones    7 8319   3.61   1.46   3.00    3.41   1.48   0.00   10.00
## latitud         8 8319   3.42   0.04   3.42    3.42   0.05   3.33    3.50
## longitud        9 8319 -76.53   0.02 -76.53  -76.53   0.02 -76.59  -76.46
##                range  skew kurtosis   se
## 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
## latitud         0.16  0.03    -1.15 0.00
## longitud        0.13  0.65     0.58 0.00

Se identifica que el estrato promedio es 4.63 con un costo promedio de 433, en un tercer piso con area construida 174, 1.84 parquederos, 3.11 baños, 3.61 habitaciones.

p1 <- ggplot(vivienda, aes(y = estrato)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5) +
  ggtitle("Estrato")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

p2 <- ggplot(vivienda, aes(y = preciom)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5)  +
  ggtitle("Precio")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

p3 <- ggplot(vivienda, aes(y = areaconst)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5) +
  ggtitle("Área Construida")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

p4 <- ggplot(vivienda, aes(y = parqueaderos)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5)  +
  ggtitle("Numero de parqueaderos")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

p5 <- ggplot(vivienda, aes(y =  banios)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5)  +
  ggtitle("Numero de baños")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

p6 <- ggplot(vivienda, aes(y =  habitaciones)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5)  +
  ggtitle("Numero de habitaciones")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

p7 <- ggplot(vivienda, aes(y = longitud)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5)  +
  ggtitle("Longitud")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

p8 <- ggplot(vivienda, aes(y = latitud)) +
  geom_boxplot(fill="lightblue",
               outlier.color = "red",
               outlier.size = 1.5)  +
  ggtitle("Latitud")+
  theme(
    plot.title = element_text(size = 10,hjust = 0.5))

(p1 | p2 | p3 | p4) /
(p5 | p6 | p7 | p8)
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
## Warning: Removed 2 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
## Warning: Removed 1605 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
## Removed 3 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
## Removed 3 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
## Removed 3 rows containing non-finite outside the scale range
## (`stat_boxplot()`).

Se identifican outliers en las variables cuantitativas: precio, area construida, numero de parqueaderos, numero de habitaciones y longitud.

lapply(vivienda[c("zona", "tipo", "barrio")], function(x) {
  sort(table(x), decreasing = TRUE)[1]
})
## $zona
## Zona Sur 
##     4726 
## 
## $tipo
## Apartamento 
##        5100 
## 
## $barrio
## valle del lili 
##           1008

Se identifica que las viviendas disponibles comercialmente se encuentran en la zona zur, tipo apartamento en el Valle de Lili.

p1<-ggplot(vivienda, aes(x = zona)) +
  geom_bar(fill = "lightblue") +
  theme_minimal() +
  theme(axis.text.x = element_text(size=8, angle = 90, hjust = 1)) +
  labs(title = "Distribución por Zona",
       x = "Zona",
       y = "Frecuencia")
p2<-ggplot(vivienda, aes(x = tipo)) +
  geom_bar(fill = "lightblue") +
  theme_minimal() +
  theme(axis.text.x = element_text(size=8, angle = 90, hjust = 1)) +
  labs(title = "Distribución por tipo de vivienda",
       x = "Vivienda",
       y = "Frecuencia")
p3<-ggplot(vivienda, aes(x = barrio)) +
  geom_bar(fill = "lightblue") +
  theme_minimal() +
  theme(axis.text.x = element_text(size=1, angle = 90, hjust = 1)) +
  labs(title = "Distribución por barrio",
       x = "Barrio",
       y = "Frecuencia")
(p1 | p2 ) /
(p3) 

Se identifica que la zona y el tipo de vivenda tienen datos faltantes, la zona centro tiene baja frecuencia y podria considerarse dato atipico.

Preprocesamiento de datos

1. Eliminacion de duplicados

vivienda <- vivienda[!duplicated(vivienda), ]
sum(duplicated(vivienda))
## [1] 0

2. Manejo de datos faltantes 2.1 Eliminar registros con mas de dos datos faltantes

na_fila <- rowSums(is.na(vivienda))
vivienda <- vivienda[na_fila < 2, ]

2.3 Imputacion de datos a registros con 1 a 2 datos faltantes

vivienda <-  kNN(vivienda, variable = c("piso", "parqueaderos"), k = 10)
par(cex = 0.8)
md.pattern(vivienda)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

##      id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## 7593  1    1    1       1       1         1            1      1            1
##       0    0    0       0       0         0            0      0            0
##      tipo barrio longitud latitud piso_imp parqueaderos_imp  
## 7593    1      1        1       1        1                1 0
##         0      0        0       0        0                0 0
par(cex = 1)

3. Manejo de datos atipicos 3.1 Eliminacion de datos atipicos en variables cualitativas

vivienda <- vivienda[vivienda$zona != "Zona Centro", ]

3.2 Eliminacion de outliers en variables cuantitativas

variables_cuantitativas <- c("piso", "estrato", "preciom", "areaconst", "parqueaderos", "banios","habitaciones", "latitud", "longitud")
limites <- t(sapply(variables_cuantitativas, function(v) {
  x <- vivienda[[v]]
  Primer_cuartil<- quantile(x, 0.25)
  Tercer_cuartil <- quantile(x, 0.75)
  RIC  <- IQR(x)
  c(lim_inf = Primer_cuartil - 1.5*RIC, lim_sup = Tercer_cuartil + 1.5*RIC)
}))

vivienda<- vivienda[
  vivienda$estrato >= limites["estrato","lim_inf.25%"] &
  vivienda$estrato <= limites["estrato","lim_sup.75%"] &

  vivienda$preciom >= limites["preciom","lim_inf.25%"] &
  vivienda$preciom <= limites["preciom","lim_sup.75%"] &

  vivienda$areaconst >= limites["areaconst","lim_inf.25%"] &
  vivienda$areaconst <= limites["areaconst","lim_sup.75%"] &

  vivienda$parqueaderos >= limites["parqueaderos","lim_inf.25%"] &
  vivienda$parqueaderos <= limites["parqueaderos","lim_sup.75%"] &

  vivienda$banios >= limites["banios","lim_inf.25%"] &
  vivienda$banios <= limites["banios","lim_sup.75%"] &

  vivienda$habitaciones >= limites["habitaciones","lim_inf.25%"] &
  vivienda$habitaciones <= limites["habitaciones","lim_sup.75%"] &

  vivienda$latitud >= limites["latitud","lim_inf.25%"] &
  vivienda$latitud <= limites["latitud","lim_sup.75%"] &

  vivienda$longitud >= limites["longitud","lim_inf.25%"] &
  vivienda$longitud <= limites["longitud","lim_sup.75%"],
]
dim(vivienda)
## [1] 5944   15

Posterior al pretratamiento de los datos se obtiene un dataset con 5944 registros y 15 atributos.

Analisis multivariado

rownames(vivienda) <- vivienda$id

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

Se realiza el escalamiento de los datos

vivienda_escalada= scale(vivienda[c("piso", "estrato", "preciom", "areaconst", "parqueaderos", "banios","habitaciones", "latitud", "longitud")])
head(vivienda_escalada)
##            piso    estrato     preciom  areaconst parqueaderos     banios
## 1169 -1.1801711 -1.7316740 -0.14062803 -0.1313794   -0.8005722 -0.7333901
## 1350 -0.7710295 -1.7316740  0.01307398  1.1753618    0.8983215 -0.7333901
## 5992 -0.7710295 -0.6800731  0.26924400  1.9594066    2.5972151  2.0675978
## 1212 -1.1801711  0.3715279 -0.44803206 -0.5234018   -0.8005722 -0.7333901
## 1724 -1.1801711  0.3715279 -0.55050007 -0.5626041   -0.8005722  0.2002725
## 2326 -1.1801711 -0.6800731 -0.65296808 -1.0199635    0.8983215 -0.7333901
##      habitaciones    latitud   longitud
## 1169   -0.2764739  0.3995623  1.0516301
## 1350    1.0541826  0.4457315  0.8634316
## 5992   -0.2764739  0.4302636 -0.6816784
## 1212   -0.2764739  0.9906224  0.9807420
## 1724   -0.2764739 -1.0998836  0.7611771
## 2326   -0.2764739  0.2256659  0.5892891
res.pca <- prcomp(vivienda_escalada)
fviz_eig(res.pca, addlabels = TRUE)
## Warning in geom_bar(stat = "identity", fill = barfill, color = barcolor, :
## Ignoring empty aesthetic: `width`.

El componente principal 1 explica el 42.7% de la variabilidad de la base de datos y entre los dos primeros componenes se explica el 58.9% de la variabilidad total.

fviz_pca_var(res.pca,
col.var = "contrib",
gradient.cols = c("#FF7F00",  "#034D94"),
repel = TRUE
)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## ℹ The deprecated feature was likely used in the ggpubr package.
##   Please report the issue at <https://github.com/kassambara/ggpubr/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the factoextra package.
##   Please report the issue at <https://github.com/kassambara/factoextra/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Criterios de interpretabilidad: - Si la flecha es casi horizontal, entonces pertenece a Dim1 - Si es casi vertical entonces pertenece a Dim2 - Si está en diagonal entonces influye en ambas

La dimension 1 que explica el 42.7% de la variabilidad representa el precio, el area construida, el numero de parqueaderos, baños y habitaciones. Variables asociadas al tamaño y al precio del inmueble. La dimension 2 que captura el 16.2% de la variabilidad representa el piso, el estrato y la latitud con menor contribucion. Adicionalmente, se observa que el precio se correlaciona positivamente con el numero de parqueaderos y que el estrato de correlaciona negativamente con la longitud de la ubidacion geoespacial del inmueble. Tambien se resalta que la latitud, el piso, la longitud y los parqueaderos no se encuetran completamente explicadas por los dos componentes principales.

Determinacion del sentido de los ejes

datos<- vivienda[vivienda$id %in% c(855, 8264, 5771, 7663), ]

datos <- as.data.frame(datos)
rownames(datos) = c("Inmueble 8264","Inmueble 7663","Inmueble 5771","Inmueble 855")
datos
##                 id         zona piso estrato preciom areaconst parqueaderos
## Inmueble 8264 8264   Zona Oeste    3       6    1000       250            2
## Inmueble 7663 7663   Zona Oeste    5       6    1000       236            3
## Inmueble 5771 5771   Zona Oeste    3       3     900       385            1
## Inmueble 855   855 Zona Oriente    1       3      62        61            1
##               banios habitaciones        tipo         barrio  longitud latitud
## Inmueble 8264      5            4        Casa      aguacatal -76.56043 3.45643
## Inmueble 7663      4            3 Apartamento      aguacatal -76.55100 3.45700
## Inmueble 5771      4            5        Casa   san cayetano -76.53812 3.44444
## Inmueble 855       1            2 Apartamento villa del lago -76.50400 3.43600
##               piso_imp parqueaderos_imp
## Inmueble 8264    FALSE            FALSE
## Inmueble 7663     TRUE            FALSE
## Inmueble 5771     TRUE            FALSE
## Inmueble 855     FALSE             TRUE
casos1 <- rbind(res.pca$x["855",1:2],res.pca$x["8264",1:2]) # CP1
rownames(casos1) = c("855","8264")
casos1 <- as.data.frame(casos1)

casos2 <- rbind(res.pca$x["5771",1:2], res.pca$x["7663",1:2]) # CP2
rownames(casos2) = c("5771","7663")
casos2 <- as.data.frame(casos2)

fviz_pca_ind(res.pca, col.ind = "#DEDEDE", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = "red", size = 3) + geom_label(data = casos1, aes(x = PC1, y = PC2, label = rownames(casos1)),
             color = "white", fill = "red", size = 4)+
geom_point(data = casos2, aes(x = PC1, y = PC2), color = "blue", size = 3)+geom_label(data = casos2, aes(x = PC1, y = PC2, label = rownames(casos2)),
             color = "white", fill = "blue", size = 4)

Para el primer caso se eligieron los inmuebles 855 y 8264, el primero tiene un precio de 62 y el segundo de 1000. En consecuencia el sentido del componente principal 1 es de mayor costo a menor. Respecto al segundo caso se eligieron los inmuebles 5771 y 7663, el primero es de estrato 3 y el segundo de estrato 6, por lo tanto el eje va de menor a mayor estrato.

fviz_pca_biplot(res.pca, 
repel = TRUE,
habillage = vivienda$tipo,
col.var = "#034A94",
col.ind = c("#DEDEDE", "#034A94")
)

Se observan grupos en el grafico, en el cual los apartamentos se ubican diferencialmente de las casas en el plano, en el cual los apartamentos tienen menor tamaño y precio a mayor estrato. Mientras que las casas tienen mayor tamaño y precio a menor estrato.

fviz_pca_biplot(res.pca, 
repel = TRUE,
habillage = vivienda$zona,
col.var = "#034A94",
col.ind = c("#DEDEDE", "#034A94")
)

Se observan grupos en el grafico, en el cual se observa que los inmuebles en la zona sur y norte pueden diversidad en tamaño, precio y estrato. Sin embargo, en la zona norte se pueden encontrar inmuebles de menor estrato. Mientras que la zona oeste se caracteriza por mayores tamaños, precios y estrato, la zona oriente menor estrato, tamaño y precio.

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

vivienda_escalada_df <- as.data.frame(vivienda_escalada)

hc_viv <- hclust(dist_viv, method = 'complete')

cluster_assigments <- cutree(hc_viv, k = 3)

assigned_cluster <- vivienda_escalada_df %>% mutate(cluster = as.factor(cluster_assigments))


# gráfico de puntos
ggplot(assigned_cluster, aes(x = longitud, y = latitud, color = cluster)) +
geom_point(size = 4) +
geom_text(aes(label = cluster), vjust = -.8) +
theme_classic()

ggplot(assigned_cluster, aes(x = estrato, y = preciom, color = cluster)) +
geom_point(size = 4) +
geom_text(aes(label = cluster), vjust = -.8) +
theme_classic()

Analisis de las caracteristas de los clusters

#Añado la etiqueta del cluster a la base de datos original 
vivienda_cluster <- vivienda
vivienda_cluster$cluster <- as.factor(cluster_assigments)
#Calculo el promedio de cada variable por cluster
perfil_cluster <- vivienda_cluster %>%
  group_by(cluster) %>%
  summarise(
    precio_prom = mean(preciom),
    area_prom = mean(areaconst),
    estrato_prom = mean(estrato),
    banios_prom = mean(banios),
    parqueaderos_prom = mean(parqueaderos),
    habitaciones_prom = mean(habitaciones),
    n = n()
  )

perfil_cluster
## # A tibble: 3 × 8
##   cluster precio_prom area_prom estrato_prom banios_prom parqueaderos_prom
##   <fct>         <dbl>     <dbl>        <dbl>       <dbl>             <dbl>
## 1 1              257.      92.8         4.40        2.27              1.24
## 2 2              470.     215.          4.90        3.76              1.85
## 3 3              705.     208.          5.77        4.30              2.24
## # ℹ 2 more variables: habitaciones_prom <dbl>, n <int>

Se observa en la grafica de conglomerados se observan tres segmentos homogeneos, el primero se encuentra a mayor latitud y longitud de la ciudad con menor precio, estrato y tamaño. El segundo se encuentra en una latitud amplia y longitud central con precio, mayor tamaño y estrato intermedio. El tercer segmento de inmuebles corresponde a inmuebles ubicados en menor latitud y longitud con mayor precio, menor tamaño y mayor estrato. Respecto al segundo grafico, se observan tres segmentos los cuales se distribuyen en los 4 estratos incluidos, los menores estratos tienen menor precio a precio intermedio, los estratos altos tienen mayor precio.

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

Zona vs Tipo

tabla <- table(vivienda$zona, vivienda$tipo)
chisq.test(tabla)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla
## X-squared = 272.73, df = 3, p-value < 2.2e-16

R/ Existe dependencia de la zona y el tipo de inmueble

Zona vs Barrio

tabla <- table(vivienda$zona, vivienda$barrio)
chisq.test(tabla)
## Warning in chisq.test(tabla): Chi-squared approximation may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  tabla
## X-squared = 17070, df = 1029, p-value < 2.2e-16

R/ Existe dependencia de la zona y el tipo inmueble

Barrio vs Tipo

tabla <- table(vivienda$barrio, vivienda$tipo)
chisq.test(tabla)
## Warning in chisq.test(tabla): Chi-squared approximation may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  tabla
## X-squared = 1483.1, df = 343, p-value < 2.2e-16

R/ Existe dependencia de el barrio y el tipo inmueble

datos_cat <- vivienda %>%
  select(zona, barrio, tipo)

tipos <- levels(as.factor(datos_cat$tipo))

plots <- lapply(tipos, function(t){
  sub <- datos_cat %>% filter(tipo == t)
  tab <- table(sub$zona, sub$barrio)
  ca  <- CA(tab, graph = FALSE)

  fviz_ca_biplot(
    ca, repel = TRUE,
    select.row = list(contrib = 20),
    select.col = list(contrib = 5)
  ) + ggtitle(paste("CA Zona vs Barrio | Tipo:", t))
})

plots[[1]] / plots[[2]]

El analisis de correspondencia para los apartamentos representa el 67.8% de la variabilidad y para las casas representa el 37.8% de la variabilidad.

Los inmuebles se concentran en:

Tipo de Inmueble Zona Barrios Asociados
Apartamento Sur Valle de Lili
Apartamento Norte La Flora
Apartamento Oeste Normandia, Santa Teresita, Los Cristales
Casa Sur Ciudad Jardín
Casa Oriente Ciudad Cordoba, Alfonso Lopez
Casa Norte La Flora, Acopi

Conclusiones

1. Extructura del mercado: El analisis de componentes principales evidencio que la mayor variabilidad del mercado esta explicada por variables asociadas al tamaño, precio y nivel socioeconomico de la propierdad.

2. Segmentacion del mercado: El analisis de conglomerados permitio identificar tres segmentos:

Segmento Características
1 Viviendas de menor tamaño, menor precio y estrato socioeconómico bajo.
2 Viviendas de mayor tamaño, precio moderado y estrato socioeconómico medio.
3 Viviendas de tamaño moderado, precio alto y estrato socioeconómico alto.

3. Relaciones entre tipo de inmueble, zona y barrio: El análisis de correspondencia mostró dependencia estadísticamente significativa entre tipo de vivienda, zona y barrio. Se identifican concentraciones específicas de casas y apartamentos segun la zona y barrio, lo cual sugiere patrones territoriales de oferta.

Anexo

Anexo A - Version de R y sistema operativo R version 4.5.2 (2025-10-31)
Sistema Operativo: macOS Tahoe 26.2

Anexo B - Paquetes devtools mice tidyverse factoextra cluster dplyr FactoMineR gridExtra tcltk2 psych ggplot2 patchwork VIM

El código completo del análisis se encuentra integrado en el presente documento RMarkdown.