Evaluación de la oferta inmobiliaria urbana

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.

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.

Analisis Base de datos

Se procede a explorar el dataset para establecer numero de observaciones, atributoS y tipos de variables:

summary(vivienda_faltantes)
##        id           zona                piso           estrato     
##  Min.   :   1   Length:8330        Min.   : 1.000   Min.   :3.000  
##  1st Qu.:2082   Class :character   1st Qu.: 2.000   1st Qu.:4.000  
##  Median :4164   Mode  :character   Median : 3.000   Median :5.000  
##  Mean   :4164                      Mean   : 3.772   Mean   :4.634  
##  3rd Qu.:6246                      3rd Qu.: 5.000   3rd Qu.:5.000  
##  Max.   :8319                      Max.   :12.000   Max.   :6.000  
##  NA's   :3                         NA's   :2641     NA's   :3      
##     preciom         areaconst       parquea           banios      
##  Min.   :  58.0   Min.   :  30   Min.   : 1.000   Min.   : 0.000  
##  1st Qu.: 220.0   1st Qu.:  80   1st Qu.: 1.000   1st Qu.: 2.000  
##  Median : 330.0   Median : 123   Median : 2.000   Median : 3.000  
##  Mean   : 434.2   Mean   : 175   Mean   : 1.836   Mean   : 3.112  
##  3rd Qu.: 540.0   3rd Qu.: 229   3rd Qu.: 2.000   3rd Qu.: 4.000  
##  Max.   :1999.0   Max.   :1745   Max.   :10.000   Max.   :10.000  
##  NA's   :2        NA's   :3      NA's   :1606     NA's   :3       
##     habitac           tipo              barrio             longitud        
##  Min.   : 0.000   Length:8330        Length:8330        Min.   :-76576.00  
##  1st Qu.: 3.000   Class :character   Class :character   1st Qu.:-76506.00  
##  Median : 3.000   Mode  :character   Mode  :character   Median :   -76.54  
##  Mean   : 3.605                                         Mean   :-21845.13  
##  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.390  
##  Median :   3.450  
##  Mean   : 970.370  
##  3rd Qu.:3367.000  
##  Max.   :3497.000  
##  NA's   :3

La base de datos consta de 8330 observaciones y 13 variables. Se evidencia presencia de datos perdidos (NA). Cuenta con 3 variables categoricas (zona, tipo y barrio) y 10 númericas. Se evidencia adicionalmente presencia de datos atípicos principalmente en precio, área construida, piso, parqueadero, baños y habitaciones.

Se procede a realizar un diagnóstico de variables faltantes:

grafico <-md.pattern(vivienda_faltantes, rotate.names = TRUE)
title(main="Figura 1. Variables perdidas de la base de datos B&C")

La mayoria de datos perdidos se dan en las variables parqueadero y piso, por tal motivo no serán tenidas en cuenta dentro del análisis. Tampoco se analizarán las variables ID, latitud y longitud. Por otro lado, se eliminan 3 observaciones que no cuentan con ID ni

Se evidencia un gran numero de faltantes en las vairables piso y parqueaderos. Tambien se encuentran 3 casos sin ID y que no aportan información al resto de variables.

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

El Analisis de componentes principales se realiza con variables numericas, por lo cual se transforman variables categoricas en numericas:

vivienda_faltantes <- vivienda_faltantes %>% mutate(zona = case_when (
    zona == "Zona Centro" ~ 1,
    zona == "Zona Norte" ~ 2,
    zona == "Zona Oeste" ~ 3,
    zona == "Zona Oriente" ~ 4,
    zona == "Zona Sur" ~ 5, ))
vivienda_faltantes$zona <- as.numeric(vivienda_faltantes$zona)

vivienda_faltantes <- vivienda_faltantes %>% mutate(tipo = case_when (                                               tipo == "Casa" ~ 1,
              tipo == "Apartamento" ~ 2))
vivienda_faltantes$tipo <- as.numeric(vivienda_faltantes$tipo)
head(vivienda_faltantes)
## # A tibble: 6 × 13
##      id  zona  piso estrato preciom areaconst parquea banios habitac  tipo
##   <dbl> <dbl> <dbl>   <dbl>   <dbl>     <dbl>   <dbl>  <dbl>   <dbl> <dbl>
## 1  8312     3     4       6    1300       318       2      4       2     2
## 2  8311     3     1       6     480       300       1      4       4     1
## 3  8307     3    NA       5    1200       800       4      7       5     1
## 4  8296     5     2       3     220       150       1      2       4     1
## 5  8297     3    NA       5     330       112       2      4       3     1
## 6  8298     5    NA       5    1350       390       8     10      10     1
## # ℹ 3 more variables: barrio <chr>, longitud <dbl>, latitud <dbl>

Se genera dataframe que contiene unicamente las siete variables seleccionadas.

dataset_filtrado <- vivienda_faltantes [c("zona", "estrato", "preciom", "areaconst", "banios", "habitac", "tipo")]
dataset_filtrado
## # A tibble: 8,330 × 7
##     zona estrato preciom areaconst banios habitac  tipo
##    <dbl>   <dbl>   <dbl>     <dbl>  <dbl>   <dbl> <dbl>
##  1     3       6    1300       318      4       2     2
##  2     3       6     480       300      4       4     1
##  3     3       5    1200       800      7       5     1
##  4     5       3     220       150      2       4     1
##  5     3       5     330       112      4       3     1
##  6     5       5    1350       390     10      10     1
##  7     5       6     305       125      3       3     2
##  8     3       5     480       280      4       4     2
##  9     5       5     275        74      2       3     2
## 10     5       5     285       120      4       3     2
## # ℹ 8,320 more rows

Se realiza analisis de estadistica descriptiva del dataframe, se omiten datos nulos:

dataset_filtrado = na.omit(dataset_filtrado)
summary(dataset_filtrado)
##       zona          estrato        preciom         areaconst     
##  Min.   :1.000   Min.   :3.00   Min.   :  58.0   Min.   :  30.0  
##  1st Qu.:3.000   1st Qu.:4.00   1st Qu.: 220.0   1st Qu.:  80.0  
##  Median :5.000   Median :5.00   Median : 330.0   Median : 124.0  
##  Mean   :3.921   Mean   :4.64   Mean   : 435.8   Mean   : 175.5  
##  3rd Qu.:5.000   3rd Qu.:5.00   3rd Qu.: 550.0   3rd Qu.: 230.0  
##  Max.   :5.000   Max.   :6.00   Max.   :1999.0   Max.   :1745.0  
##      banios          habitac            tipo      
##  Min.   : 0.000   Min.   : 0.000   Min.   :1.000  
##  1st Qu.: 2.000   1st Qu.: 3.000   1st Qu.:1.000  
##  Median : 3.000   Median : 3.000   Median :2.000  
##  Mean   : 3.119   Mean   : 3.608   Mean   :1.612  
##  3rd Qu.: 4.000   3rd Qu.: 4.000   3rd Qu.:2.000  
##  Max.   :10.000   Max.   :10.000   Max.   :2.000

Es importante tener en cuenta que el ACP, es sensible a datos atípicos. Se observan datos atípicos por encima del tercer cuartil para cuatro variables (precio, area construida, baños y habitaciones). Se decide realizar imputación de estas variables por mediana dado que la media, en este caso se ve afectada por la presencia de valores extremos.

Imputación de datos

columns <- c("zona", "estrato","preciom", "areaconst","banios", "habitac", "tipo")
imputed_data <- mice(dataset_filtrado[,names(dataset_filtrado) %in% columns],m = 1,
  maxit = 1, method = "median",seed = 2018,print=F)
complete.data <- mice::complete(imputed_data)
sum(is.na(complete.data))
## [1] 0

Se verifica que no haya datos nulos en el dataset imputado:

md.pattern(complete.data)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

##      zona estrato preciom areaconst banios habitac tipo  
## 8227    1       1       1         1      1       1    1 0
##         0       0       0         0      0       0    0 0
grafico <-md.pattern(complete.data, rotate.names = TRUE)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'
title(main="Figura 2. Variables perdidas luego de imputación de datos")

Correlación de variables

Verificamos el índice de correlación para las variables con el fin de comprender las relaciones entre ellas para determinar la fuerza y dirección de esas relaciones

matrizcor <- cor(complete.data)
corrplot (matrizcor, method = "number", number.cex = 0.5, 
          main="Figura 3. matriz de correlacion")

Las correlaciones positivas que mas destacan son:

areaconst y preciom: 0.69. banios y preciom: 0.67. banios y areaconst: 0.65.

Estandarización de variables

Con el fin de evitar sesgos dado por las variables que tiene una escala con valores más grandes afecten las estimaciones, se realiza la estandarización de las siete variables:

vivienda_std <- scale(complete.data)
head (vivienda_std, n = 5)
##            zona    estrato    preciom  areaconst     banios    habitac
## [1,] -0.6937075  1.3229679  2.6242492  1.0005237  0.6169735 -1.1014403
## [2,] -0.6937075  1.3229679  0.1342939  0.8741651  0.6169735  0.2689263
## [3,] -0.6937075  0.3499608  2.3205961  4.3841273  2.7167424  0.9541096
## [4,]  0.8135239 -1.5960533 -0.6552042 -0.1788236 -0.7828724  0.2689263
## [5,] -0.6937075  0.3499608 -0.3211858 -0.4455807  0.6169735 -0.4162570
##            tipo
## [1,]  0.7967805
## [2,] -1.2548982
## [3,] -1.2548982
## [4,] -1.2548982
## [5,] -1.2548982

Con el fin de determinar pertinencia de ACP para el dataset se realiza medición de KMO y prueba de Barlett. Estas dos pruebas indican la idoneidad de los datos para la detección de estructuras.

KMO(complete.data)
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = complete.data)
## Overall MSA =  0.73
## MSA for each item = 
##      zona   estrato   preciom areaconst    banios   habitac      tipo 
##      0.37      0.61      0.71      0.78      0.78      0.71      0.78

La Medida Kaiser-Meyer-Olkin de adecuación de muestreo es un estadístico que indica la proporción de varianza en las variables que pueden ser causadas por factores subyacentes. Los valores altos (cercanos a 1.0) generalmente indican que un análisis factorial puede ser útil con los datos. Si el valor es menor que 0,50, los resultados del análisis factorial probablemente no serán muy útiles, en este caso la variable zona no aporta mucho en el analisis por estructuras.

cortest(cor(complete.data))
## Warning in cortest(cor(complete.data)): n not specified, 100 used
## Tests of correlation matrices 
## Call:cortest(R1 = cor(complete.data))
##  Chi Square value 454.53  with df =  21   with probability < 4.5e-83
cortest.bartlett(cor(complete.data),n=850)
## $chisq
## [1] 2753.898
## 
## $p.value
## [1] 0
## 
## $df
## [1] 21

Prueba de esfericidad de Bartlett contrasta la hipótesis de que la matriz de correlaciones es una matriz de identidad, lo que indicaría que las variables no están relacionadas y, por lo tanto, no son adecuadas para la detección de estructuras. Los valores pequeños (menores que 0,05) del nivel de significancia del p valor, indican que un análisis factorial puede ser útil con los datos.En este caso el valor es de 2753 con un p valor estadisticamente significativo.

El indice de KMO se encuentra por encima de 0.65 y el resultado del test de Barllet es mayor a 0.60. Por lo cual se considera pertinencia para realizar analisis de componentes principales.

PCA

Se realiza analisis de componentes principales para las cuatro variables y se grafica resultado:

viviendaacp <- (prcomp(vivienda_std))
fviz_eig(viviendaacp, addlabels = TRUE, ylim = c(0, 80), main="Figura 4. Porcentaje de varianza por dimension")

El primer componente concentra la mayor varianza de los datos (46.1%), seguido del segundo componente (21.1%) y el tercer componente 14.4%. Entre los tres primeros componentes se concentra el 81.6% de la variabilidad de los datos.

Se verifica con los valores propios de cada uno de los componentes, se evidencia que el ideal de explicación de varianza de al menos 95%, se da con 5 dimensiones de las 7 dimensiones:

get_eigenvalue(viviendaacp)
##       eigenvalue variance.percent cumulative.variance.percent
## Dim.1  3.2268988        46.098555                    46.09855
## Dim.2  1.4782242        21.117488                    67.21604
## Dim.3  1.0054218        14.363169                    81.57921
## Dim.4  0.5145366         7.350522                    88.92973
## Dim.5  0.3469235         4.956050                    93.88578
## Dim.6  0.2416918         3.452740                    97.33852
## Dim.7  0.1863034         2.661476                   100.00000

En la siguiente tabla se observa la contribución de cada variable por cada uno de los 7 componentes:

get_pca_var(viviendaacp)$contrib[,1:7]
##                Dim.1      Dim.2        Dim.3      Dim.4      Dim.5        Dim.6
## zona       0.1977851  0.9497739 96.672992991  0.1132256  1.9703492 1.757149e-02
## estrato    6.0768005 44.5596269  0.002841512  0.5636907 24.0023903 2.315369e+01
## preciom   20.1168675 12.5352908  1.556640240  3.7164306  7.7778129 4.759171e+00
## areaconst 23.4900027  0.3080794  0.747537549 11.5354320 29.0520941 8.721477e+00
## banios    24.1054622  0.2844353  0.016094512 14.3657173  3.2391929 4.438597e+01
## habitac   13.9904609 18.9392322  0.152284655 40.0641955  0.2301186 1.896143e+01
## tipo      12.0226210 22.4235615  0.851608542 29.6413084 33.7280420 6.935406e-04
##                 Dim.7
## zona       0.07830174
## estrato    1.64096493
## preciom   49.53778693
## areaconst 26.14537775
## banios    13.60312864
## habitac    7.66227493
## tipo       1.33216508

Para el primer componente, el numero de baños, area construida y precio aportan la mayor cantidad de varianza. Para el segundo componente estrato, tipo de vivienda, numero de habitaciones y el precio son las que realizan el mayor aporte. En el tercer componente, la zona es el principal aportante; mientras que para el cuarto componente el numero de habitaciones y tipo de vivienda son los que aportan mayor variabilidad. En la siguiente grafica se pueden visualizarse de mejor manera que el numero de habitaciones y el area construida se situan en el mismo cuadrante, mientras que numero de baños, precio y estrato se ubican en otro cuadrante y el tipo de vivienda se encuentra en otra dirección. La zona aparentemente no tiene mayor relación.

fviz_pca_var(viviendaacp, col.var = "contrib", gradient.cols = c("#FF7F00",  "#034D94"),
repel = TRUE)

Con este gráfico es posible visualizar diferencias entre las muestras y el impacto de cada dato en cada uno de los componentes principales.

fviz_pca_biplot(viviendaacp,
                repel=FALSE,
                col.var='#2e9fdf',
                col.ind='#ffff00')

Conclusiones ACP

Según lo mostrado en el gráfico se puede ver dos tipos de agrupamiento, en la parte superior derecha la asociación se da entre numero de habitaciones, numero de baños con el que se encuentra dotada la vivienda y el area construida. En el segmento inferior derecho, se ubican el precio de la vivienda y el estrato.

El componente principal explica el 46.1% de la varianza de los datos, el segundo componente principal 21.1% y el tercer componente 14.4, estos tres primeros componentes representan la mayor parte de la variabilidad de las 7 variables tomadas en el ACP.

En el primer componente principal las variables con mayor participación son numero de baños, area construida y precio; en el segundo componente la participación mas alta es dada por estrato, tipo de vivienda, numero de habitaciones y el precio. En el tercer componente, la zona es el principal aportante; mientras que para el cuarto componente el numero de habitaciones y tipo de vivienda son los que aportan mayor variabilidad.

Para realizar reduccion de dimensionalidad se utilizarían los primeros 4 componentes principales, que acumulan el 95% de la varianza del conjunto de datos.

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

Normalizacion

Se normalizan las variables

vivienda_cluster <- scale (complete.data)
vivienda_cluster = as.data.frame(vivienda_cluster) 
head (vivienda_cluster, n=5)
##         zona    estrato    preciom  areaconst     banios    habitac       tipo
## 1 -0.6937075  1.3229679  2.6242492  1.0005237  0.6169735 -1.1014403  0.7967805
## 2 -0.6937075  1.3229679  0.1342939  0.8741651  0.6169735  0.2689263 -1.2548982
## 3 -0.6937075  0.3499608  2.3205961  4.3841273  2.7167424  0.9541096 -1.2548982
## 4  0.8135239 -1.5960533 -0.6552042 -0.1788236 -0.7828724  0.2689263 -1.2548982
## 5 -0.6937075  0.3499608 -0.3211858 -0.4455807  0.6169735 -0.4162570 -1.2548982

Se realiza medición de distancias euclidianas:

dis_euc<- dist(vivienda_cluster, method="euclidean")
head(dis_euc,5)
## [1] 3.507582 5.033033 5.566414 4.048754 7.442378
c1 <-hclust(dis_euc,method ="complete")
c1
## 
## Call:
## hclust(d = dis_euc, method = "complete")
## 
## Cluster method   : complete 
## Distance         : euclidean 
## Number of objects: 8227

Métodos no jerárquicos

Se procede a evaluar diferentes métodos de agrupación de los datos con el objetivo de identificar el número más óptimo de clústeres de acuerdo al conjunto de datos. Para ello comenzaremos con la construcción del siguiente gráfico

scv <- (nrow(vivienda_cluster) - 1) * sum(apply(vivienda_cluster, 2, var))
for (i in 2:7) scv[i] <- sum(kmeans(vivienda_cluster,
                                     centers = i)$withinss)
plot(1:7, scv, 
     type = "b", 
     xlab = "Cantidad de Clusters",
     ylab="Suma de cuadrados dentro de grupos")

La anterior gráfica evidencia la cantidad de clústeres que se pueden realizar con la data disponible. Sin embargo, la anterior gráfica no permite esclarecer la cantidad de clústeres necesarios para el análisis. Debido a ello, procedemos a evaluar el número de clúster mediante el método del codo el cual se puede representar mediante la siguiente figura

fviz_nbclust(vivienda_cluster, kmeans, method = "wss") + 
  geom_vline(xintercept = 4, linetype = 2) + labs (subtitle="Metodo del Codo")

Tambien se realiza un grafico con el metodo Silhouette para identificar cuantos clúster se pueden generar:

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

Se evidencia que el índice mas alto se genera a partir de dos cluster.

Metodos jerarquicos

library(cluster)
# distancia euclidiana
dist_vivi_k2 <- dist(vivienda_cluster, method = 'euclidean')

# Cluster jerarquico con el método complete
hc_viv_k2 <- hclust(dist_vivi_k2, method = 'complete')

# Determinamos a dónde pertenece cada observación
cluster_assigments_k2 <- cutree(hc_viv_k2, k = 2)

# Calcular el coeficiente de Silhouette
sil_k2 <- silhouette(cluster_assigments_k2, dist(vivienda_cluster))
sil_avg_k2 <- mean(sil_k2[,3])

# Imprimir el coeficiente de Silhouette promedio
cat("Coeficiente de Silhouette promedio k=2 : ", sil_avg_k2)
## Coeficiente de Silhouette promedio k=2 :  0.6511063

Estos resultados indican una mejor agrupación cuando se eligen k=2 conglomerados (valores más cercanos a 1 indican un agrupamiento más coherente)

Se determina la pertenencia de cada observación a un cluster determinado:

cluster_assigments <- cutree(c1, k = 2)
cluster_assigments_k3 <- cutree(c1, k = 3)
cluster_assigments_k4 <- cutree(c1, k = 4)
cluster_assigments_k5 <- cutree(c1, k = 5)

Se asignan las observaciones a los cluster:

assigned_cluster <- vivienda_cluster %>% mutate(cluster = as.factor(cluster_assigments))
head(assigned_cluster,10)
##          zona    estrato    preciom  areaconst      banios    habitac
## 1  -0.6937075  1.3229679  2.6242492  1.0005237  0.61697355 -1.1014403
## 2  -0.6937075  1.3229679  0.1342939  0.8741651  0.61697355  0.2689263
## 3  -0.6937075  0.3499608  2.3205961  4.3841273  2.71674245  0.9541096
## 4   0.8135239 -1.5960533 -0.6552042 -0.1788236 -0.78287239  0.2689263
## 5  -0.6937075  0.3499608 -0.3211858 -0.4455807  0.61697355 -0.4162570
## 6   0.8135239  0.3499608  2.7760758  1.5059583  4.81651135  4.3800262
## 7   0.8135239  1.3229679 -0.3970990 -0.3543217 -0.08294942 -0.4162570
## 8  -0.6937075  0.3499608  0.1342939  0.7337666  0.61697355  0.2689263
## 9   0.8135239  0.3499608 -0.4881950 -0.7123378 -0.78287239 -0.4162570
## 10  0.8135239  0.3499608 -0.4578297 -0.3894213  0.61697355 -0.4162570
##          tipo cluster
## 1   0.7967805       1
## 2  -1.2548982       1
## 3  -1.2548982       1
## 4  -1.2548982       1
## 5  -1.2548982       1
## 6  -1.2548982       1
## 7   0.7967805       1
## 8   0.7967805       1
## 9   0.7967805       1
## 10  0.7967805       1

Se procede a graficar los cluster acorde con las variables de interes:

# gráfico de puntos para las variables zona y estrato
ggplot(assigned_cluster, aes(x = zona, y = estrato, color = cluster)) +
geom_point(size = 4) +
geom_text(aes(label = cluster), vjust = -.8) + labs (title =  "Distribucion por cluster de zona y estrato") 

theme_classic()
# gráfico de puntos para las variables zona y precio
ggplot(assigned_cluster, aes(x = zona, y = preciom, color = cluster)) +
geom_point(size = 4) +
geom_text(aes(label = cluster), vjust = -.8) + labs (title =  "Distribucion por cluster de zona y precio (Millones)") + # Agregar etiquetas del clúster
theme_classic()

# gráfico de puntos para las variables zona y area construida
ggplot(assigned_cluster, aes(x = zona, y = areaconst, color = cluster)) +
geom_point(size = 4) +
geom_text(aes(label = cluster), vjust = -.8) + labs (title =  "Distribucion por cluster de zona y area construida (metros cuadrados)") + # Agregar etiquetas del clúster
theme_classic()

# gráfico de puntos para las variables precio y area construida
ggplot(assigned_cluster, aes(x = preciom, y = areaconst, color = cluster)) +
geom_point(size = 4) +
geom_text(aes(label = cluster), vjust = -.8) + labs (title =  "Distribucion por cluster de zona y area construida (metros cuadrados)") + # Agregar etiquetas del clúster
theme_classic()

Se realiza el dendograma de viviendas para los dos cluster generados:

plot(c1, cex = 0.6, main = "Dendograma de Viviendas", las=1,
ylab = "Distancia euclidiana", xlab = "Viviendas")
rect.hclust(c1, k = 2, border = 2:5)

En el dendograma se encuentran la agrupacion de las observaciones de cada vivienda generadas a partir de dos grandes divisiones.

Se genera nuevo conjunto de datos incluyendo la clasificación por cluster:

set.seed(1)
modelkmeans <- kmeans(vivienda_cluster, 2) 
vivienda_cluster2 <- data.frame(vivienda_cluster,modelkmeans$cluster) 

aggregate(complete.data,
          by = list(vivienda_cluster2$modelkmeans.cluster),
          FUN = median)
##   Group.1 zona estrato preciom areaconst banios habitac tipo
## 1       1    5       4     250        90      2       3    2
## 2       2    5       5     620       277      4       4    1

Se verifica numero de observaciones por cada uno de los cluster:

Numcluste = table(vivienda_cluster2$modelkmeans.cluster)%>% 
       as.data.frame()

colnames(Numcluste)=c("Cluster", "Frecuencia")
flextable(Numcluste)

Cluster

Frecuencia

1

5,328

2

2,899

Se agrega una nueva columna al conjunto de datos con la pertenencia al cluster que corresponde cada observacion:

viviendakmeans = kmeans(vivienda_cluster2, centers = 2)
vivienda_cluster2$cluster = viviendakmeans$cluster
vivienda_cluster2$cluster = as.character(vivienda_cluster2$cluster)
head(vivienda_cluster2, n = 6)
##         zona    estrato    preciom  areaconst     banios    habitac       tipo
## 1 -0.6937075  1.3229679  2.6242492  1.0005237  0.6169735 -1.1014403  0.7967805
## 2 -0.6937075  1.3229679  0.1342939  0.8741651  0.6169735  0.2689263 -1.2548982
## 3 -0.6937075  0.3499608  2.3205961  4.3841273  2.7167424  0.9541096 -1.2548982
## 4  0.8135239 -1.5960533 -0.6552042 -0.1788236 -0.7828724  0.2689263 -1.2548982
## 5 -0.6937075  0.3499608 -0.3211858 -0.4455807  0.6169735 -0.4162570 -1.2548982
## 6  0.8135239  0.3499608  2.7760758  1.5059583  4.8165113  4.3800262 -1.2548982
##   modelkmeans.cluster cluster
## 1                   2       2
## 2                   2       2
## 3                   2       2
## 4                   1       1
## 5                   1       1
## 6                   2       2

Se grafica la pertenencia de cada observacion por los dos cluster generados:

fviz_cluster(list(data = vivienda_cluster2[1:8], 
                  cluster = vivienda_cluster2$modelkmeans.cluster),
             palette = c("#2E9FDF", "#E7B800" , "#FC4E07"),
             ellipse.type = "convex",repel = F, 
             show.clust.cent = TRUE, ggtheme = theme_minimal())

Con el fin de analizar cada cluster por separado, se calculan medidas de tendencia central (media) para las variables contenidas en cada cluster generados:

median_clus <- aggregate(cbind(estrato, preciom, areaconst, habitac, banios, zona) 
                      ~ modelkmeans.cluster,
             data = vivienda_cluster2, FUN = function(x) c(Media = round(mean(x), 2)))

colnames(median_clus)=c("Cluster", "Estrato", "Precio","Area construida", "Banios", "Zona", "habitaciones")
flextable(median_clus)

Cluster

Estrato

Precio

Area construida

Banios

Zona

habitaciones

1

-0.21

-0.47

-0.51

-0.44

-0.53

-0.03

2

0.38

0.87

0.94

0.82

0.98

0.05

No obstante los datos en cada cluster se encuentran normalizado por lo cual se dificulta su interpretacion.

Conclusiones AC

El analisis por conglomerados muestra la presencia de dos grandes grupos que comparten determinadas características. El primero de ellos contiene 5328 observaciones y el segundo contiene 2899. El primer cluster se caracteriza por tener menos área construida por lo tanto cuentan con menor numero de baños y habitaciones, y esto hace que tenga un menor precio. El segundo cluster esta conformado por viviendas con mayor área construida, por lo tanto ofrece mayor numero de baños y habitaciones, caracteristicas que incluyen en el precio final de la viviendam siendo mas costosas que las del cluster 1.

  1. Análisis de Correspondencia :

Examinar la relación entre las variables categóricas (tipo de vivienda, zona y barrio), para identificar patrones de comportamiento de la oferta en mercado inmobiliario.

La variable barrio presenta un gran numero de subcategorias por lo cual no será tenido en cuenta en el análisis de correspondencia.

Se genera tabla de contigencia para las variables zona y estrato.

tabla <- table(dataset_filtrado$zona, dataset_filtrado$estrato)
rownames(tabla) <- c("Centro", "Norte", "Oeste", "Oriente", "Sur")
colnames(tabla) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6" )
addmargins(tabla)
##          
##           Estrato3 Estrato4 Estrato5 Estrato6  Sum
##   Centro       105       14        4        1  124
##   Norte        555      398      762      171 1886
##   Oeste         54       85      287      767 1193
##   Oriente      330        8        2        1  341
##   Sur          374     1597     1673     1039 4683
##   Sum         1418     2102     2728     1979 8227

Se aplica prueba de asociacion chi cuadrado para determinar la relacion entre las variables zona y estrato:

chisq.test(tabla)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla
## X-squared = 3780, df = 12, p-value < 2.2e-16

Se evidencia que ambas variables zona y estrato se encuentran relacionadas acorde con p valor obtenido, por lo tanto se rechaza hipotesis nula que determina que son independientes la una de la otra. El nivel de significancia establecido es 0.05.

Se estiman las coordenadas para cada una de los niveles de las variables para ser representadas en un plano cartesiano

resultados_ac <- CA(tabla)

En la grafica se observa que las viviendas de estrato 3 estan ubicadas en la zona centro y oriente. Las viviendas que están ubicadas en las zonas Norte y Sur son principalmente de estratos 4 y 5. Las viviendas estrato 6 se ubican en la zona oeste de la ciudad.

Para medir el grado de representatividad del proceso, se calculan 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.32119386              69.907181                          69.90718
## dim 2 0.12717852              27.680142                          97.58732
## dim 3 0.01108523               2.412677                         100.00000
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Componentes")

Los resultados indican que el primer componente contiene el 68.9% de la varianza de los datos y el segundo componente el 27.7%, es decir que entre ambos se aporta el 97.6% de los datos categoricos.

Se realiza tabla de contigencia para las variables tipo de vivienda y estrato.

tabla2 <- table(complete.data$tipo, complete.data$estrato)
rownames(tabla2) <- c("Casa", "Apartamento")
colnames(tabla2) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6" )
addmargins(tabla2)
##              
##               Estrato3 Estrato4 Estrato5 Estrato6  Sum
##   Casa             799      721      982      693 3195
##   Apartamento      619     1381     1746     1286 5032
##   Sum             1418     2102     2728     1979 8227
chisq.test(tabla2)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla2
## X-squared = 222.65, df = 3, p-value < 2.2e-16

Se evidencia que ambas variables tipo de vivienda y estrato se encuentran relacionadas, ya que el valor de p obtenido es menor al nivel de significancia, por lo tanto se rechaza hipotesis nula que determina que son independientes ambas variables.

Recomendaciones:

El precio de la vivienda se relaciona con el estrato, y éste con la zona geografica donde se ubica la vivienda. El área construida determina la dotación de la vivienda en cuanto a numero de habitaciones y baños. Entre mejor dotada se encuentre la vivienda mayor será el precio. La mayor demanda se da en tipos de vivienda apartamento estrato 4 y 5. Con esta información se puede segmentar la oferta de vivienda a los clientes acorde con sus necesidades.

Las viviendas de estrato 3 estan ubicadas en la zona centro y oriente. Las viviendas que están ubicadas en las zonas Norte y Sur son principalmente de estratos 4 y 5. Las viviendas estrato 6 se ubican en la zona oeste de la ciudad. Esto permite identificar a la empresa oportunidades de compra o venta de viviendas con alta demanda por parte de los clientes.

Se evidencia que los clientes se pueden segmentar en dos grandes cluster.El primer cluster se caracteriza porque los clientes prefieren viviendas pequeñas en área (menor numero de baños y habitaciones), a un precio accesible. El segundo cluster esta conformado por clientes con mayores ingresos que prefieren viviendas con mayor área construida, (por lo tanto ofrece mayor numero de baños y habitaciones).