Índice

  1. Descripción de la actividad

  2. Objetivo

  3. Procesamiento de datos

  4. Análisis de Correspondencia

  5. Matriz de Covarianza

  6. Análisis de Componentes Principales

  7. Análisis de Conglomerados

8 Discusión de resultados

  1. Anexos

1. Descripción de la actividad

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.

2. Objetivo

Realizar un análisis integral y multidimensional de la base de datos para obtener una comprensión del mercado inmobiliario urbano.

3. Procesamiento de datos

Los datos para el estudio fueron importados desde el paqueteMOD suministrado.

library(paqueteMODELOS)
library(scales)
library (dplyr)
library(ggplot2)
library(kableExtra)
library(tidyr)
library(DescTools)

# Consumo de datos
data("vivienda")

#Presentación de datos

knitr::kable(vivienda[1:3,],
             booktabs = TRUE,
             format = "html",
             caption = "<center><b><span style='font-size:18px'> Datos de oferta inmobiliaria </span></b></center>",
) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Datos de oferta inmobiliaria
id zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo barrio longitud latitud
1147 Zona Oriente NA 3 250 70 1 3 6 Casa 20 de julio -76.51168 3.43382
1169 Zona Oriente NA 3 320 120 1 2 3 Casa 20 de julio -76.51237 3.43369
1350 Zona Oriente NA 3 350 220 2 2 4 Casa 20 de julio -76.51537 3.43566

3.1 Detección de errores, datos faltantes y datos atípicos

Durante el tratamiento de datos solamente se filtraron aquellos registros completamente vacios y a su misma vez se homologaron los campos cuyo valor es “N/A” a 0.

Con respecto a los datos atípicos estos no se eliminaron ya que representaban un número considerable, gran cantidad de estos datos pertenecen a las variables “areaconst” y “preciom” estos se muestran a continuación en el siguiente gráfico.

# Pasar a formato largo
datos_f <- datos[names(datos) %in% c("preciom","areaconst","parqueaderos","banios","habitaciones")]
datos_long <- datos_f %>%
  pivot_longer(
    cols = everything(),
    names_to = "Variable",
    values_to = "Valor"
  )

# Graficar todos en un mismo recuadro
ggplot(datos_long, aes(x = Variable, y = Valor)) +
  geom_boxplot(fill = "lightcoral", alpha = 0.6) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5),
    axis.text.x = element_text(angle = 45, hjust = 1)
  ) +
  labs(
    title = "Diagramas de caja de variables continuas",
    x = "Variables",
    y = "Valor"
  ) +
  scale_y_continuous(labels = function(x) format(x, scientific = FALSE))

Fue necesario emplear indicadores de tendencia central, posición y dispersión para la profundización de este conjunto de datos, en la sección de anexos se encuentra esta tabla.

4. Análisis de Correspondencia

Antes de iniciar con el análisis de cada una de las variables cuantitativas es importante considerar la relación existente entre las variables categóricas presentes para identificar alguna relación. En la sección de anexos se encuentran estas matrices de contingencia.

4.1 Relación Piso y Estrato

Para iniciar, se analiza la relación entre piso y estrato, mediante un test de chicuadrado en donde se obtiene un de valor p de < 2.2e-16 y cuyos valores residuales en algunos casos son mayores a 2 y como complento la fuerza de asociación tiene un valor de 0.118. Por otra parte, es posible gráficar estos puntos en el plano cartesiano.

library(FactoMineR)
library(factoextra)
library(gridExtra)
resultados_ac <- CA(T_contingencia, graph = TRUE)

valores_prop <-resultados_ac$eig ; valores_prop
##        eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.034010731              80.269128                          80.26913
## dim 2 0.006337305              14.956747                          95.22588
## dim 3 0.002022838               4.774125                         100.00000

4.2 Relación Piso Y Tipo de Inmueble

Consecutivamente, se repite el mismo procedimiento, pero entre las variables piso y tipo de inmueble, reportando un valor p < 2.2e-16 y con algunos valores residuales ampliamente superiores a 2 y la fuerza de asociación tiene un valor de 0.466. No es posible gráfica los puntos en mismo plano cartesiano para este escenario.

4.3 Relación Estrato y Tipo de Inmueble

La relación entre estrato y tipo presente un valor p < 2.2e-16 y con algunos valores residuales ampliamente superiores a 2 y la fuerza de asociación tiene un valor de 0.164.. No es posible gráfica los puntos en mismo plano cartesiano para este escenario.

4.4 Relación entre Estrato y Zona

Como parte final del presente estudio, resulta pertinente centrar el análisis en la zona de ubicación de los inmuebles y en su respectivo estrato socioeconómico. Reportando un valor p < 2.2e-16 y con algunos valores residuales ampliamente superiores a 2 y la fuerza de asociación tiene un valor de 0.391. Por otra parte, es posible gráficar estos puntos en el plano cartesiano.

library(factoextra)
library(gridExtra)
resultados_ac <- CA(T_contingencia4, graph = TRUE)

valores_prop <-resultados_ac$eig ; valores_prop
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32215213              69.965515                          69.96551
## dim 2 0.12745096              27.680002                          97.64552
## dim 3 0.01084108               2.354483                         100.00000

5 Matriz de covarianzas

Continuando con el analisis, se procede a igualar las escalas de medida para poder gráficar la respectiva matriz de covarianza con el fin de estudiar la relación entre variables.

# Graficar
ggplot(mat_cov_long, aes(Var1, Var2, fill = value)) +
  geom_tile() +
  geom_text(aes(label = round(value, 2)), size = 4, color = "black") +
  scale_fill_gradient2(
    low = "blue",
    mid = "white",
    high = "red",
    midpoint = 0
  ) +
  theme_minimal() +
  labs(
    title = "Matriz de Covarianza",
    x = "",
    y = "",
    fill = "Covarianza"
  ) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

La matriz de correlación no presenta coeficientes superiores a 0,80. Las asociaciones más elevadas se encuentran rondando 0,68–0,69 y se concentran vinculadas al precio.

6. Análisis de Componentes Principales

Para este estudio se involucran las variables cuantitativas características propias del inmueble como:

  • preciom
  • areaconst
  • parqueaderos
  • banios
  • habitaciones

Las variables (estrato, zona, barrio, longitud, latitud, piso y tipo) no fueron tenidas en cuenta en esta etapa ya que son variables categóricas.

En este caso, el primer componente principal explica el 62,6% de la variabilidad total, mientras que el segundo aporta un 18,4%. En conjunto, ambos componentes concentran aproximadamente el 81% de la varianza, lo que permite reducir el set de datos a dos dimensiones principales (PC1 y PC2) El siguiente gráfico explica la concentración de los componentes.

fviz_eig(res.pca, addlabels = TRUE)

library(plotly)

# Extraer scores de los 3 primeros componentes
scores <- as.data.frame(res.pca$x[, 1:2])

En la siguiente gráfica se puede apreciar la distribución de los inmubles entre las dos dimensiones principales identificadas anteriormente.

plot_ly(
  data = scores,
  main = "Grafica N Diagrama",
  x = ~PC1,
  y = ~PC2,
  type = "scatter",
  mode = "markers",
  marker = list(size = 6, color = "steelblue")
) %>%
  layout(
    title = "Proyección PCA (PC1 vs PC2)",
    xaxis = list(title = "PC1"),
    yaxis = list(title = "PC2")
  )

Por último, la siguiente gráfica del coseno representa la participación de cada una de las variables dentro de cada una de las dimensiones caracterizadas.

fviz_pca_var(res.pca,
             col.var = "contrib", # Color by contributions to the PC
             gradient.cols = c("#FF7F00",  "#034D94"),
             repel = TRUE     # Avoid text overlapping
)

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 las variables parqueaderos y precio, mientras que el segundo componente se puede asociar a la variable habitaciones, área construida y baños.

7. Análisis de Conglomerados

Dado que el conjunto de datos es considerablemente grande y no corresponde a una muestra pequeña, la aplicación de un método jerárquico no resulta viable, ya que este tipo de técnicas requiere el cómputo de un dendograma en el cual se forman grupos de individuos que comparten similitudes.No obstante, se procede a emplear un método no jerárquico basado en k-means basado en las dimensiones (PC1 y PC2).

scores <- as.data.frame(res.pca$x[, 1:2])
colnames(scores) <- c("PC1", "PC2")


set.seed(123)
wss <- sapply(1:10, function(k) {
  kmeans(scores, centers = k, nstart = 25)$tot.withinss
})

plot(1:10, wss, type = "b",
     main = "Método del codo",
     xlab = "Número de clusters (k)",
     ylab = "WSS")

Como resultado, podemos identificar claramente mediante el método del codo 3 clusters en el conjunto de datos, en estos podemos clasificar cada uno de los inmuebles según su participación en PC1 y PC2. En la siguiente grafica se puede ver cada uno de los clusters.

set.seed(123)
km <- kmeans(scores, centers = 3, nstart = 25)

scores$cluster <- factor(km$cluster)


ggplot(scores, aes(PC1, PC2, color = cluster)) +
  geom_point(size = 2) +
  theme_minimal() +
  labs(
    title = "Clustering sobre componentes principales",
    color = "Cluster"
  )

aggregate(datos[names(datos) %in% c("preciom","areaconst","parqueaderos","banios","habitaciones")],
          by = list(cluster = km$cluster),
          mean)

Finalmente, con lo realizado anteriormente es posible etiquetar los inmuebles según sea la cantidad de baños, parquederos, área construida, precio y número de habitaciones.

datos$cluster <-factor(km$cluster)
head(datos)
table(datos$cluster)
## 
##    1    2    3 
## 2544  960 4815

8. Discusion de Resultados

Después de analizar los resultados obtenidos anteriormente y relacionar el comportamiento de los inmuebles en cada uno de los análisis, el conjunto de datos esta influenciado fuertemente por los siguientes fenómenos:

  1. Lujo / Tamaño: Compuesto por las correlaciones existentes entre precio, parqueaderos, área construida y baños, ya que mayor área construida, mayor número de baños, parqueaderos y, lógicamente, un precio más elevado.

  2. Número de habitaciones: Se evidencia que el número de habitaciones es inherente al precio, área construida, baños y parqueaderos.

Estos fenónemos representan el 81% de la varainza total.

Por otra parte, el cojunto de datos se divide en tres perfiles, en tres tipos de inmuebles diferentes.

  1. Viviendas Económicas/ Pequeñas: Son inmuebles antiguos o viviendas de proyectos sociales los cuales no tienen una gran área construida y no tienen un número amplio de baños o parqueaderos, no hay una amplia variación entre inmuebles, es decir que casi todos tienen los mismos atributos, ubicados en la zona oriente y la zona centro de la ciudad, su estrato social corresponde al “estrato 3” y si este inmueble es un apartamento puede estar ubicado en los primeros pisos del edificio residencial.

  2. Viviendas de Rango Medio: Son inmuebles con características similares a las viviendas económicas, sin embargo estas presentan cambios en su composición como parqueaderos, baños y área de construcción y lógicamente el precio, peuden tener un área construida similar a inmuebles de alto valor pero a un precio menor, estos inmuebles corresponden al “estrato 4” y están ubicados en la zona Norte y zona Sur de la ciudad, además no tienden a estar en un piso predeterminado si llegara a ser un apartamento.

  3. Viviendas de Alto Valor / Grandes: Son los inmuebles con más metros cuadrados, más parqueaderos y precios elevados, hay una amplia dispersión con respecto al número de habitaciones y lujo/tamaño ofreciendo una variedad para los compradores, en este perfil se encuentran inmuebles ubicados en la zona sur y en la zona oeste perteneciendo a los estratos 5 y 6 aquí se pueden encontrar casas de lujo o apartamentos de lujo ubicados en los pisos más altos de un edificio residencial.

Como estrategía para la inmobiliaria se sugiere que emplear estategias de ventas y marketing efoncadas a cada tipo de vivienda por ejemplo:

  • Para el sector de Viviendas Económicas/ Pequeñas potencializar los inmuebles en base a la cantidad de habitaciones preservando un precio accesible.

  • Para viviendas de Alto valor se pueden usar estrategias con respecto al tamaño y lujo y ofrecer alternativas como: un cas lujosa en una de las zonas más exclusivas de la ciudad o un apartamento ubicado en en los últimos pisos de un edificio.

9. Anexos

9.1 Indicadores de Tendencia central,dispersión y posición

var_continuas <- names(datos)[sapply(datos, is.numeric)]

  #Indicadores de Tendencia central, dispersión y posición
calc_stats <- function(columna){
  
  media <- round(mean(columna, na.rm = TRUE), 3)
  mediana <- round(median(columna, na.rm = TRUE), 3)
  maximo <- max(columna, na.rm = TRUE)
  minimo <- min(columna, na.rm = TRUE)
  rango <- round((max(columna, na.rm = TRUE) - min(columna, na.rm = TRUE)), 3)
  varianza <- round(var(columna, na.rm = TRUE), 3)
  Desv_Estandar <- round(sd(columna, na.rm = TRUE), 3)
  Coef_Variacion <- round(((Desv_Estandar / media) * 100), 3)
  
  Q1 <- quantile(columna, 0.25, na.rm = TRUE)
  Q3 <- quantile(columna, 0.75, na.rm = TRUE)
  IQR_val <- Q3 - Q1
  lim_inf <- Q1 - 1.5 * IQR_val
  lim_sup <- Q3 + 1.5 * IQR_val
  
  datos_atipicos <- columna[columna < lim_inf | columna > lim_sup]
  
  if(length(datos_atipicos) == 0){
    valores_txt <- "Ninguno"
  } else {
    valores_unicos <- unique(datos_atipicos)
    valores_txt <- paste(head(valores_unicos, 5), collapse = ", ")
    if(length(valores_unicos) > 5){
      valores_txt <- paste0(valores_txt, ", ...")
    }
  }
  
  return(list(
    Media = media,
    Mediana = mediana,
    Minimo = minimo,
    Maximo = maximo,
    Rango = rango,
    Varianza = varianza,
    Desv_Estandar = Desv_Estandar,
    Coef_Variacion = Coef_Variacion,
    Cantidad_de_valores_atipicos = length(datos_atipicos),
    Valores_atipicos = valores_txt
  ))
}
  resultados <- lapply(datos[, var_continuas, drop = FALSE], calc_stats)
  resultados_df <- do.call(rbind, lapply(resultados, as.data.frame))
  resultados_df <- cbind(Variable = names(resultados), resultados_df)
  resultados_df$Varianza <- format(resultados_df$Varianza, scientific = FALSE)
  outliers_df <- resultados_df[, c("Variable", "Cantidad_de_valores_atipicos")]
  resultados_df %>%
    kable(
      col.names = c(
        "Variable",
        "Media",
        "Mediana",
        "Mínimo",
        "Máximo",
        "Rango",
        "Varianza",
        "Desv. Estándar",
        "Coef. Variación",
        "Cantidad de valores atípicos",
        "Valores atípicos"
      ),
      align = "c", 
      caption = "<center><b><span style='font-size:18px'> Indicadores de tendencia central, dispersión, posición y valores atípicos</span></b></center>",
      row.names = FALSE)%>%

    kable_styling(full_width = FALSE, position = "center")
Indicadores de tendencia central, dispersión, posición y valores atípicos
Variable Media Mediana Mínimo Máximo Rango Varianza Desv. Estándar Coef. Variación Cantidad de valores atípicos Valores atípicos
preciom 433.904 330 58 1999 1941 108020.698 328.665 75.746 552 1400, 1150, 1200, 1100, 1130, …
areaconst 174.935 123 30 1745 1715 20438.741 142.964 81.724 382 455, 480, 550, 540, 460, …
parqueaderos 1.482 1 0 10 10 1.545 1.243 83.873 567 4, 7, 5, 8, 6, …
banios 3.111 3 0 10 10 2.040 1.428 45.902 72 8, 10, 9
habitaciones 3.605 3 0 10 10 2.130 1.460 40.499 888 6, 0, 1, 8, 7, …
# estrato vs tipo

knitr::kable(T_contingencia,
             booktabs = TRUE,
             format = "html",
             caption = "<center><b><span style='font-size:18px'> Matriz de contingencia Estrato Vs Tipo </span></b></center>",
) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Matriz de contingencia Estrato Vs Tipo
3 4 5 6
0 575 613 792 655
1 209 211 276 164
2 230 347 501 372
3 205 306 353 233
4 96 178 209 124
5 122 175 154 116
6 2 56 104 83
7 2 64 86 52
8 7 71 80 53
9 0 44 53 49
10 3 38 58 31
11 2 14 39 29
12 0 12 45 26
# estrato vs tipo
knitr::kable(T_contingencia2,
             booktabs = TRUE,
             format = "html",
             caption = "<center><b><span style='font-size:18px'> Matriz de contingencia Piso vs Tipo </span></b></center>",
) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Matriz de contingencia Piso vs Tipo
0 1
0 1381 1254
1 430 430
2 512 938
3 573 524
4 545 62
5 564 3
6 243 2
7 200 4
8 211 0
9 146 0
10 128 2
11 84 0
12 83 0
# estrato vs tipo
knitr::kable(T_contingencia3,
             booktabs = TRUE,
             format = "html",
             caption = "<center><b><span style='font-size:18px'> Matriz de contingencia Estrato vs Tipo </span></b></center>",
) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Matriz de contingencia Estrato vs Tipo
0 1
3 639 814
4 1404 725
5 1766 984
6 1291 696
knitr::kable(T_contingencia4,
             booktabs = TRUE,
             format = "html",
             caption = "<center><b><span style='font-size:18px'> Matriz de contingencia Estrato vs Zona </span></b></center>",
) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Matriz de contingencia Estrato vs Zona
Estrato_3 Estrato_4 Estrato_5 Estrato_6
Zona Centro 105 14 4 1
Zona Norte 572 407 769 172
Zona Oeste 54 84 290 770
Zona Oriente 340 8 2 1
Zona Sur 382 1616 1685 1043