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:

Iniciamos con la exploración de los datos proporcionada por la empresa inmobiliaria “vivienda” la cual se componen de 8.330 observaciones en 13 columnas, ahora daremos una breve descripción de los datos:

Nombre columna Descripción Tipo de dato
Id Identificador único de cada fila, no puede estar repetido. Numérico
zona Zona de que parte de la ciudad se encuentra inmueble. Carácter
piso Numero de pisos del inmueble. Numérico
Estrato Estrato social del inmueble. Numérico
Areaconst Area construida en metros cuadrados. Numérico
Parqueadero Numero de parqueaderos. Numérico
banios Número de baños del inmueble. Numérico
habitaciones Número de habitaciones. Numérico
Tipo Tipo de inmueble si es casa o apartamento. Carácter
Barrio Nombre de barrio del inmueble. Carácter
longitud y latitud Ubicación exacta de donde se encuentra el inmueble. Numérico
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

Limpieza de Datos

viviendaLD=vivienda

colSums(is.na(viviendaLD))
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3         2638            3            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##         1605            3            3            3            3            3 
##      latitud 
##            3

Se visualiza que las variables piso y parqueadero son las que más tienen N/A entre las dos suman 3243 por lo cual se decide en ambos casos reemplazar por el promedio.

viviendaLD$piso= as.integer(viviendaLD$piso)

viviendaLD$piso= round(na.aggregate(viviendaLD$piso),digits = 0) 

viviendaLD$parqueaderos= round(na.aggregate(viviendaLD$parqueaderos),digits = 0) 

colSums(is.na(viviendaLD))
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3            0            3            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##            0            3            3            3            3            3 
##      latitud 
##            3

En el caso de las otras variables se eliminarán las filas correspondientes a los N/A, debido a que no es significante el volumen de datos.

viviendaLD=na.omit(viviendaLD)
colSums(is.na(viviendaLD))
##           id         zona         piso      estrato      preciom    areaconst 
##            0            0            0            0            0            0 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##            0            0            0            0            0            0 
##      latitud 
##            0

Ya se encuentran los datos limpios sin ningun N/A, por lo cual podemos continuar con el análisis de componentes principales.



Análisis de componentes principales

A continuación se eliminarán las columnas de ID, longitud, latitud y barrio teniendo en cuenta que no aportan gran relevancia en nuestro analisis, por lo cual solo dejaremos las columnas desde zona, hasta el tipo de vivienda.

Procederemos a codificar las variables zona y tipo para el perfecto funcionamiento de variables de componentes principales.

viviendaACP=viviendaLD
viviendaACP$zona=as.integer(as.factor(viviendaLD$zona))
viviendaACP$tipo=as.integer(as.factor(viviendaLD$tipo))
viviendaACP=viviendaACP[2:10]

De esta manera quedaron codificadas las variables de zona

   - zona centro  -> 1
   - zona norte   -> 2
   - zona oeste   -> 3
   - zona oriente -> 4
   - zona sur     -> 5

De esta manera se codificaron las de tipo de apartamento

   - apartamento  -> 1
   - casa         -> 2
correlacion<- round(viviendaACP,2)
 
corPlot(correlacion, main = "Gráfico de Correlacion")

En el gráfico de correlación se visualiza que ninguna variable tiene una alta correlación.


En el dataframe se evidencia que existe una alta diferencia entre datos de la misma variable por lo cual se procede a normalizar los datos.

viviendaACPNormalizada=viviendaACP %>% scale()

Despues de normalizar los datos aplicamos la función PCA con el fin de realizar el analisis de componentes principales.

GraficoPCA=prcomp(viviendaACPNormalizada)
fviz_eig(GraficoPCA, addlabels = TRUE, main = "Grafico PCA")

Se toman las primeras 4 componenentes que sumadas dan un resultado del 80.1% de los datos, correspondientes a el 40.7%, 18.5%, 11.5% y 9.4% componentes que en su porcentaje son las que más explican el dataframe, omitimos el 19.7% por tanto seria desde el componente 5 hasta el 9 correspondientes a 6.6%, 4.9%, 3.6%, 2.6% y 2%.

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

  fviz_contrib(GraficoPCA, choice = "var", axes = 1, top = 10) # PC1

En la dimensión 1 las cuatro variables que más tienen peso son el área construida, los baños, el precio y el número de parqueaderos, estas variables se encuentran sobre el promedio de los datos y por debajo de el tenemos las variables de habitaciones, tipo de vivienda, estrato de la vivienda, piso y zona.

  fviz_contrib(GraficoPCA, choice = "var", axes = 2, top = 10) # PC2

En la dimensión 2 las cuatro variables que más tienen peso son el estrato, el tipo de vivienda, piso y el número de habitaciones, estas variables se encuentran sobre el promedio de los datos y por debajo de el tenemos las variables precio, número de parqueaderos, área construida, baños y zona.

  fviz_contrib(GraficoPCA, choice = "var", axes = 3, top = 10) # PC3

En la dimensión 3 solo la variable de zona se encuentra sobre el promedio de los datos y por tanto las o variables restantes como piso, estrato, habitaciones, área constituida, parqueadero, precio, tipo y baños se encuentran por debajo de el promedio.

  fviz_contrib(GraficoPCA, choice = "var", axes = 4, top = 10) # PC4

En esta última dimensión tomada que es la dimensión 4 solo dos variables que son piso y habitaciones sobrepasan el promedio, de esta manera zona, parqueaderos, baños, estrato, precio, tipo y área construida se encuentran por debajo de el promedio.




##Analisis de conglomerados

head(viviendaACP)
## # A tibble: 6 × 9
##    zona  piso estrato preciom areaconst parqueaderos banios habitaciones  tipo
##   <int> <dbl>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl> <int>
## 1     4     4       3     250        70            1      3            6     2
## 2     4     4       3     320       120            1      2            3     2
## 3     4     4       3     350       220            2      2            4     2
## 4     5     2       4     400       280            3      5            3     2
## 5     2     1       5     260        90            1      2            3     1
## 6     2     1       5     240        87            1      3            3     1

Para hacer el analisis de conglomerados tomaremos las mismas variables que utilizamos en el analisis de componentes principales, debido a que encontramos los datos muy distantes entre ellos necesitamos tambien realizar escalamiento de los datos.

head(viviendaACPNormalizada)
##             zona        piso    estrato    preciom  areaconst parqueaderos
## [1,]  0.06192582  0.07232598 -1.5872276 -0.5595498 -0.7339949   -0.8559050
## [2,]  0.06192582  0.07232598 -1.5872276 -0.3465670 -0.3842568   -0.8559050
## [3,]  0.06192582  0.07232598 -1.5872276 -0.2552886  0.3152194    0.1313764
## [4,]  0.81508501 -0.85191340 -0.6156201 -0.1031580  0.7349051    1.1186578
## [5,] -1.44439256 -1.31403309  0.3559875 -0.5291236 -0.5940997   -0.8559050
## [6,] -1.44439256 -1.31403309  0.3559875 -0.5899759 -0.6150839   -0.8559050
##           banios habitaciones       tipo
## [1,] -0.07793773    1.6406840  1.2586312
## [2,] -0.77811479   -0.4147626  1.2586312
## [3,] -0.77811479    0.2703863  1.2586312
## [4,]  1.32241640   -0.4147626  1.2586312
## [5,] -0.77811479   -0.4147626 -0.7944184
## [6,] -0.07793773   -0.4147626 -0.7944184

Para realizar la fase de clustering vamos a utilizar la técnica del codo, por tanto se buscará mediante esta técnica el punto de corte donde se diferenciará los diferentes agrupamientos.

X <-viviendaACPNormalizada

sse <- numeric(10)  

for (k in 1:10) {
  km <- kmeans(X, centers = k)
  sse[k] <- km$tot.withinss  
}

plot(1:10, sse, type = "b", pch = 19, frame = FALSE, 
     xlab = "Número de clusters (k)", ylab = "SSE",
     main = "Método del codo")

abline(v = 4, col = "red", lty = 2)

Debido a que en la gráfica se visualiza el codo en el punto 4 se realiza un corte para diferenciar los cluster.

##Técnica K-mean

Esta técnica agrupa por los k- vecinos más cercanos por lo cual es ek método más conveniente de agrupación.

KM=kmeans(viviendaACPNormalizada, 4)

head(aggregate(viviendaACPNormalizada, by=list(cluster= km$cluster), mean))
##   cluster       zona       piso     estrato    preciom  areaconst parqueaderos
## 1       1  0.7770075 -0.1723955 -0.82709249 -0.7684028 -0.7104127   -0.4845112
## 2       2 -1.2839229 -0.1968315 -1.29491313 -0.8113242 -0.6203265   -0.2872140
## 3       3  0.8150850 -0.1587339  0.58384234 -0.2909437 -0.4656095   -0.3544010
## 4       4  0.7662749 -0.4902545 -0.09992681 -0.0680694  0.1636721   -0.1358942
## 5       5 -0.3943026  0.6204578  1.23224266  1.7139761  0.4742171    0.7528124
## 6       6  0.4955997 -0.5090504  1.02514299  2.0279411  2.0498340    2.2030750
##       banios habitaciones       tipo
## 1 -0.8285131  -0.56682215 -0.7486778
## 2 -0.9235477  -0.49912242 -0.1173956
## 3 -0.2625862  -0.35776787 -0.7926015
## 4  0.2351029   0.21867696  1.2569470
## 5  0.9326393  -0.09131664 -0.7562060
## 6  1.5911940   0.77319717  1.2188948
fviz_cluster(KM, data=viviendaACPNormalizada)

Analisis de cluster

El primer cluster se caracteriza por tener valores relativamente bajos en estrato y parqueaderos, pero altos en areaconst, banios, y habitaciones. Esto podría indicar propiedades más grandes con un número considerable de habitaciones y baños, pero ubicadas en estratos más bajos.

El segundo cluster tiene valores intermedios en todas las variables, con un estrato y parqueaderos moderados, pero no tan altos como en el Cluster 3. Las propiedades en este cluster podrían ser de tamaño y precio promedio.

El tercer cluster se destaca por tener valores muy altos en todas las variables. Las propiedades en este cluster parecen ser grandes, con precios y características de lujo.

El cuarto cluster tiene valores bajos en todas las variables, lo que sugiere propiedades insignificantes y posiblemente de menor valor.




##Analisis de correspondecia simple

Se utiliza para visualizar asociaciones entre dos variables categoricas que en nuestro caso será zona y estrato, para resumir en una tabla bivariada.

tabla <- as.data.frame.matrix(table(viviendaLD$zona,viviendaLD$estrato))
tabla2<- as.data.frame.matrix(tabla)
 
  nuevos_nombres <- c("Estrato 3", "Estrato 4", "Estrato 5","Estrato 6")
  num_columnas <- ncol(tabla2)
  names(tabla2) <- nuevos_nombres

  head(tabla2)
##              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

##prueba chi cuadrado se realiza la prueba de chi cuadrado con el fin de encontrar el grado de relación que tienen las dos variables.

options(scipen = 999)

chisq.test(tabla2)
## 
##  Pearson's Chi-squared test
## 
## data:  tabla2
## X-squared = 3830.4, df = 12, p-value < 0.00000000000000022

Debido a que el valor que dio el P-value es menor a 0.05 las variables no son independientes, por tanto se rechaza la hipotesis nula.

resultados_ac <- CA(tabla2)

En el primer cuadrante se relacionan la zona oeste con el estrato 6, el cuadrante 2 correpondiente a la zona oriente y zona centro con el estrato 3, en el cuadrante 3 se relaciona la zona norte sin estratos pero con cercania a los estratos 4 y 5 que se encuentran relacionados a la zona sur.

Gráfico de Varianza…

fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")