Evaluación de la oferta inmobiliaria urbana

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.

1. Entendimiento de los datos

Se cargan los datos contenidos en paqueteMOD

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

2. Descripción de los datos

Resumen de los datos

summary(data)
##        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

Descripción de los datos

Datos Categoricos

Las variables zona, piso, estado, tipo y barrio son de tipo categóricas en donde se visualiza poca cantidad de datos faltantes en una de las variables, la cual es estrato. Esto quiere decir que la mayoría de los registros tiene datos completos.

Datos Numericos

preciom: la media es de 433.9 y la mediana es de 330, el valor minimo es de 58 y el maximo de 1999, aqui encontramos 2 valores faltantes. Segun documentación estos valores corresponden a millones.
areaconst: El área construida tiene una media de 174.9 y una mediana de 123, lo que indica que más de la mitad de las propiedades tienen un área inferior a 174.9 unidades. Hay 3 valores faltantes.
parqueaderos: La media de parqueaderos es 1.835, con una mediana de 2. Esto sugiere que la mayoría de las propiedades tienen 2 parqueaderos. Sin embargo, hay una gran cantidad de valores faltantes (1605).
banios: El número de baños tiene una media de 3.111, y la mediana es 3. La mayoría de las propiedades tienen entre 2 y 3 baños, con un máximo de 10. Hay 3 valores faltantes.
habitaciones: El número de habitaciones tiene una media de 3.605, con una mediana de 3. La distribución es similar a la de los baños, con un máximo de 10 habitaciones. Hay 3 valores faltantes.
data %>%
  group_by(zona) %>%
  summarise(n = n(), .groups = "drop")
data %>%
  group_by(tipo) %>%
  summarise(n = n(), .groups = "drop")
skim(data)
Data summary
Name data
Number of rows 8322
Number of columns 13
_______________________
Column type frequency:
character 4
numeric 9
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
zona 3 1.00 8 12 0 5 0
piso 2638 0.68 2 2 0 12 0
tipo 3 1.00 4 11 0 2 0
barrio 3 1.00 4 29 0 436 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
id 3 1.00 4160.00 2401.63 1.00 2080.50 4160.00 6239.50 8319.00 ▇▇▇▇▇
estrato 3 1.00 4.63 1.03 3.00 4.00 5.00 5.00 6.00 ▅▆▁▇▆
preciom 2 1.00 433.89 328.65 58.00 220.00 330.00 540.00 1999.00 ▇▂▁▁▁
areaconst 3 1.00 174.93 142.96 30.00 80.00 123.00 229.00 1745.00 ▇▁▁▁▁
parqueaderos 1605 0.81 1.84 1.12 1.00 1.00 2.00 2.00 10.00 ▇▁▁▁▁
banios 3 1.00 3.11 1.43 0.00 2.00 3.00 4.00 10.00 ▇▇▃▁▁
habitaciones 3 1.00 3.61 1.46 0.00 3.00 3.00 4.00 10.00 ▂▇▂▁▁
longitud 3 1.00 -76.53 0.02 -76.59 -76.54 -76.53 -76.52 -76.46 ▁▅▇▂▁
latitud 3 1.00 3.42 0.04 3.33 3.38 3.42 3.45 3.50 ▃▇▅▇▅

Analisis Correlacional

datacor <- data [, c(4, 5, 6, 8, 9)] 
chart.Correlation(datacor, hist = TRUE, method = "pearson")

De acuerdo con el análisis de correlación, podemos concluir lo siguiente:

El coeficiente de Pearson, que mide el grado de asociación lineal entre variables, muestra lo siguiente en relación con el precio: la correlación con el área construida es de 0.7, la correlación con el número de habitaciones es de 0.3, la correlación con el número de baños es de 0.7.

Estos valores sugieren que, en general, un mayor precio está asociado con una mayor área construida, un mayor número de habitaciones, y un mayor número de baños. Además, el coeficiente de Pearson para la asociación entre el área construida y otras variables muestra: una correlación de 0.5 con el número de habitaciones y una correlación de 0.6 con el número de baños.

Esto indica que una mayor área construida tiende a estar asociada con un mayor número de habitaciones y baños.

Finalmente, la correlación entre el número de habitaciones y el número de baños es de 0.6, lo que sugiere que un mayor número de habitaciones suele estar acompañado por un mayor número de baños.

Analisis Descriptivo

Distribución por Zonas

conteo_valores_zona <- table(data$zona)
conteo_valores_zona_df <- as.data.frame(conteo_valores_zona)

frecuencias <- conteo_valores_zona_df$Freq
etiquetas <- paste0(conteo_valores_zona_df$Var1, ": ", round(frecuencias / sum(frecuencias) * 100, 1), "%")
colores <- brewer.pal(n = length(frecuencias), name = "Set3")

pie(frecuencias, labels = etiquetas, col = colores, clockwise = TRUE, radius = 1, init.angle = 90, 
    main = "Distribución de Inmuebles por Zona")

graphics::legend("topright", legend = conteo_valores_zona_df$Var1, fill = colores, cex = 0.8, 
       title = "Zonas")

El mayor porcentaje se concentró en la zona sur con un 56.8%, seguida por la zona norte con un 23.1%. Las zonas oeste, oriente y centro registraron el 14.4%, 4.2% y 1.5%, respectivamente.

Distribución por Tipo de Vivienda

conteo_tipo <- table(data$tipo)
conteo_tipo_df <- as.data.frame(conteo_tipo)

ggplot(conteo_tipo_df, aes(x = Var1, y = Freq, fill = Var1)) + geom_bar(stat = "identity", color = "black") + geom_text(aes(label = Freq), vjust = -0.5, color = "black", size = 3.5) + labs(title = "Distribución de Inmuebles por Tipo", x = "Tipo de Inmueble", y = "Número de Inmuebles") + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.title = element_blank()) + scale_fill_brewer(palette = "Set3")

Distribución por Estrato

conteo_valores_estrato <- table(data$estrato)
conteo_valores_estrato_df <- as.data.frame(conteo_valores_estrato)

frecuencias <- conteo_valores_estrato_df$Freq
porcentajes <- round(frecuencias / sum(frecuencias) * 100, 2)
etiquetas <- paste0(conteo_valores_estrato_df$Var1, ": ", porcentajes, "%")

ggplot(conteo_valores_estrato_df, aes(x = Var1, y = frecuencias, fill = Var1)) +
  geom_bar(stat = "identity", color = "black") +
  geom_text(aes(label = frecuencias), vjust = -0.5, color = "black", size = 3.5) +
  labs(title = "Distribución por Estrato",
       x = "Estrato",
       y = "Número de Inmuebles") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        legend.title = element_blank()) +
  scale_fill_brewer(palette = "Set3")

La gráfica muestra que el estrato 5 concentra el mayor porcentaje de inmuebles, con un 33%. Le siguen el estrato 4 con un 26%, el estrato 6 con un 24%, y el estrato 3 con un 17%.

3. Verificación e imputación de datos faltantes.

miss_var_summary(data)
miss_var_summary_df <- as.data.frame(miss_var_summary(data))
miss_var_summary_df$var <- factor(miss_var_summary_df$var, levels = miss_var_summary_df$var[order(miss_var_summary_df$n_miss)])

ggplot(miss_var_summary_df, aes(x = var, y = n_miss, label = n_miss)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  geom_text(aes(label = n_miss), vjust = -0.3, color = "black", size = 3.5) +
  coord_flip() +
  labs(title = "Número de Valores Faltantes por Variable",
       x = "Variable",
       y = "Número de Valores Faltantes") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

vis_miss(data, cluster = TRUE)

aggr(data,numbers=T,sortVar=T)

## 
##  Variables sorted by number of missings: 
##      Variable        Count
##          piso 0.3169911079
##  parqueaderos 0.1928622927
##            id 0.0003604903
##          zona 0.0003604903
##       estrato 0.0003604903
##     areaconst 0.0003604903
##        banios 0.0003604903
##  habitaciones 0.0003604903
##          tipo 0.0003604903
##        barrio 0.0003604903
##      longitud 0.0003604903
##       latitud 0.0003604903
##       preciom 0.0002403268

El diagrama muestra que aproximadamente el 50% de los datos contienen al menos una característica con valores faltantes (NA), lo que añade una capa adicional de complejidad en la aplicación de los algoritmos.

En este contexto, se ha decidido proceder con la imputación de los valores faltantes en la variable “Piso y Parqueadero” excluyendo estas variables del análisis.

4. Análisis de Componentes Principales

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

Selección de Variables

head(datacor,3)

Escalar Variables

dataesc <- datacor %>%
scale()
head(dataesc,10)
##          estrato    preciom  areaconst      banios habitaciones
##  [1,] -1.5872276 -0.5595420 -0.7339949 -0.07793773    1.6406840
##  [2,] -1.5872276 -0.3465477 -0.3842568 -0.77811479   -0.4147626
##  [3,] -1.5872276 -0.2552644  0.3152194 -0.77811479    0.2703863
##  [4,] -0.6156201 -0.1031256  0.7349051  1.32241640   -0.4147626
##  [5,]  0.3559875 -0.5291143 -0.5940997 -0.77811479   -0.4147626
##  [6,]  0.3559875 -0.5899698 -0.6150839 -0.07793773   -0.4147626
##  [7,] -0.6156201 -0.6508253 -0.8599006 -0.77811479   -0.4147626
##  [8,]  0.3559875 -0.3769755 -0.2653459 -0.07793773    0.2703863
##  [9,]  0.3559875 -0.3465477 -0.1744140  0.62223934    1.6406840
## [10,]  0.3559875  1.0531293  1.4343813 -0.07793773   -0.4147626

PCA estimar:

dataesc<- na.omit(dataesc)
prcomp(dataesc)
## Standard deviations (1, .., p=5):
## [1] 1.7126702 1.0901061 0.6673491 0.4916092 0.4376110
## 
## Rotation (n x k) = (5 x 5):
##                    PC1        PC2        PC3        PC4        PC5
## estrato      0.3300034 -0.6744210  0.4209148 -0.4795679  0.1705853
## preciom      0.5068979 -0.2807716 -0.3015624  0.2214323 -0.7240509
## areaconst    0.4940391  0.1638245 -0.6525161 -0.2985094  0.4628195
## banios       0.5189521  0.1092985  0.3767724  0.6647387  0.3672975
## habitaciones 0.3475145  0.6538646  0.4051619 -0.4358863 -0.3123167

PCA Grafica:

PCA(dataesc, scale.unit = TRUE, ncp = 5, graph = TRUE)

## **Results for the Principal Component Analysis (PCA)**
## The analysis was performed on 8319 individuals, described by 5 variables
## *The results are available in the following objects:
## 
##    name               description                          
## 1  "$eig"             "eigenvalues"                        
## 2  "$var"             "results for the variables"          
## 3  "$var$coord"       "coord. for the variables"           
## 4  "$var$cor"         "correlations variables - dimensions"
## 5  "$var$cos2"        "cos2 for the variables"             
## 6  "$var$contrib"     "contributions of the variables"     
## 7  "$ind"             "results for the individuals"        
## 8  "$ind$coord"       "coord. for the individuals"         
## 9  "$ind$cos2"        "cos2 for the individuals"           
## 10 "$ind$contrib"     "contributions of the individuals"   
## 11 "$call"            "summary statistics"                 
## 12 "$call$centre"     "mean of the variables"              
## 13 "$call$ecart.type" "standard error of the variables"    
## 14 "$call$row.w"      "weights for the individuals"        
## 15 "$call$col.w"      "weights for the variables"

La gráfica anterior ilustra las relaciones entre la variable estrato y el precio, así como las interacciones entre el área, el número de habitaciones y el número de baños. Para identificar el número óptimo de componentes principales, se puede utilizar un Scree Plot. Este gráfico muestra los valores propios ordenados de mayor a menor. El número de componentes principales se selecciona observando el punto en el que los valores propios empiezan a estabilizarse y se vuelven relativamente pequeños y similares entre sí.

grafico_pca <- prcomp(dataesc, scale. = TRUE)

fviz_eig(grafico_pca, 
         addlabels = TRUE,       
         barfill = "steelblue",  
         barcolor = "black",     
         linecolor = "red",      
         line.size = 1,          
         title = "Scree Plot de Valores Propios",
         xlab = "Número de Componente Principal",
         ylab = "Valor Propio",
         ggtheme = theme_minimal() +
           theme(
             plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
             axis.title = element_text(size = 12),
             axis.text = element_text(size = 10),
             panel.grid = element_blank()
           )) +
  geom_vline(xintercept = which.max(diff(fviz_eig(grafico_pca)$data$y)), 
             linetype = "dashed", 
             color = "blue") +
  annotate("text", 
           x = which.max(diff(fviz_eig(grafico_pca)$data$y)) + 0.5, 
           y = max(fviz_eig(grafico_pca)$data$y) * 0.9, 
           label = "Codo", 
           color = "blue", 
           size = 3)

Matriz de Correlaciones:

matriz_correlaciones <- cor(dataesc, use = "pairwise.complete.obs")
matriz_correlaciones
##                  estrato   preciom areaconst    banios habitaciones
## estrato       1.00000000 0.6098066 0.2743233 0.4203218  -0.07137615
## preciom       0.60980664 1.0000000 0.6873520 0.6691456   0.26409121
## areaconst     0.27432332 0.6873520 1.0000000 0.6484165   0.51691292
## banios        0.42032178 0.6691456 0.6484165 1.0000000   0.58990641
## habitaciones -0.07137615 0.2640912 0.5169129 0.5899064   1.00000000
corPlot(matriz_correlaciones,numbers = 0.5)

preciom: tiene una fuerte relación con areaconst y banios, y una relación más débil pero aún positiva con habitaciones.

estrato: muestra una relación positiva moderada con preciom y banios, pero relaciones débiles con areaconst y habitaciones.

areaconst: está correlacionada con banios y habitaciones, lo que sugiere que los inmuebles con mayor área construida suelen tener más baños y habitaciones.

Factores:

resultado_pca <- prcomp(dataesc, scale. = TRUE)
print("Resumen del PCA:")
## [1] "Resumen del PCA:"
pca_summary <- summary(resultado_pca)
print(pca_summary)
## Importance of components:
##                           PC1    PC2     PC3     PC4    PC5
## Standard deviation     1.7126 1.0901 0.66735 0.49161 0.4376
## Proportion of Variance 0.5866 0.2377 0.08907 0.04834 0.0383
## Cumulative Proportion  0.5866 0.8243 0.91337 0.96170 1.0000
cat("\nPrimeros Componentes Principales:\n")
## 
## Primeros Componentes Principales:
print(head(resultado_pca$rotation))
##                    PC1        PC2        PC3        PC4        PC5
## estrato      0.3300032 -0.6744363  0.4208934 -0.4795545  0.1706159
## preciom      0.5068715 -0.2807656 -0.3015468  0.2213868 -0.7240921
## areaconst    0.4940473  0.1638135 -0.6525373 -0.2984641  0.4628138
## banios       0.5189619  0.1092831  0.3767649  0.6647648  0.3672488
## habitaciones 0.3475270  0.6538568  0.4051685 -0.4359154 -0.3122700
cat("\nProporción de Varianza Explicada por Cada Componente:\n")
## 
## Proporción de Varianza Explicada por Cada Componente:
print(pca_summary$importance["Proportion of Variance", ])
##     PC1     PC2     PC3     PC4     PC5 
## 0.58663 0.23766 0.08907 0.04834 0.03830
cat("\nVarianza Acumulada por los Componentes Principales:\n")
## 
## Varianza Acumulada por los Componentes Principales:
print(pca_summary$importance["Cumulative Proportion", ])
##     PC1     PC2     PC3     PC4     PC5 
## 0.58663 0.82430 0.91337 0.96170 1.00000

PC1: es el componente principal, capturando más del 58% de la varianza en los datos.

La combinación de PC1 y PC2 explica más del 82% de la varianza total, lo que indica que estos dos componentes son importantes para la interpretación de los datos.

Resumen: El primer componente principal (PC1) explica el 58.66% de la varianza total. El segundo componente principal (PC2) captura el 23.77% de la varianza. El tercer componente principal (PC3) explica el 8.90% de la varianza, mientras que el cuarto componente principal (PC4) contribuye con el 4.83%. Finalmente, el quinto componente principal (PC5) representa el 3.83% de la varianza total.

Sidementación

conflicts_prefer(psych::scree)
## [conflicted] Will prefer psych::scree over any other package.
scree(dataesc,main ="Sedimentacion")

Según el gráfico de sedimentación, lo optimo seria realizar 3 componentes, puesto que este valor se encuentra por encima de la línea aceptable de la grafica .

Almacenamiento de los componetes principales seleccionados

CP1 = resultado_pca[[2]][,1]
CP2 = resultado_pca[[2]][,2]
CP3 = resultado_pca[[2]][,3]
ComponentePrincipal = cbind(CP1, CP2, CP3)
ComponentePrincipal
##                    CP1        CP2        CP3
## estrato      0.3300032 -0.6744363  0.4208934
## preciom      0.5068715 -0.2807656 -0.3015468
## areaconst    0.4940473  0.1638135 -0.6525373
## banios       0.5189619  0.1092831  0.3767649
## habitaciones 0.3475270  0.6538568  0.4051685

5. Análisis de Conglomerados:

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

datacon <- data [, c(2, 4,10)]
head(datacon,10)

Dummy

A continuación, se realiza las conversión de la variables cualitativas (tipo y zona) en numéricas, esto con el objetivo de poder utilizar un algoritmo de clustering:

datacon <- mutate_if(datacon, is.character, tolower)
datacon$tipo[datacon$tipo == "apto"] <- "apartamento"
unique(datacon$tipo)
## [1] "casa"        "apartamento" NA
data_cluster <- datacon
data_cluster <- data_cluster %>% mutate(zona = replace(zona, 
                                               zona == "zona centro", 1))
data_cluster <- data_cluster %>% mutate(zona = replace(zona, 
                                               zona == "zona norte", 2))
data_cluster <- data_cluster %>% mutate(zona = replace(zona, 
                                               zona == "zona oeste", 3))
data_cluster <- data_cluster %>% mutate(zona = replace(zona, 
                                               zona == "zona oriente",4))
data_cluster <- data_cluster %>% mutate(zona = replace(zona, 
                                               zona == "zona sur", 5))
data_cluster$zona <- as.numeric(data_cluster$zona)
                          
data_cluster <- data_cluster %>% mutate(tipo = replace(tipo, 
                                               tipo == "casa", 1))
data_cluster <- data_cluster %>% mutate(tipo = replace(tipo, 
                                               tipo == "apartamento", 2))
data_cluster$tipo <- as.numeric(data_cluster$tipo)
head(datacon,10)
head(data_cluster,10)

Kmeans

data_cluster <- na.omit(data_cluster)
scv <- numeric(15)
scv[1] <- (nrow(data_cluster) - 1) * sum(apply(data_cluster, 2, var))

for (i in 2:15) {
  scv[i] <- sum(kmeans(data_cluster, centers = i)$withinss)
}

plot(1:15, scv, 
     type = "b", 
     pch = 19, 
     col = "blue", 
     xlab = "Número de Clusters",
     ylab = "Suma de Cuadrados Dentro de los Grupos",
     main = "Kmeans",
     lwd = 2, 
     cex = 1.2)

abline(v = which.min(diff(diff(scv))), col = "red", lty = 2, lwd = 2)
abline(h = min(scv), col = "green", lty = 2, lwd = 2)

El gráfico muestra la variación dentro de los clusters en función del número de clusters 𝑘 A medida que aumenta 𝑘, la suma de cuadrados dentro de los clusters disminuye. Se observa una inflexión en 𝑘=4, lo que sugiere que agregar más clusters más allá de este punto aporta un valor marginal adicional. Esto indica que el número óptimo de clusters podría ser alrededor de 4.

Silueta

fviz_nbclust(data_cluster, kmeans, method = "silhouette") + labs(subtitle = "Número Óptimo de Clusters según el Método de Silueta")

La gráfica anterior, basada en el método de silueta, sugiere que el número óptimo de clusters es 2. Esto contrasta con la recomendación del método K-means, que indicaba 4 clusters. Después de revisar ambos métodos, se ha decidido utilizar 2 clusters para el análisis, ya que el método de silueta proporciona una evaluación más precisa en este caso.

num_clusters <- 2
clustering_result <- kmeans(data_cluster, centers = num_clusters)
fviz_cluster(clustering_result, data = data_cluster,
             palette = c("#2E9FDF", "#E7B800"),   
             ellipse.type = "euclid",             
             star.plot = TRUE,                    
             repel = FALSE,                       
             ggtheme = theme_minimal()            
)

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

data_acm <- data [, c(2,4,10)]
data_acm$estrato = as.factor(data_acm$estrato)
#head(data_acm,3)
str(data_acm)
## tibble [8,322 × 3] (S3: tbl_df/tbl/data.frame)
##  $ zona   : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ estrato: Factor w/ 4 levels "3","4","5","6": 1 1 1 2 3 3 2 3 3 3 ...
##  $ tipo   : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
# Realizar la prueba de chi-cuadrado

set.seed(7)  # Establecer una semilla para reproducibilidad
chi_cuadrado <- data.frame(
  estrato = rep(c("3", "4", "5", "6"), times = 50),
  tipo = sample(c("zona centro", "zona sur","zona norte", "zona oeste","zona oriente"), size = 100, replace = TRUE)
)

# Crear una tabla de contingencia
tabla_zona_estrato <- table(data_acm$estrato, data_acm$zona)

# Mostrar la tabla de contingencia
print(tabla_zona_estrato)
##    
##     Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
##   3         105        572         54          340      382
##   4          14        407         84            8     1616
##   5           4        769        290            2     1685
##   6           1        172        770            1     1043
chisq <- chisq.test(tabla_zona_estrato)
chisq
## 
##  Pearson's Chi-squared test
## 
## data:  tabla_zona_estrato
## X-squared = 3830.4, df = 12, p-value < 0.00000000000000022
library(factoextra) # Librerías
library(gridExtra)
ac <- CA(tabla_zona_estrato) # Gráfico

A través de esta representación gráfica, emergen patrones claros y concretos:

  • El estrato 6 se encuentra prominentemente ubicado en la Zona Oeste.
  • Los estratos 4 y 5 exhiben una asociación con las zonas sur casi cerca a la zona norte
  • El estrato 3 se manifiesta en las zonas Oriente y Centro.

Conclusiones

La visualización gráfica obtenida ofrece una perspectiva valiosa sobre las relaciones entre las variables “estrato” y “zona” en el mercado inmobiliario. Esta representación permite identificar patrones significativos, facilitando una segmentación más precisa del mercado y una mejor comprensión de las preferencias de los compradores en distintas áreas geográficas.

El enfoque estadístico empleado valida las tendencias identificadas visualmente y proporciona un sólido fundamento para la toma de decisiones estratégicas en el ámbito inmobiliario.

La reducción de dimensionalidad mediante Análisis de Componentes Principales (PCA) reveló que los dos primeros componentes capturan el 82.43% de la varianza total, destacando las variables numéricas más influyentes en la variabilidad del mercado.

Además, el análisis de correspondencia evidenció relaciones significativas entre las variables categóricas y numéricas. Esto sugiere que factores como el tipo de propiedad y la zona están estrechamente relacionados con características numéricas como el estrato, proporcionando así una comprensión más profunda de las dinámicas del mercado.