Introducción

El sector inmobiliario en Cali (Colombia), ha experimentado un notable crecimiento en los últimos años, impulsado por diversos factores como el aumento de la población, la inversión extranjera y el desarrollo de nuevos proyectos sociales y urbanísticos. Con el propósito de identificar algunos patrones, relaciones y segmentaciones relevantes entre las principales variables de la vivienda en la ciudad, se llevará a cabo un análisis holístico de modelos multivariados que permitan mejorar la toma de decisiones en cuanto a la compra, venta y valoración de propiedades.

Métodos

Para el desarrollo de este informe, se hará uso de técnicas y herramientas estadísticas para organizar, resumir y presentar los datos recopilados de acuerdo con la guía del curso de modelos estadisticos para la toma de decisiones, la cual seguirá las siguientes etapas:

  1. Análisis explotario de los datos.

  2. Análisis de modelos multivariados.

  3. Conclusiones y recomendaciones.

1. Análisis Exploratorio de Datos (EDA)

En este apartado, se realizará la carga de la base de datos original, se realizará una primera visualización de los datos obtenidos, además de los paquetes a utilizar para el desarrollo de la actividad.

1.1 Paquete de librerías.

Consolidado de paquete de librerias a utilizar en el proyecto:

library(paqueteMETODOS)
library(broom)
library(devtools)
library(dplyr)
library(ggplot2)
library(reshape2)
library(GGally)
library(naniar)
library(mice)
library(FactoMineR)
library(factoextra)
library(corrplot)
library(tidyr)
library(gridExtra)
library(cluster)
library(knitr)
library(rmarkdown)
library(kableExtra)
library(stargazer)

1.2 Importación y entendimiento de los datos

Antes de comenzar a procesar los datos, debemos conocer las características del conjunto de datos que tenemos. Para ello podemos mirar los siguientes puntos:

  • Número de registros y atributos.

  • Tipo de datos

  • Medida de centralidad o dispersión de los datos

  • Cálculo de la matriz de correlación de los datos

  • Cálculo de datos faltantes o perdidos

  • Cálculo de datos atipicos

Al realizar el proceso de importación, se observa que el conjunto inicial de datos cuenta con un total de 8322 registros (filas - observaciones) y 13 variables (columnas) con diferentes tipos de datos como: id, zona, piso, estrato, precio en millones de pesos COP, area construida, parqueadero, baños, habitaciones, tipo de vivienda, barrio, longitud y latitud. Los principales tipos de dato que nos encontramos son numérico y categórico.

#Descarga de la base de datos original
#devtools::install_github("dgonxalex80/paqueteMETODOS, force = TRUE") 
data(vivienda)

# Se crea una copia seguridad.
viviwork = vivienda

dim(vivienda)
## [1] 8322   13
# Aplicar la función class a cada columna del data frame
column_classes = sapply(vivienda, class)
# Convertir el resultado en un data frame
df_column_classes = data.frame(Tipo = column_classes, stringsAsFactors = FALSE)
# Mostrar el data frame resultante
print(df_column_classes)
##                   Tipo
## id             numeric
## zona         character
## piso         character
## estrato        numeric
## preciom        numeric
## areaconst      numeric
## parqueaderos   numeric
## banios         numeric
## habitaciones   numeric
## tipo         character
## barrio       character
## longitud       numeric
## latitud        numeric

Tal como se observa en la siguiente tabla, las variables piso (2638) y parqueadero (1605) son las variables con la mayor pérdida de datos (NA); equivalente al 32% y 19%, respectivamente. De igual forma, hay 3 filas en las que todos sus atributos son NA y posteriormente, se procederá a su posterior eliminación.

# Se visualiza la existencia de datos faltantes por medio de un data frame
faltantes = colSums(is.na(vivienda)) %>%
  as.data.frame()
colnames(faltantes) = "Faltantes"

kable(faltantes, caption = "Faltantes por variable") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), full_width = FALSE)
Faltantes por variable
Faltantes
id 3
zona 3
piso 2638
estrato 3
preciom 2
areaconst 3
parqueaderos 1605
banios 3
habitaciones 3
tipo 3
barrio 3
longitud 3
latitud 3

Al realizar el análisis de datos perdidos o faltantes en la base de datos, podemos concluir principalmente que:

  • Hay 4808 observaciones con datos completos para todas las variables.
  • Hay 1909 observaciones con datos para todas las variables excepto piso y,
  • Hay 876 observaciones con datos para la variable parqueaderos y dos observaciones que presentan ausencia total de datos.
#Posibles Anexos o dejarlos en la linea
md.pattern(vivienda, rotate.names = TRUE)

##      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
vis_miss(vivienda_faltantes)

gg_miss_var(vivienda, show_pct = TRUE)

El análisis de correlación de las variables muestra que, en teoria hay baja relación de las variables. Alcanza un valor máximo de 0.69 (moderado) entre variables como parqueadero y precio o, el area construida y el precio.

# Seleccionar solo las columnas numéricas
numeric_columns = sapply(vivienda, is.numeric)
vivienda_numeric = vivienda[, numeric_columns]

# Calcular la matriz de correlación
correlation_matrix = cor(vivienda_numeric, use = "complete.obs")

# Convertir la matriz de correlación en un formato largo
melted_correlation_matrix = melt(correlation_matrix)

# Crear un mapa de calor usando ggplot2
ggplot(data = melted_correlation_matrix, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(low = "red", high = "blue", mid = "white", midpoint = 0, limit = c(-1, 1), space = "Lab", name = "Correlación") +
  geom_text(aes(label = round(value, 2)), color = "black", size = 2) +  # Añadir números de correlación
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
  coord_fixed()

En el cálculo de datos atípicos se puede observar que hay una gran cantidad de datos outliers para las variables de precio y area construida. Sin embargo, no se procede a su eliminación por motivos como: medir los modelos multivariables y coincide con la relación de las variables y el análisis del sector en la vivienda en Cali (hay zonas de alto costo y alto nivel de area construida).

# Seleccionar las variables de interés
vivienda_subset = vivienda[, c("piso", "preciom", "areaconst", "parqueaderos", "banios", "habitaciones")]
# Convertir el conjunto de datos a formato largo
vivienda_melted = melt(vivienda_subset)

# Crear un boxplot para todas las variables seleccionadas
ggplot(vivienda_melted, aes(x = variable, y = value)) +
  geom_boxplot(fill = "#9abaf9", color = "#001865") +
  labs(title = "Datos Atípicos de variables numéricas",
       x = "Variable",
       y = "Valores") +
  theme_minimal()

2. Preparación de los datos

En esta etapa se define una secuencia de pasos que modifican los datos para reducir situaciones que puedan ser causa de fallo o deficiencia en el proceso del modelado previsto para esta actividad. En este caso se van a realizar las siguientes actividades:

2.1 Completar los datos faltantes utilizando la media para atributos numéricos. 2.2 Eliminación de registros totalmente vacios. 2.3 Eliminación de variables que no aportarían a la modelación (id, barrio, longitud, latitud). Además se pasará el piso a variable numérica. 2.4 Preparación de los subset para trabajar el analisis con variables cuantitativas (Analisis de Componentes Principales PCA y Analisis de Conglomerados) y categoricas (Analisis de Correspondencia Multiple)

2.1 Completar los datos faltantes utilizando la media para atributos numéricos.

De acuerdo al analisis realizado a esta misma base de datos en trabajos anteriores, para rellenar los datos faltantes de las variable piso y parqueadero, tendremos en cuenta su relación con los atriburos apartamento y casa.

Para piso, en apartamento con el valor cinco (5) y para casa con valor de (3). Por su parte, para la variable parqueadero, tanto para apartamento como para casa, se utilizará el promedio general correspondiente al valor de uno (1). Esto, teniendo en cuenta lo mencionado respecto a que actualmente las casas y apartamentos en la ciudad no poseen parqueadero o son de tipo comunitario, de acuerdo con el análisis de medidas de tendencia central.

# Rellenar los datos faltantes en la columna "piso"
vivienda$piso = ifelse(
  is.na(vivienda$piso) & vivienda$tipo == "Apartamento", 5,
  ifelse(is.na(vivienda$piso) & vivienda$tipo == "Casa", 3, 
         vivienda$piso)
)


# Rellenar los datos faltantes en la columna "parquea"
vivienda$parqueaderos = ifelse(is.na(vivienda$parqueaderos) & (vivienda$tipo == "apartamento" | viviwork$tipo == "casa"), 
                           1, 
                           vivienda$parqueaderos)

#Corroboramos nuevamente faltantes
faltantesNew = colSums(is.na(viviwork)) %>%
  as.data.frame()

2.2 Eliminación de registros totalmente vacios.

# Eliminar las filas con valores NA en viviwork
vivienda = vivienda[complete.cases(viviwork), ]
faltantesNew = colSums(is.na(vivienda)) %>% as.data.frame() 

Se corroborá por medio de la tabla, que los datos faltantes hayan sido rellenados, para poder avanzar con el siguiente punto del proyecto.

# Crear y mostrar la tabla con kableExtra
kable(faltantesNew, 
      caption = "Datos faltantes",
      col.names = c("Variable", "Faltantes"),
      align = "c",
      digits = 0,
      format = "html",
      table.attr = "class='table table-striped table-hover'",
      row.names = TRUE) %>%
  kable_styling(full_width = FALSE)
Datos faltantes
Variable Faltantes
id 0
zona 0
piso 0
estrato 0
preciom 0
areaconst 0
parqueaderos 0
banios 0
habitaciones 0
tipo 0
barrio 0
longitud 0
latitud 0

2.3 Eliminación de variables que no aportarían a la modelación (id, barrio,longitud y latitud). Cambio de la variable piso a numérica.

#Antes, se crea una copia de lo que se ha avanzando
vivienda_nw = vivienda

# Eliminar las columnas id, barrio, longitud y latitud
vivienda = subset(vivienda, select = -c(id, longitud, latitud, barrio))

#Cambiar piso a numerico y estrato a categórico
vivienda$piso = as.numeric(vivienda$piso)
vivienda$estrato = as.character(vivienda$estrato)
head(vivienda)

2.4 Creación de los subset para trabajar el análisis con variables cuantitativas (Análisis de Componentes Principales PCA y Analisis de Conglomerados) y categóricas (Análisis de Correspondencia Multiple)

#subset para variables cuantitativas y cuantitativas
vivienda_numericas = vivienda[, c("piso", "preciom", "areaconst", "parqueaderos", "banios", "habitaciones")]
vivienda_categoricas = vivienda[, c("zona", "tipo", "estrato")]

head(vivienda_numericas)
head(vivienda_categoricas)

3. Modelos multivariados

3.1 Analisis de Componente Principales (PCA)

El objetivo de esta técnica es reducir la dimensionalidad del conjunto de datos, con la mayor varianza posible, a fin de 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.

En principio, vamos a calcular la variabilidad de cada una de las columnas. Con ello, podemos observar que la mayor variabilidad la tienen el precio (106,026) y el área construida (19,125).

varianzas = apply(vivienda_numericas, 2, var)
df_varianzas = data.frame(Variable = names(varianzas), Varianza = varianzas)
print(df_varianzas, row.names = FALSE)
##      Variable     Varianza
##          piso 7.146887e+00
##       preciom 1.060265e+05
##     areaconst 1.912528e+04
##  parqueaderos 1.208368e+00
##        banios 1.825867e+00
##  habitaciones 1.771170e+00

A continuación, se muestra la información de la desviación estadar de cada una de las componentes principales y las rotaciones de sus combinaciones lineales en las variables continuas. La matriz de rotación ha calculado 6 componentes principales (vectores propios) a partir de las variables.

De igual forma, podemos observar que las primeras tres componentes principales nos dan una explicabilidad del 86% y las primeras cuatro ya componen un 90% de variabilidad en nuestro conjunto de datos.

Los graficos de codo y de varianza acumulada, sugieren la elección entre 2 y 3 componentes principales.

Del gráfico biplot podemos observar que las variables de preciom, area, baños y parqueaderos están fuertemente correlacionados entre sí y con PC1 (apuntan en direcciones similares). La variable habitaciones tiene una fuerte relación con PC2 y piso tiene una correlación negativa con PC1 y PC2 (apunta en dirección opuesta).

#procedemos a hacer estandarización de los datos
acp = prcomp(vivienda_numericas,
             center = TRUE, scale = TRUE)
#Resumen
print(acp)
## Standard deviations (1, .., p=6):
## [1] 1.8335756 1.0340089 0.8553449 0.5882495 0.5520768 0.4317233
## 
## Rotation (n x k) = (6 x 6):
##                     PC1         PC2          PC3         PC4        PC5
## piso          0.1303842 -0.83216185 -0.517488231  0.02596413 -0.1358974
## preciom      -0.4559601 -0.32247810  0.264482021 -0.35698936  0.1622554
## areaconst    -0.4798166  0.04280053 -0.009048408 -0.48839255 -0.6010120
## parqueaderos -0.4315969 -0.23714602  0.378193665  0.74696838 -0.2128396
## banios       -0.4785793 -0.03420384 -0.205573515 -0.04099560  0.7232466
## habitaciones -0.3599478  0.37983485 -0.690566723  0.27150467 -0.1600102
##                      PC6
## piso          0.05975193
## preciom      -0.68146114
## areaconst     0.41002386
## parqueaderos  0.10579715
## banios        0.45029456
## habitaciones -0.38725009
summary(acp)
## Importance of components:
##                           PC1    PC2    PC3     PC4    PC5     PC6
## Standard deviation     1.8336 1.0340 0.8553 0.58825 0.5521 0.43172
## Proportion of Variance 0.5603 0.1782 0.1219 0.05767 0.0508 0.03106
## Cumulative Proportion  0.5603 0.7385 0.8605 0.91814 0.9689 1.00000
plot(acp, type = "l", main = "Gráfico de sedimentación")
abline(h = 1, col = "red", lty = 2)
legend("topright", legend = c("Autovalores", "Autovalor = 1"),
       col = c("black", "red"), lty = c(1, 2))

var_explained = acp$sdev^2 / sum(acp$sdev^2)
cumvar_explained = cumsum(var_explained)
plot(cumvar_explained, type = "b", ylim = c(0, 1),
     xlab = "Número de componentes", ylab = "Proporción de varianza explicada",
     main = "Varianza explicada acumulada")
abline(h = 0.8, col = "red", lty = 2)

biplot(acp, scale = 0, cex = 0.6, col = c("#9FB6CD", "#EE6363"))

# Contribuciones de las variables
loadings = acp$rotation
contrib = loadings^2
for(i in 1:ncol(contrib)) {
  contrib[,i] <- contrib[,i] / sum(contrib[,i]) * 100
}
print(round(contrib, 2))
##                PC1   PC2   PC3   PC4   PC5   PC6
## piso          1.70 69.25 26.78  0.07  1.85  0.36
## preciom      20.79 10.40  7.00 12.74  2.63 46.44
## areaconst    23.02  0.18  0.01 23.85 36.12 16.81
## parqueaderos 18.63  5.62 14.30 55.80  4.53  1.12
## banios       22.90  0.12  4.23  0.17 52.31 20.28
## habitaciones 12.96 14.43 47.69  7.37  2.56 15.00

El eigenvalue ayuda a determinar la importancia de cada componente principal. En teoría, representa la cantidad de varianza que ese componente captura o explica en los datos originales

res.pca = PCA(vivienda_numericas, ncp = 3,graph = TRUE)

res.pca$eig
##        eigenvalue percentage of variance cumulative percentage of variance
## comp 1  3.3619994              56.033324                          56.03332
## comp 2  1.0691744              17.819573                          73.85290
## comp 3  0.7316149              12.193581                          86.04648
## comp 4  0.3460375               5.767291                          91.81377
## comp 5  0.3047888               5.079814                          96.89358
## comp 6  0.1863850               3.106417                         100.00000
res.pca$var
## $coord
##                   Dim.1       Dim.2       Dim.3
## piso         -0.2390693  0.86046275  0.44263091
## preciom       0.8360373  0.33344522 -0.22622334
## areaconst     0.8797799 -0.04425612  0.00773951
## parqueaderos  0.7913655  0.24521109 -0.32348601
## banios        0.8775113  0.03536707  0.17583625
## habitaciones  0.6599914 -0.39275261  0.59067271
## 
## $cor
##                   Dim.1       Dim.2       Dim.3
## piso         -0.2390693  0.86046275  0.44263091
## preciom       0.8360373  0.33344522 -0.22622334
## areaconst     0.8797799 -0.04425612  0.00773951
## parqueaderos  0.7913655  0.24521109 -0.32348601
## banios        0.8775113  0.03536707  0.17583625
## habitaciones  0.6599914 -0.39275261  0.59067271
## 
## $cos2
##                   Dim.1       Dim.2        Dim.3
## piso         0.05715414 0.740396139 1.959221e-01
## preciom      0.69895845 0.111185715 5.117700e-02
## areaconst    0.77401271 0.001958604 5.990001e-05
## parqueaderos 0.62625929 0.060128479 1.046432e-01
## banios       0.77002616 0.001250830 3.091839e-02
## habitaciones 0.43558868 0.154254613 3.488942e-01
## 
## $contrib
##                  Dim.1      Dim.2        Dim.3
## piso          1.700005 69.2493341 26.779406959
## preciom      20.789963 10.3992124  6.995073955
## areaconst    23.022393  0.1831885  0.008187369
## parqueaderos 18.627585  5.6238234 14.303044847
## banios       22.903816  0.1169902  4.226047005
## habitaciones 12.956239 14.4274513 47.688239865

En los siguientes gráficos podemos observar la varianza explicada, en donde la dimensión 1 tiene un 56% de variabilidad seguida de la siguiente dimensión con un 17,8%, lo que es mayormente mas importante en terminos de explicar variabilidad.

En el gráfico de calor de cos2, no se observan clusters claramente definidos, pero hay algunas agrupaciones sutiles, tambien hay una mayor concentración de puntos en el centro del gráfico y algunos outliers son visibles, especialmente en los extremos derecho y superior.

fviz_eig(res.pca, addlabels = TRUE)

fviz_pca_ind(res.pca,
             col.ind = "cos2",
             gradient.cols = c("#00AFBB", "#E7B800","#DC4E07"),
             repel = FALSE)

Análisis de la contribución de las variables a la dimensión 1 y 2 en el PCA. Para la dimensión uno, se puede ver la contribución que tienen las variables area construida, baños, precio y parqueaderos. Por su parte, en la dimensión dos la variable piso es la que más inferencia tiene.

fviz_contrib(res.pca, choice = "var", axes = 1, top=10)

fviz_contrib(res.pca, choice = "var", axes = 2, top=10)

3.2 Analisis de Conglomerados

Este metodo sugiere agrupar las propiedades residenciales en segmentos homogéneos con características similares para entender las dinámicas de las ofertas específicas en diferentes variables del sector inmobiliario.

corrplot(cor(vivienda_numericas))

Uno de los primeros pasos, es conocer la cantidad de cluster y para ello, existen tres principales formas de saber el numero de factores, entre las más populares se encuentran:

  1. elbow

  2. silhouette

  3. gap_stat (este método demora mucho la renderización, por la gran cantidad de datos. Se omitirá su presentación gráfica en el informe)

Con el primer metodo “wss”, se puede observar un codo a partir del 3 o 4 cluster, mientras que el segundo metodo “silhouette”, nos sugiere el uso de 2 cluster.

fviz_nbclust(vivienda_numericas, kmeans, method="wss")

fviz_nbclust(vivienda_numericas, kmeans, method="silhouette")

En las siguientes gráficas, se observa la representación visual para dos, tres y cuatro cluster. Posterior a ello, analizaremos el coeficiente para conocer su distribución y rendimiento.

k2 = kmeans (vivienda_numericas, centers=2, nstar=25)
fviz_cluster(k2, data=vivienda_numericas)

k3 = kmeans (vivienda_numericas, centers=3, nstar=25)
fviz_cluster(k3, data=vivienda_numericas)

k4 = kmeans (vivienda_numericas, centers=4, nstar=25)
fviz_cluster(k4, data=vivienda_numericas)

Al realizar el análisis del coeficiente de silhouette para 2, 3 y 4 cluster, podemos observar un mejor rendimiento en anchura promedio total del silhouette para dos (2) cluster: 0.67. Lo anterior, recordando que un valor cercano a 1 indica que los datos están bien agrupados, un valor cercano a cero los datos están cerca del limite de los cluster y -1 los datos están mal agrupados. A una mayor cantidad de cluster, disminuye ese coeficiente.

De igual forma, el gráfico indica que el Cluster 1 (rojo) está bastante bien definido y sus puntos están bien agrupados, con una anchura media del silhouette alta.mientras que el cluster 2 (verde) es menos cohesivo, lo que sugiere que algunos puntos podrían estar mal agrupados o que este cluster podría beneficiarse de una revisión o un ajuste en el número de clusters. Sin embargo, al hacer el aumento de cluster, empeora el resultado por lo cual seguiremos con esta elección.

La línea punteada roja muestra la anchura media del silhouette global, y aunque para los cluster 3 y 4 indica que cada cluster lo pasa; se evidencia una perdida en el coeficiente.

#calcular el coeficiente de silhouette
set.seed(123)

silhouette_valuesk2 = silhouette(k2$cluster, dist(vivienda_numericas))
silhouette_valuesk3 = silhouette(k3$cluster, dist(vivienda_numericas))
silhouette_valuesk4 = silhouette(k4$cluster, dist(vivienda_numericas))

fviz_silhouette(silhouette_valuesk2)
##   cluster size ave.sil.width
## 1       1 3999          0.72
## 2       2  809          0.40

fviz_silhouette(silhouette_valuesk3)
##   cluster size ave.sil.width
## 1       1 3218          0.66
## 2       2 1220          0.38
## 3       3  370          0.45

fviz_silhouette(silhouette_valuesk4)
##   cluster size ave.sil.width
## 1       1  321          0.40
## 2       2 2413          0.62
## 3       3 1392          0.34
## 4       4  682          0.33

vivienda_numericas$clus = as.factor(k2$cluster)
head(vivienda_numericas)
## # A tibble: 6 × 7
##    piso preciom areaconst parqueaderos banios habitaciones clus 
##   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <fct>
## 1     2     400       280            3      5            3 1    
## 2     1     260        90            1      2            3 1    
## 3     1     240        87            1      3            3 1    
## 4     1     220        52            2      2            3 1    
## 5     1     310       137            2      3            4 1    
## 6     2     320       150            2      4            6 1

Hay una mejor sectorización de la contribución de los atributos, sin embargo el siguiente gráfico muestra que con dos cluster es suficiente para interpretar el resultado.

vivienda_numericas$clus = factor(vivienda_numericas$clus)
data_long = gather(vivienda_numericas, caracteristica, valor, piso:habitaciones, factor_key=TRUE)

ggplot(data_long, aes(x = caracteristica, y = valor, group=clus, colour = clus)) + 
  stat_summary(fun = mean, geom="pointrange", size = 1) +
  stat_summary(geom="line") +
  labs(title = "Perfil de clusters por características de vivienda",
       x = "Características", 
       y = "Valor promedio",
       colour = "Cluster") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Ahora, se propone hacer una caracterización sobre los resultado en los que incide cada cluster (para este caso, dos (2)). Se realiza un analisis descriptivo de los promedios en las variables del piso, precio, del area construida, parqueaderos, baños y habitaciones. En esta caracterización se puede observar los valores promedios por cluster, para el 1ro es de 336 millones y el 2do de 1053 millones (recodando como valores mínimos 58 millones y máximos 1999 millones). De igual forma se presenta un análisis similar en el área construida donde los valores oscilar en la base de datos principal entre 210 y 800 mtrs, agrupados en promedio de 135 y 367 metros para los cluster 1 y 2, respectivamente. Este valor puede representar una tendencia mas conjunta.

vivienda_numericas$cluster = as.factor(k2$cluster)

# Calcular el promedio de las variables seleccionadas por cluster
resumen_clusters = aggregate(cbind(preciom, areaconst, parqueaderos, banios, habitaciones) ~ cluster, 
                              data = vivienda_numericas, 
                              FUN = mean)

resumen_tabla <- resumen_clusters %>%
  kable(caption = "Resumen por Cluster")

print(resumen_tabla)
## 
## 
## Table: Resumen por Cluster
## 
## |cluster |   preciom| areaconst| parqueaderos|   banios| habitaciones|
## |:-------|---------:|---------:|------------:|--------:|------------:|
## |1       |  336.5229|  135.6975|     1.522131| 2.873218|     3.413854|
## |2       | 1053.6551|  367.8579|     3.263288| 4.929543|     4.309024|

3.3 Analisis de Correspondencia

En este modelo, buscamos examinar la relación entre las variables categóricas (tipo de vivienda, zona y estrato), para identificar patrones de comportamiento de la oferta en mercado inmobiliario.

Hay que mencionar que se exluyen algunas variables como el barrio, latitud y longitud pues en principio no aportar valor al análisis y además, incluir el barrio con sus más de 300 categorías dificulta su interpretación. De igual forma, se incluye en el subset el estrato pues representa una variable de tipo ordinal.

Con lo anterior, primero se observará la frecuencia que tiene cada variable, resaltando la Zona Sur, las viviendas de tipo apartamento y el Estrato 5 como las de mayor incidencia y participación.

f1 = ggplot(vivienda_categoricas, aes(x=zona)) +   geom_bar(fill="#EEDC82") +  theme(axis.text.x = element_text(angle = 45, hjust = 1))

f2 = ggplot(vivienda_categoricas, aes(x=tipo)) +   geom_bar(fill="#FF7256")

f3 = ggplot(vivienda_categoricas, aes(x=estrato)) +   geom_bar(fill="#3A5FCD")

grid.arrange(f1, f2, f3, ncol=2, nrow=2)

El siguiente gráfico indica unas relaciones muy fuertes entre los apartamentos hacia la zona sur y las casas en la zona norte de la Ciudad, a su vez asociados a estratos medio alto y alto (4 – 5). La zona oeste la comprenden estratos altos, y hacia el centro y oriente los medios.

res.acm = MCA(vivienda_categoricas, graph = FALSE)
fviz_mca_var(res.acm, repel=TRUE, col.var = "#104E8B")

Esta función esta asociada con la varianza, donde se puede determinar el valor individual de cada una de las dimensiones, el valor porcentual y el valor acumulado.

eigenval = get_eigenvalue(res.acm)
head(eigenval)
##       eigenvalue variance.percent cumulative.variance.percent
## Dim.1  0.5416488         20.31183                    20.31183
## Dim.2  0.4594459         17.22922                    37.54105
## Dim.3  0.3986773         14.95040                    52.49145
## Dim.4  0.3333715         12.50143                    64.99288
## Dim.5  0.3188668         11.95750                    76.95039
## Dim.6  0.2679131         10.04674                    86.99713

De igual forma, para determinar el numero de componentes principales se puede ejecutar un ScreePlot ordenado de mayor a menor, de como se reduce la variabilidad de la varianza.

fviz_screeplot(res.acm, addlabels = TRUE)

A continuación podemos observar la contribución de las categorías variables a las dimensiones. La linea discontinua roja, indica el valor promedio esperado si las contribuciones fueran uniformes.

Se puede concluir que para la primera dimensión, las variables estrato tres y zonas oriente, centro y oeste son las que mayor contribución tiene y, para la dimensión dos, la zona oeste seguido de estrato 6 y 4.

fviz_contrib(res.acm, choice="var", axes=1, top=10)

fviz_contrib(res.acm, choice="var", axes=2, top=10)

4. Conclusiones y recomendaciones

Conclusiones

En general hay variables críticas y determinantes como lo son el precio y el área a construida, además de la influencia de datos faltantes en variables parqueadero y piso en el análisis multivariado. Sin embargo, estas representan la realidad de la oferta de la vivienda en la ciudad de Cali (la relación entre el precio y el tamaño de la vivienda mostró una tendencia clara, donde las viviendas más grandes tienden a tener precios más altos) reflejado en los modelos multivariados que se detallaron en el desarrollo del ejercicio.

EL análisis de componentes principales (PCA), que mide las variables numéricas, nos muestra la gran contribución que tienen asociadas el precio y el área construida, lo cual las hace muy útiles en el conjunto de dimensiones a conservar.

El análisis de conglomerados ratifica la visión proporcionada por el PCA. Hay una gran tendencia a clusterizar conjuntamente la variable precio y área. Las métricas funcionan mejor cuando existen dos cluster, indicando mejor agrupamiento de las variables. El ruido está efectuado principalmente por el precio.

El análisis de correspondencia está determinado en principio por tres variables, lo que puede resultar siendo un reto. Sin embargo, es suficiente para indicar relaciones que el investigador supone como las zonas de la ciudad, el estrato y el tipo de vivienda (conocer el sector inmobiliario), lo que indica la importancia de adaptar la oferta de viviendas a las preferencias locales.

Recomendaciones:

En importante tener en cuenta para una oferta de vivienda el conjunto de variables comprendidas entre el precio, el área, los baños y el parqueadero. El área a construir aumenta considerablemente con el número de baños y muestra sensibilidad con el número de habitaciones, al igual que el precio de la vivienda si incluye parqueaderos.

Habría que validar la importancia de la variable piso en la oferta, pues marca como una preferencia fuerte y aparte. Aunque, hay que resaltar que hubo datos imputados en este campo.

Lo anterior con el fin de considerar estrategias de nichos personalizados, identificando preferencias y comportamientos del consumidor, si se busca vivienda familiar, unipersonal, con mascotas que van a depender mucho del área y el precio y, ayuda a definir adecuadamente el mercado al que se quiere apuntar. De esta manera, se pueden ofrecer viviendas que satisfagan un conjunto general de necesidades, tanto en términos de infraestructura como de ubicación.