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.

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 preferencias del mercado.

Análisis de Conglomerados: Agrupar las propiedades residenciales en segmentos homogéneos con características similares para entender las dinámicas y demandas 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) y las variables numéricas (precio, área construida, número de parqueaderos, baños, habitaciones) para identificar patrones de comportamiento del 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.

Desarrollo

# devtools::install_github("dgonxalex80/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
## Loading required package: boot
## Loading required package: broom
## Loading required package: GGally
## Loading required package: ggplot2
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
## Loading required package: gridExtra
## Loading required package: knitr
## Loading required package: summarytools
data(vivienda)
str(vivienda)
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ id          : num [1:8322] 1147 1169 1350 5992 1212 ...
##  $ zona        : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ piso        : chr [1:8322] NA NA NA "02" ...
##  $ estrato     : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
##  $ preciom     : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
##  $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
##  $ banios      : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
##  $ barrio      : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
##  $ longitud    : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
##  - attr(*, "spec")=List of 3
##   ..$ cols   :List of 13
##   .. ..$ id          : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ zona        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ piso        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ estrato     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ preciom     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ areaconst   : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ parqueaderos: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ banios      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ habitaciones: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ tipo        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ barrio      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ longitud    : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ latitud     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   ..$ default: list()
##   .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
##   ..$ delim  : chr ";"
##   ..- attr(*, "class")= chr "col_spec"
##  - attr(*, "problems")=<externalptr>

1.Exploraciòn de la base de datos

# Mostrar las primeras filas del conjunto de 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>
# Mostrar las dimensiones del conjunto de datos (número de filas y columnas)
dim(vivienda)
## [1] 8322   13

El conjunto de datos con el que se está trabajando está compuesto por 8322 filas y 13 columnas, lo que se traduce en 8322 observaciones (viviendas) con 13 variables para cada una de ellas.

# Resumen estadístico de las variables numéricas
summary(vivienda)
##        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
library(ggplot2)

# Gráfico de dispersión entre 'areaconst' y 'preciom' con color arcoíris
ggplot(vivienda, aes(x = areaconst, y = preciom, color = areaconst)) +
  geom_point() +
  scale_color_gradient(low = "blue", high = "red") +
  ggtitle("Relación entre área construida y precio")
## Warning: Removed 3 rows containing missing values (`geom_point()`).

El grafico muestra una relación positiva entre el área construida y el precio de las viviendas ya que a medida que aumenta el área construida, también aumenta el precio. La tendencia es lineal, con una pendiente positiva. Existe una alta dispersión de los puntos alrededor de la línea de tendencia.

# Se carga la librería `tidyverse` para el manejo de datos
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ lubridate 1.9.3     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::combine() masks gridExtra::combine()
## ✖ dplyr::filter()  masks stats::filter()
## ✖ dplyr::lag()     masks stats::lag()
## ✖ tibble::view()   masks summarytools::view()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# Se calcula el porcentaje de valores NA para cada variable
porcentaje_na <- map_dfr(names(vivienda), ~ {
  data.frame(variable = .x, porcentaje_na = round((sum(is.na(vivienda[[.x]])) / length(vivienda[[.x]])) * 100, 2))
})

# Ordenar variables por porcentaje de NAs de mayor a menor
porcentaje_na <- porcentaje_na %>%
  arrange(desc(porcentaje_na))

# Diagrama 
ggplot(porcentaje_na, aes(x = reorder(variable, porcentaje_na), y = porcentaje_na, fill = variable)) +
  geom_bar(stat = "identity") +
  labs(title = "Porcentaje de NA's en la base de datos vivienda",
       x = "Variable",
       y = "% NA's",
       fill = "Variable") +
  theme(legend.position = "bottom")

# Imprimir porcentaje de NAs
print(porcentaje_na)
##        variable porcentaje_na
## 1          piso         31.70
## 2  parqueaderos         19.29
## 3            id          0.04
## 4          zona          0.04
## 5       estrato          0.04
## 6     areaconst          0.04
## 7        banios          0.04
## 8  habitaciones          0.04
## 9          tipo          0.04
## 10       barrio          0.04
## 11     longitud          0.04
## 12      latitud          0.04
## 13      preciom          0.02

De acuerdo con el análisis univariado de la base de datos, los atributos “piso” y “parqueadero” presentan la mayor cantidad de datos faltantes, con 31,70% y 19,29% de registros ausentes, respectivamente. Los 11 atributos restantes tienen un máximo de 0,04%.

La presencia significativa de valores faltantes en las variables ‘piso’ y ‘parqueadero’ podría comprometer la precisión del análisis y la confiabilidad de los resultados. Por tanto, para abordar este desafío, se optará por eliminar estas características del conjunto de datos.

Además, se eliminará el atributo barrio y ‘id’, dado que su presencia no aporta valor sustancial al análisis ni al tratamiento de los datos.

2. Limpieza de la base de datos

# Verificar los nombres de las columnas del conjunto de datos
colnames(vivienda)
##  [1] "id"           "zona"         "piso"         "estrato"      "preciom"     
##  [6] "areaconst"    "parqueaderos" "banios"       "habitaciones" "tipo"        
## [11] "barrio"       "longitud"     "latitud"
# Eliminando las columnas 'id', 'piso', 'barrio' y 'parqueaderos' usando subset()
vivienda_limpia <- subset(vivienda, select = -c(id, piso, barrio, parqueaderos))

# Eliminando filas con valores faltantes
vivienda_limpia <- vivienda_limpia[complete.cases(vivienda_limpia), ]

# Conteo de valores faltantes
sum(is.na(vivienda_limpia)) 
## [1] 0
# Verificando la estructura del nuevo conjunto de datos
str(vivienda_limpia)
## tibble [8,319 × 9] (S3: tbl_df/tbl/data.frame)
##  $ zona        : chr [1:8319] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ estrato     : num [1:8319] 3 3 3 4 5 5 4 5 5 5 ...
##  $ preciom     : num [1:8319] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8319] 70 120 220 280 90 87 52 137 150 380 ...
##  $ banios      : num [1:8319] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8319] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8319] "Casa" "Casa" "Casa" "Casa" ...
##  $ longitud    : num [1:8319] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8319] 3.43 3.43 3.44 3.44 3.46 ...

Después de eliminar las columnas ‘id’, ‘piso’, ‘barrio’ y ‘parqueadero’, y de eliminar las filas con datos faltantes, la nueva base de datos consta de 8,319 filas y 9 columnas. Las columnas incluyen ‘zona’, ‘estrato’, ‘preciom’, ‘areaconst’, ‘banios’, ‘habitaciones’, ‘tipo’, ‘longitud’ y ‘latitud’, con datos de tipo caracter (chr) y numérico (num).

# Convertir la variable 'zona' a factor con etiquetas numéricas
vivienda$zona <- factor(vivienda$zona,
                        levels = c("Zona Centro", "Zona Norte", "Zona Oeste", "Zona Oriente", "Zona Sur"),
                        labels = c(1, 2, 3, 4, 5))

# Convertir la variable 'tipo' a factor con etiquetas numéricas
vivienda$tipo <- factor(vivienda$tipo,
                        levels = c("Casa", "Apartamento"),
                        labels = c(1, 2))

# Mostrar las primeras filas de la tabla actualizada
head(vivienda, 10)
## # A tibble: 10 × 13
##       id zona  piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <fct> <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  1147 4     <NA>        3     250        70            1      3            6
##  2  1169 4     <NA>        3     320       120            1      2            3
##  3  1350 4     <NA>        3     350       220            2      2            4
##  4  5992 5     02          4     400       280            3      5            3
##  5  1212 2     01          5     260        90            1      2            3
##  6  1724 2     01          5     240        87            1      3            3
##  7  2326 2     01          4     220        52            2      2            3
##  8  4386 2     01          5     310       137            2      3            4
##  9  1209 2     02          5     320       150            2      4            6
## 10  1592 2     02          5     780       380            2      3            3
## # ℹ 4 more variables: tipo <fct>, barrio <chr>, longitud <dbl>, latitud <dbl>

3.Análisis de Componentes Principales (PCA)

# Revisar la presencia de datos faltantes
library(mice)
## 
## Attaching package: 'mice'
## The following object is masked from 'package:stats':
## 
##     filter
## The following objects are masked from 'package:base':
## 
##     cbind, rbind
md.pattern(vivienda_limpia)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

##      zona estrato preciom areaconst banios habitaciones tipo longitud latitud  
## 8319    1       1       1         1      1            1    1        1       1 0
##         0       0       0         0      0            0    0        0       0 0

La gráfica indica que no se presentan datos faltantes

# Seleccionar subconjunto de variables y escalar
vivienda_limpiaZ <- vivienda_limpia[, 2:5] %>%
  scale()

# Visualizar los primeros 6 registros
head(vivienda_limpiaZ)
##         estrato    preciom  areaconst      banios
## [1,] -1.5872276 -0.5595498 -0.7339949 -0.07793773
## [2,] -1.5872276 -0.3465670 -0.3842568 -0.77811479
## [3,] -1.5872276 -0.2552886  0.3152194 -0.77811479
## [4,] -0.6156201 -0.1031580  0.7349051  1.32241640
## [5,]  0.3559875 -0.5291236 -0.5940997 -0.77811479
## [6,]  0.3559875 -0.5899759 -0.6150839 -0.07793773
# Análisis de Componentes Principales (ACP) para la vivienda limpia Z
prcomp(vivienda_limpiaZ)
## Standard deviations (1, .., p=4):
## [1] 1.6370866 0.8724805 0.5935867 0.4542907
## 
## Rotation (n x k) = (4 x 4):
##                 PC1         PC2         PC3         PC4
## estrato   0.4139520 -0.81614845  0.03322832 -0.40179758
## preciom   0.5598459 -0.07724738  0.32048598  0.76019348
## areaconst 0.4966474  0.52228812  0.46905805 -0.51043214
## banios    0.5182254  0.23483968 -0.82229506 -0.01111769
# Análisis de Componentes Principales (ACP) para el dataset "vivienda_limpia"

library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(paqueteMODELOS)

# Cargar el dataset
data("vivienda_limpia")
## Warning in data("vivienda_limpia"): data set 'vivienda_limpia' not found
# Seleccionar variables y escalar
vivienda_limpiaZ <- scale(vivienda_limpia[, 2:5])

# Realizar ACP y visualizar el gráfico 
res.pca <- prcomp(vivienda_limpiaZ)
fviz_eig(res.pca, addlabels = TRUE)

  • El primer componente principal (CP1) explica el 67% de la variabilidad total de los datos.
  • Los dos primeros componentes principales (CP1 y CP2) explican conjuntamente el 86% de la variabilidad total de los datos.
  • El gráfico de ACP indica que es posible resumir gran parte de la variabilidad de la base de datos con una sola variable (CP1).
# Definir los colores personalizados
colores_personalizados <- c("pink", "blue")

# Personalizar el gráfico
fviz_pca_var(res.pca,
              col.var = "contrib",
              gradient.cols = colores_personalizados,
              repel = TRUE,
              # Opciones adicionales (opcional)
              # axis.lty = 1,
              # legend.title = "Contribución a la variabilidad",
              # legend.position = "top",
              # point.size = 4
              )

Al visualizar las variables en el plano de los componentes principales permite identificar el sentido y la caracterización de los componentes (característica capturada por los vectores propios de Σ). En este ejercicio el primer componente principal está asociado principalmente con la variables estrato y precio, mientras que el segundo componente se puede asociar a la variable area construida.

# Para explicar el sentido de los ejes, se escogen cuatro casos extremos conformados por los siguientes clientes

datos <- rbind(vivienda_limpia[6000, ],
                vivienda_limpia[8300, ],
                vivienda_limpia[2, ],
                vivienda_limpia[3000, ])

datos <- as.data.frame(datos)
rownames(datos) = c("Cliente 6000", "Cliente 8300", "Cliente 002", "Cliente 3000")
datos
##                      zona estrato preciom areaconst banios habitaciones
## Cliente 6000     Zona Sur       5     440       210      5            5
## Cliente 8300     Zona Sur       5     240        68      2            3
## Cliente 002  Zona Oriente       3     320       120      2            3
## Cliente 3000   Zona Oeste       6     550       233      2            6
##                     tipo  longitud latitud
## Cliente 6000        Casa -76.52621 3.37787
## Cliente 8300 Apartamento -76.52673 3.37677
## Cliente 002         Casa -76.51237 3.43369
## Cliente 3000        Casa -76.54271 3.45003
library(factoextra)
casos1 <- rbind(res.pca$x[98,1:2],res.pca$x[778,1:2]) # CP1
rownames(casos1) = c("6000","8300")
casos1 <- as.data.frame(casos1)

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

fviz_pca_ind(res.pca, col.ind = "#DEDEDE", gradient.cols = c("#00FFFF", "#7FFF00", "#FF1493")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = "#FFFF00", size = 3) +
geom_point(data = casos2, aes(x = PC1, y = PC2), color = "#DA70D6", size = 3)

La vivienda 3000 se encuentra en una zona del gráfico que indica una mayor asociación con las variables de mayor peso en el primer componente principal (precio, estrato y área construida). Por otro lado, la vivienda 002 se ubica en una zona que indica una menor asociación con estas variables.

4.Análisis de Conglomerados

# Cargar los datos
if (!exists("vivienda_limpia"))
  
variables_clustering <- select(vivienda_limpia, estrato, preciom, areaconst, banios, habitaciones)


# Seleccionar las variables relevantes para el clustering
variables_clustering <- select(vivienda_limpia, estrato, preciom, areaconst, banios, habitaciones)

# Escalar las variables si es necesario
variables_clustering_scaled <- scale(variables_clustering)

# Determinar el número óptimo de clusters usando el método del codo
wcss <- numeric(10)
for (i in 1:10) {
  kmeans_fit <- kmeans(variables_clustering_scaled, centers = i, nstart = 10)
  wcss[i] <- kmeans_fit$tot.withinss
}

# Graficar el método del codo
plot(1:10, wcss, type = "b", pch = 19, frame = FALSE, 
     xlab = "Número de clusters (k)", ylab = "WCSS")

# Ajustar el modelo k-means con el número óptimo de clusters
k_optimo <- 3  
set.seed(123) 
modelo_kmeans <- kmeans(variables_clustering_scaled, centers = k_optimo, nstart = 10)

# Asignar las etiquetas de cluster a cada observación en los datos
cluster_labels <- as.factor(modelo_kmeans$cluster)

# Agregar las etiquetas de cluster al conjunto de datos original
vivienda_limpia_con_clusters <- mutate(vivienda_limpia, cluster = cluster_labels)

# Visualizar los clusters en función de algunas variables relevantes
ggplot(vivienda_limpia_con_clusters, aes(x = estrato, y = preciom, color = cluster)) +
  geom_point() +
  labs(title = "Clusters de Propiedades Residenciales",
       x = "Estrato Socioeconómico",
       y = "Precio de la Propiedad") +
  theme_minimal() +
  scale_color_discrete(name = "Cluster")

El gráfico ” Clusters de Propiedades Residenciales” presentado revela una correlación positiva entre el estrato socioeconómico, el precio de la propiedad y la cantidad de clusters. Se observa un aumento en el número de clusters a medida que se incrementa el estrato socioeconómico, con una mayor presencia en los estratos 5 y 6 en comparación con los estratos 1 y 2. De manera similar, el precio de la propiedad también se eleva en conjunto con el estrato socioeconómico.

El cluster 1 se presenta de manera similar en los estratos 3,4 y 5 y en menor proporciòn en el estatro 6, a diferencia del cluster 2 presentando mayor presencia en los estratos y y 6. El cluster 3 tiene presencia en los estratos 3,4 y y en menor proporciòn en el estrato 6.

# Calcular la matriz de correlación
correlation_matrix <- cor(variables_clustering_scaled)

# Convertir la matriz de correlación en un marco de datos
correlation_df <- as.data.frame(as.table(correlation_matrix))
colnames(correlation_df) <- c("Var1", "Var2", "Correlation")

# Graficar la matriz de correlación como un mapa de calor
ggplot(data = correlation_df, aes(x = Var1, y = Var2, fill = Correlation)) +
  geom_tile() +
  scale_fill_gradient2(low = "green", high = "red", mid = "white", midpoint = 0) +
  theme_minimal() +
  labs(title = "Matriz de Correlación")

Existe una fuerte correlación positiva entre el número de habitaciones y el número de baños (0,75). Existe una correlación positiva fuerte entre el estrato socioeconómico y el precio de la propiedad (0,75). Existe una correlación positiva moderada entre el número de habitaciones y el área construida (0,50). Existe una correlación positiva moderada entre el número de habitaciones y el precio de la propiedad (0,50) Existe una correlación positiva moderada entre el número de baños y el área construida (0,50). Existe una correlación positiva moderada entre el número de baños y el precio de la propiedad (0,50).

Se puede concluir que el número de habitaciones, baños y área construida están correlacionados positivamente con el precio de la propiedad.El estrato socioeconómico está fuertemente correlacionado con el precio de la propiedad.

# Gráfico de Barras (Distribución de Observaciones por Cluster para el Tipo de Propiedad)
ggplot(vivienda_limpia_con_clusters, aes(x = factor(cluster), fill = tipo)) +
  geom_bar(position = "fill") +
  labs(title = "Distribución de Observaciones por Cluster y Tipo de Propiedad", x = "Cluster", y = "Proporción") +
  theme_minimal()

El análisis del gráfico de distribución de observaciones por cluster y tipo de propiedad revela una clara diferenciación en la composición de los clusters según la tipología de vivienda.

El Cluster 1 se caracteriza por un predominio abrumador de apartamentos, con un 75% de las observaciones.El Cluster 2 presenta una distribución más equilibrada, con un 50% de apartamentos y un 50% de casas. Por último, el Cluster 3 se destaca por el dominio de las casas, con una proporción superior al 90% de las observaciones.

# Gráfico de Densidad (Distribución de Precios por Cluster)
ggplot(vivienda_limpia_con_clusters, aes(x = preciom, fill = cluster)) +
  geom_density(alpha = 0.5) +
  labs(title = "Distribución de Precios por Cluster", x = "Precio", y = "Densidad") +
  theme_minimal()

El cluster 1 tiene la mayor concentración de datos y se encuentra en el rango de precios entre 0 y 750.El cluster 2 tiene una distribución de precios más amplia que el cluster 1. Hay una cantidad significativa de datos en el rango de precios entre 500 y 1500, y también hay algunos puntos de datos en el rango de precios entre 1500 y 2000. Por ultimo el Cluster 3 tiene la distribución de precios más amplia. Hay algunos puntos de datos en el rango de precios entre 0 y 1000.

# Mapa de Clusters (Si tienes datos geoespaciales)
ggplot(vivienda_limpia_con_clusters, aes(x = longitud, y = latitud, color = cluster)) +
  geom_point() +
  labs(title = "Mapa de Clusters", x = "Longitud", y = "Latitud", color = "Cluster") +
  theme_minimal()

De acuerdo con el mapa, se observa que el Cluster 1 posee la mayor cantidad de datos y presenta una distribución dispersa por todo el territorio. El Cluster 2, por su parte, muestra una menor cantidad de datos y una mayor concentración de puntos, con una menor dispersión espacial. Finalmente, el Cluster 3 tiene la menor cantidad de datos, pero se observa una dispersión similar al Cluster 1, aunque con menor densidad.

5.Análisis de correspondencia

Análisis de Correspondencia : Examinar la relación entre las variables categóricas (tipo de vivienda, zona y barrio) y las variables numéricas (precio, área construida, número de parqueaderos, baños, habitaciones) para identificar patrones de comportamiento del mercado inmobiliario.

# Se establece la semilla para la aleatoriedad
set.seed(1234)

# Se toma una muestra aleatoria de 4000 viviendas
vivienda <- sample_n(vivienda, 2000)

# Se convierte la variable "estrato" a factor
vivienda$estrato <- as.factor(vivienda$estrato)

# Se analiza el patrón de datos faltantes

md.pattern(vivienda, rotate.names = TRUE)

##      preciom id zona estrato areaconst banios habitaciones tipo barrio longitud
## 1155       1  1    1       1         1      1            1    1      1        1
## 474        1  1    1       1         1      1            1    1      1        1
## 214        1  1    1       1         1      1            1    1      1        1
## 156        1  1    1       1         1      1            1    1      1        1
## 1          1  0    0       0         0      0            0    0      0        0
##            0  1    1       1         1      1            1    1      1        1
##      latitud parqueaderos piso     
## 1155       1            1    1    0
## 474        1            1    0    1
## 214        1            0    1    1
## 156        1            0    0    2
## 1          0            0    0   12
##            1          371  631 1012
# Se crea una tabla de contingencia con la zona y el estrato
library(FactoMineR)
tabla <- table(vivienda$zona, vivienda$estrato)

# Se asignan nombres a las columnas de la tabla
colnames(tabla) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6")

# Se realiza la prueba de chi-cuadrado
chisq.test(tabla)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla
## X-squared = 1012, df = 12, p-value < 2.2e-16

Existe una asociación altamente significativa entre las variables analizadas en la tabla, por lo tanto se rechaza la hipótesis nula.

# Realizar el Análisis de Correspondencia Múltiple (ACM)
resultados_ac <- CA(tabla)

El gráfico nos permite establecer relaciones y validarlas como son:

El estrato 6 se encuentra ubicado en la Zona Oeste Los estratos 4 y 5 están ubicados principalmente en la Zona Sur y Norte El estrato 3 está presente en las Zonas Oriente y Centro Dim 1 (68.31%): Explica el 68.31% de la variabilidad total en los datos. Dim 2 (26.89%): Explica el 26.89% de la variabilidad total en los datos.

Para medir el grado de representatividad del proceso calculas los valores de la varianza acumulada, utilizando para ellos los valores propios de la matriz de discrepancias

valores_prop <-resultados_ac$eig ; valores_prop
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.34877488              68.893118                          68.89312
## dim 2 0.14151958              27.954206                          96.84732
## dim 3 0.01596058               3.152676                         100.00000

El análisis de correspondencias múltiples (ACM) ha demostrado ser efectivo para reducir la dimensionalidad de los datos, ya que las dos primeras dimensiones (Dim 1 y Dim 2) capturan el 95.19% de la información total. Dim 1 explica el 68.31% de la varianza, mientras que Dim 2 explica el 26.89%. La tercera dimensión (Dim 3) solo explica el 4.80% de la varianza, lo que significa que las dos primeras dimensiones son suficientes para la mayoría de los análisis.

# Se crea un gráfico de scree plot con colores personalizados
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80), col = "blue") +
  ggtitle("") +
  ylab("Porcentaje de varianza explicado") +
  xlab("Ejes")

Las dos primeras dimensiones juntas explican el 95.19% de la varianza total en los datos.Esto significa que las dos primeras dimensiones son suficientes para capturar la mayor parte de la información en los datos.

Conclusiones

  1. El Análisis de Componentes Principales (ACP) se lleva a cabo con el propósito de discernir las variables primordiales que subyacen en la variabilidad del precio de la vivienda. Se constata que el primer componente principal (CP1) exhibe una explicación del 67% de la variabilidad total, mientras que la combinación de los dos primeros CPs da cuenta del 86%. A través del gráfico de ACP, se observa que el CP1 está primordialmente asociado con variables tales como el estrato, precio y área construida.

  2. En el Análisis de Conglomerados, se ejecuta un análisis de k-means con el propósito de segmentar las viviendas en conglomerados según las variables pertinentes. Se percibe una correlación positiva entre el estrato socioeconómico, el precio de la propiedad y la cantidad de conglomerados. El conglomerado 1 se caracteriza por la preeminencia de apartamentos, mientras que el conglomerado 3 exhibe una preponderancia de casas. Por su parte, el conglomerado 2 presenta una distribución más equilibrada entre apartamentos y casas.

  3. En el Análisis de Correlación, se procede a calcular la matriz de correlación con el fin de identificar las interrelaciones entre las variables. Se constata una fuerte correlación positiva entre el número de habitaciones y baños, así como entre el estrato socioeconómico y el precio de la propiedad. Se evidencia, además, una correlación positiva moderada entre el número de habitaciones y área construida, así como entre el número de baños y el precio de la propiedad.

  4. El Análisis de Correspondencia Múltiple (ACM) se emplea para examinar la relación entre variables categóricas y numéricas. Se identifica una asociación altamente significativa entre las variables zona y estrato. Asimismo, se constata que el estrato 6 se encuentra predominantemente en la Zona Oeste, mientras que los estratos 4 y 5 tienen una presencia predominante en las Zonas Sur y Norte. Las dos primeras dimensiones del ACM logran capturar el 95.19% de la información total, evidenciando así su efectividad en la reducción de la dimensionalidad de los datos.