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. 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 oferta del mercado.
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.
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.
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.
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
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.
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)
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")