El presente trabajo tiene como objetivo realizar un análisis integral de la base de datos de una empresa inmobiliaria líder en la ciudad, que contiene información detallada sobre diversas propiedades residenciales. A través de la aplicación de técnicas avanzadas de análisis de datos, como el Análisis de Componentes Principales (PCA), el Análisis de Conglomerados (Clustering) y el Análisis de Correspondencia, se busca reducir la complejidad de los datos, identificar grupos homogéneos de propiedades, y explorar las relaciones entre diferentes características del mercado.
Inicialmente cargamos las librerias utilizadas en la estimación de los modelos a probar y procedemos a cargar la base de datos, la cual se encuentra en “paqueteMODELOS” con el nombre de vivienda.
Posteriormente visualizamos los datos que contiene la base de datos:
Realizamos un resumen de toda la base de datos:
Frecuencias para la variable: zona
zona n
1 Zona Centro 124
2 Zona Norte 1920
3 Zona Oeste 1198
4 Zona Oriente 351
5 Zona Sur 4726
6 <NA> 3
Frecuencias para la variable: piso
piso n
1 01 860
2 02 1450
3 03 1097
4 04 607
5 05 567
6 06 245
7 07 204
8 08 211
9 09 146
10 10 130
11 11 84
12 12 83
13 <NA> 2638
Frecuencias para la variable: estrato
estrato n
1 3 1453
2 4 2129
3 5 2750
4 6 1987
5 <NA> 3
Frecuencias para la variable: tipo
tipo n
1 Apartamento 5100
2 Casa 3219
3 <NA> 3
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 | ▇▇▇▇▇ |
| 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 | ▃▇▅▇▅ |
Inicialmente, podemos identificar que la base de datos tiene 8322 registros y 13 variables, 5 de ellas son categoricas (incluyendo el estrato) y 8 son numericas. Evidenciamos tambien que las que más tienen datos perdidos corresponden a piso y parqueaderos. En la variable “zona”, se observa que la mayoría de los apartamentos se encuentran ubicados en la zona sur de la ciudad, con un total de 4726 viviendas ofertadas, mientras que la zona centro muestra la menor oferta, con tan solo 124 viviendas disponibles. En cuanto al precio, se destaca que el valor promedio de la oferta es de 433.89 millones de pesos. En relación al área construida en metros cuadrados, se evidencia que el \(50\%\) de las viviendas tienen un área construida comprendida entre \(80\) y \(229 m^{2}\), según el primer y tercer cuartil. El tamaño promedio de las viviendas es de \(174 m^{2}\).
Ahora analizamos gráficamente la distribución de alguas variables:
par(mfrow=c(2, 2))
# Histograma del precio de la vivienda
hist(bd_viviendas$preciom, main = "Distribución del Precio de la Vivienda",
xlab = "Precio de la Vivienda (millones COP)", ylab = "Frecuencia")
# Boxplot del precio de la vivienda
boxplot(bd_viviendas$preciom, main = "Boxplot del Precio de la Vivienda",
ylab = "Precio de la Vivienda (millones COP)", horizontal = TRUE, cex.lab = 0.7)
# Histograma del área de la vivienda
hist(bd_viviendas$areaconst, main = "Distribución del Área de la Vivienda",
xlab = "Área de la Vivienda (m²)", ylab = "Frecuencia")
# Boxplot del área de la vivienda
boxplot(bd_viviendas$areaconst, main = "Boxplot del Área de la Vivienda",
ylab = "Área de la Vivienda (m²)" , horizontal = TRUE, cex.lab = 0.7)
Se observa que tanto el precio como el área de la viviendapresenta una distribución asimétrica sesgada hacia la derecha, tambien se destacan varios posibles datos atípicos en el extremo superior.
Para profundizar en la relación entre la variable respuesta “Precio de la vivienda” en función de la variable predictora “Área construida” se realiza un análisis bivariado:
Inicialmente vemos un gráfico de dispersión entre el precio y el área de la vivienda
plot(bd_viviendas$areaconst, bd_viviendas$preciom, main = "Dispersión entre Precio y Área de la Vivienda",
xlab = "Área de la Vivienda (m²)", ylab = "Precio de la Vivienda (millones COP)")
abline(lm(preciom ~ areaconst, data = bd_viviendas), col = "red")
Gráficamente, se evidencia una relación positiva entre estas dos variables, dado que cuando el área de la vivienda es mayor, también aumenta el precio de las viviendas. Ahora validaremos esta observación con la estimación de la correlación de pearson.
# Calcular la matriz de correlación
correlacion <- cor(bd_viviendas %>% select_if(is.numeric)%>% select(-id) %>% select(-latitud)%>% select(-longitud) , use = "complete.obs")
# Crear el heatmap
corrplot(correlacion, method = "color",
col = colorRampPalette(c("blue", "white", "red"))(200),
type = "upper",
order = "hclust",
addCoef.col = "black",
tl.col = "black",
tl.srt = 45)
Se puede evidenciar que las variables más correlacionadas corresponden a precio de la vivienda y número de parqueaderos, asi como el precio y el area construida. Por su parte las variables menos correlacionadas corresponden al número de habitaciones con las variables precio y parqueaderos.
Ahora analizamos como es el comportamiento del precio de las viviendas segun la zona en la que se encuentran:
ggplot(bd_viviendas, aes(x = zona, y = preciom)) +
geom_boxplot() +
labs(x = "Zona", y = "Precio de la vivienda", title = "Boxplot del precio de la vivienda por zona")
## Warning: Removed 2 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
A pesar de que el numero de registros de cada zona es muy variable, teneniendo el mayor numero de registros en la zona sur y en la zona norte, se evidencia que las viviendas de la zona Oeste son los que tienen los precios mas altos. Mientras que las viviendas con los precios mas bajos se encuentran en el oriente de la ciudad.
Inicialmente revisamos como esta la información respecto a datos faltantes:
vivienda_num = bd_viviendas %>% select_if(is.numeric)%>% select(-id) %>% select(-latitud)%>% select(-longitud)
md.pattern(vivienda_num, rotate.names = TRUE)
## preciom areaconst banios habitaciones parqueaderos
## 6717 1 1 1 1 1 0
## 1602 1 1 1 1 0 1
## 1 1 0 0 0 0 4
## 2 0 0 0 0 0 5
## 2 3 3 3 1605 1616
Se logra identificar que:
Hay 6717 observaciones con datos completos para todas las variables analizadas. Hay 1602 observaciones con datos para todas las variables excepto parqueaderos. Hay una observación que solo tiene datos para preciom. Hay dos observaciones que no tienen datos para ninguna de las variables.
Eliminamos los 3 registros que tienen muy poca información en las diferentes variables, mientras que en el caso de la variable parqueadero realizamos una imputación ya que no cuenta con el \(19\%\) de sus datos.
# Eliminar registros con NA en la columna 'banios'
vivienda_num <- vivienda_num %>%
filter(!is.na(banios))
##### tratamos los datos faltantes de parqueadero
# Imputación KNN
Vivienda_imputado <- kNN(vivienda_num)
Vivienda_imputado = Vivienda_imputado %>% select_if(is.numeric)
### nuevamente revisamos datos faltantes
md.pattern(Vivienda_imputado, rotate.names = TRUE)
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
## preciom areaconst parqueaderos banios habitaciones
## 8319 1 1 1 1 1 0
## 0 0 0 0 0 0
Efectivamente no quedan variables con datos faltantes debido a la imputación por el método KNN (K-Nearest Neighbors). Esta técnica se consideró adecuada debido a su capacidad para utilizar la información de otras variables similares para imputar los valores perdidos.
Ahora procedemos a estandarizar las variables:
## estandarización
viviendaZ = Vivienda_imputado %>%
scale()
head(viviendaZ)
## preciom areaconst parqueaderos banios habitaciones
## [1,] -0.5595498 -0.7339949 -0.6877597 -0.07793773 1.6406840
## [2,] -0.3465670 -0.3842568 -0.6877597 -0.77811479 -0.4147626
## [3,] -0.2552886 0.3152194 0.2421075 -0.77811479 0.2703863
## [4,] -0.1031580 0.7349051 1.1719748 1.32241640 -0.4147626
## [5,] -0.5291236 -0.5940997 -0.6877597 -0.77811479 -0.4147626
## [6,] -0.5899759 -0.6150839 -0.6877597 -0.07793773 -0.4147626
Ahora procedemos a realizar el ACP, con la información que procesamos anteriormente.
## ACP
pca <- prcomp(viviendaZ)
Seleccionamos el número de componentes adecuado:
## ACP
fviz_eig(pca, addlabels = TRUE)
Se puede evidenciar que los primeros dos componentes recogen un total del 82,4% de la varianza explicada.
Ahora veamos la contribución de las variables a los componentes, Para interpretar los factores es necesario apreciar correctamente los elementos que contribuyeron a construir y definir a los factores, y la calidad de representación \((Cos^2)\), tanto de los individuos como de las variables, con dichos indicadores será posible determinar cuales son aquellas variables e individuos mejor representados en el plano y aquellas que mayor contribuyen a la formación de los ejes para así obtener mejores conclusiones de las relaciones representadas.
fviz_pca_var(pca,
col.var = "contrib", # Color by contributions to the PC
gradient.cols = c("#FF7F00", "#034D94"),
repel = TRUE # Avoid text overlapping
)
En este primer gráfico podemos identificar que las variables parqueaderos, precio, area construida y baños estan asociadas con el primer componente principal. Mientras que la variable Habitaciones al segundo componente. Adicionalmente se reafirma lo que vimos en las correlaciones, donde parqueadero y precio estan altamente correlacionadas, al igual que area construida y número de baños. Mientras que las variables parqueadero y precio estan poco correlacionadas con la variable habitaciones al tener un ángulo de \(45°\)
Ahora analizamos a los individuos:
fviz_pca_ind(pca, col.ind = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
Los individuos que se encuentran cercanos tienen un comportamiento similar en sus variables. Se pueden identificar las viviendas que más aportan en la construcción del primer y segundo eje factorial por su proximidad, del mismo modo las viviendas que no son excéntricas y se encuentran en el centro del primer plano factorial, son las que menos contribuyen a la formación de los ejes.
Representación simultanea:
vivienda_car <- bd_viviendas %>%
filter(!is.na(banios))
fviz_pca_biplot(pca,
repel = FALSE,
habillage = vivienda_car$estrato,
col.var = "#034A94", # Variables color
col.ind = c("#DEDEDE", "#034A94") # Individuals color
)
La representación simultanea nos permite observar la relación existente entre las variables e individuos. Adicionalmente en este caso agregamos la variable estrato y nos arroja resultados muy interesantes, las variables parqueadero y precio estan mas correlacionados con viviendas del estrato 6, mientras que las viviendas de estrato 5 se concentran mas en las variables area construida y número de baños.
Ahora procedemos a crear los clusters:
# PCA
res.pca <- PCA(Vivienda_imputado, graph = FALSE, scale.unit = TRUE )
# Calculamos la distancia euclidiana
distancia <- dist(res.pca$ind$coord, method = "euclidean")
# Cluster
res.HCPC <- HCPC(res.pca, nb.clust=4)
Validamos que el número de clusters sea el adecuado:
# distancia euclidiana
dist_emp <- dist(viviendaZ, method = 'euclidean')
# Cluster jerarquico con el método complete
hc_emp <- hclust(dist_emp, method = 'complete')
# Determinamos a dónde pertenece cada observación
cluster_assigments <- cutree(hc_emp, k = 4)
# Calcular el coeficiente de Silhouette
sil <- silhouette(cluster_assigments, dist(viviendaZ))
sil_avg <- mean(sil[,3])
# Imprimir el coeficiente de Silhouette promedio
cat("Coeficiente de Silhouette promedio k=4 : ", sil_avg)
## Coeficiente de Silhouette promedio k=4 : 0.4958457
El resultado nos indica que en general los puntos están bien agrupados dentro de su clúster y que los clústeres están bien separados.
Ahora veremos las caracteristicas de estos clusters respecto al resto de variables:
# Caracteristicas de las viviendas
res.HCPC$desc.var
##
## Link between the cluster variable and the quantitative variables
## ================================================================
## Eta2 P-value
## preciom 0.7116892 0
## areaconst 0.5858089 0
## parqueaderos 0.6158302 0
## banios 0.6355780 0
## habitaciones 0.6091471 0
##
## Description of each cluster by quantitative variables
## =====================================================
## $`1`
## v.test Mean in category Overall mean sd in category Overall sd
## habitaciones -47.11161 2.860570 3.605361 0.7181321 1.459449
## parqueaderos -51.99508 1.133967 1.739632 0.3461504 1.075358
## areaconst -55.20505 89.448470 174.934938 40.6189756 142.955533
## preciom -57.51519 229.152732 433.904436 94.2085431 328.645270
## banios -67.30810 2.070071 3.111311 0.5989557 1.428124
## p.value
## habitaciones 0
## parqueaderos 0
## areaconst 0
## preciom 0
## banios 0
##
## $`2`
## v.test Mean in category Overall mean sd in category Overall sd
## banios 25.176540 3.709690 3.111311 0.8184682 1.428124
## preciom 16.575553 524.563145 433.904436 192.6589268 328.645270
## parqueaderos 14.837052 2.005163 1.739632 0.5744538 1.075358
## areaconst 7.301088 192.305052 174.934938 77.8251788 142.955533
## p.value
## banios 7.239434e-140
## preciom 1.046947e-61
## parqueaderos 8.438382e-50
## areaconst 2.854502e-13
##
## $`3`
## v.test Mean in category Overall mean sd in category Overall sd
## habitaciones 63.62868 6.900690 3.605361 1.434957 1.459449
## banios 29.86512 4.624828 3.111311 1.469672 1.428124
## areaconst 26.80789 310.929159 174.934938 125.880160 142.955533
## p.value
## habitaciones 0.000000e+00
## banios 5.587357e-196
## areaconst 2.614474e-158
##
## $`4`
## v.test Mean in category Overall mean sd in category Overall sd
## preciom 67.57831 1148.288684 433.904436 350.800121 328.645270
## parqueaderos 63.67833 3.942263 1.739632 1.482427 1.075358
## areaconst 54.63508 426.163891 174.934938 205.948444 142.955533
## banios 44.73448 5.166282 3.111311 1.280542 1.428124
## habitaciones 17.50765 4.427252 3.605361 1.405169 1.459449
## p.value
## preciom 0.000000e+00
## parqueaderos 0.000000e+00
## areaconst 0.000000e+00
## banios 0.000000e+00
## habitaciones 1.252595e-68
# cruzamos con el resto de variables
data_with_clusters <- cbind(vivienda_car, cluster = res.HCPC$data.clust$clust)
# Gráfico de barras para estrato cruzada por clúster
ggplot(data_with_clusters, aes(x = factor(cluster), fill = estrato)) +
geom_bar(position = "dodge") +
theme_minimal()
# Gráfico de barras para zona cruzada por clúster
ggplot(data_with_clusters, aes(x = factor(cluster), fill = zona)) +
geom_bar(position = "dodge") +
theme_minimal()
A continuación se describen las caracteristicas de las variables cuantitativas de cada cluster:
Clúster 1: Obtiene los valores mas bajos en todas las variables analizadas, es decir las viviendas que pertenecen a este cluster tienen menos habitaciones, menor área construida, menos parqueaderos, menor número de baños y el precio más bajo, al compararlo con el resto de los clusters. En este cluster se encuentra la mayor proporción de viviendas de estrato 3 pertenecientes a zona sur y norte
Clúster 2: Este clúster agrupa viviendas con un número moderado de baños, precio moderado y poca área construida, sin embargo se evidencia que su estrato es de 5 y 6 principalmente y pertenecientes a zonas sur, oeste y norte.
Clúster 3: Este clúster agrupa viviendas con muchas habitaciones, muchos baños, y una gran área construida, este cluster tambien tiene como estrato principal viviendas de nivel 3 , se destaca la participación de la zona oriental en este estrato.
Clúster 4: Este grupo incluye viviendas con el precio mas alto, tambien tienen mas parqueaderos, mayor area construida, mas baños y más habitaciones, en este cluster se destaca notablemente que son viviendas de estrato 6 pertenecientes a zonas sur y oeste.
En este punto se pretente examinar la relación entre las variables categóricas (tipo de vivienda, zona y estrato), para identificar patrones de comportamiento de la oferta en mercado inmobiliario, utilizando un análisis de correspondencia.
Seleccionamos las variables y validamos que no tengamos datos nulos.
### Correspondencia
vivienda.AC <- vivienda_car[, c(2,4,10)]
head(vivienda.AC)
md.pattern(vivienda.AC, rotate.names = TRUE)
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
## zona estrato tipo
## 8319 1 1 1 0
## 0 0 0 0
# zona estrato
tabla <- table(vivienda.AC$zona, vivienda.AC$estrato)
colnames(tabla) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6" )
tabla
##
## Estrato3 Estrato4 Estrato5 Estrato6
## 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
chisq.test(tabla)
##
## Pearson's Chi-squared test
##
## data: tabla
## X-squared = 3830.4, df = 12, p-value < 2.2e-16
El valor p es menor a un \(\alpha = 0,05\) por lo que se rechaza la hipótesis de independencia de las variables, indicando un grado de relación entre ellas.
Finalmente se procede a realizar el análisis de correspondencia que consistes en estimar las coordenadas para cada uno de los niveles de ambas variables y representarlas en un plano cartesiano
resultados.ac.ZE <- CA(tabla)
Se identifican las siguientes relaciones en el gráfico:
Por ultimo, revisamos las varianzas acumuladas:
fviz_screeplot(resultados.ac.ZE, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")
Los resultados indican que la primera componente resumen el 70% y los dos primeros componentes prepresentados en el plano factorial, mientras que los dos primeros ejes resumen un 97.7% de los datos.
tabla2 <- table(vivienda.AC$tipo, vivienda.AC$zona)
colnames(tabla2) <- c("Zona_Centro", "Zona_Norte", "Zona_Oeste", "Zona_Oriente", "Zona_Sur")
tabla2
##
## Zona_Centro Zona_Norte Zona_Oeste Zona_Oriente Zona_Sur
## Apartamento 24 1198 1029 62 2787
## Casa 100 722 169 289 1939
chisq.test(tabla2)
##
## Pearson's Chi-squared test
##
## data: tabla2
## X-squared = 690.93, df = 4, p-value < 2.2e-16
El valor p es menor a un \(\alpha = 0,05\) por lo que se rechaza la hipótesis de independencia de las variables, indicando un grado de relación entre ellas.
tabla3 <- table(vivienda.AC$estrato, vivienda.AC$tipo)
colnames(tabla3) <- c("Casa", "Apartamento" )
tabla3
##
## Casa Apartamento
## 3 639 814
## 4 1404 725
## 5 1766 984
## 6 1291 696
chisq.test(tabla3)
##
## Pearson's Chi-squared test
##
## data: tabla3
## X-squared = 224.33, df = 3, p-value < 2.2e-16
El valor p es menor a un \(\alpha = 0,05\) por lo que se rechaza la hipótesis de independencia de las variables, indicando un grado de relación entre ellas.
El análisis detallado de la base de datos de viviendas en oferta de la ciudad de Cali ha revelado patrones clave y relaciones significativas que pueden guiar las decisiones estratégicas de la empresa inmobiliaria en un mercado altamente competitivo.
Inicialmente, la caracterización de las variables ha permitido identificar que la mayoría de las viviendas ofertadas se encuentran en la Zona Sur, mientras que la Zona Centro muestra una oferta considerablemente menor. Esta información es crucial para enfocar las estrategias de marketing y oferta de la empresa. El análisis descriptivo también resalta que el precio promedio de las viviendas es de 433.89 millones de pesos, y la mayoría de las propiedades tienen un tamaño promedio de \(174 m^2\), con un rango intercuartil que varía entre \(80\) y \(229 m^2\). Este hallazgo puede orientar la empresa en la segmentación y valoración de propiedades según su tamaño y ubicación.
Las correlaciones detectadas indican una fuerte relación entre el precio de la vivienda, el número de parqueaderos y el área construida, mientras que las habitaciones muestran menor correlación con estas variables. Esto sugiere que el valor de mercado de una vivienda está más influenciado por la infraestructura y espacio disponible que por el número de habitaciones, un insight que puede ayudar a redefinir las estrategias de pricing.
El análisis de componentes principales (ACP) ha demostrado que los primeros dos componentes explican el 82,4% de la varianza total, destacando que las variables como parqueaderos, precio, área construida y baños son las más influyentes. Este análisis refuerza la correlación entre parqueaderos y precio, y sugiere que las viviendas con mayor número de baños y mayor área construida suelen estar asociadas con un mayor valor de mercado. Además, se observa que las viviendas de estrato 6 tienen una relación más estrecha con estas variables, mientras que las viviendas de estrato 5 están más asociadas con el área construida y el número de baños. Estos insights pueden ser utilizados para orientar las políticas de mejora y desarrollo de propiedades.
El análisis de conglomerados ha permitido identificar cuatro clústeres distintos de viviendas, cada uno con características únicas:
Finalmente, el análisis de correspondencia ha mostrado una relación significativa entre la zona y el estrato de las viviendas, con el estrato 3 concentrado en las zonas Oriente y Centro, los estratos 4 y 5 en las zonas Sur y Norte, y el estrato 6 en la Zona Oeste. Esto confirma la segmentación socioeconómica de la ciudad y puede ser un factor clave en la planificación de estrategias de expansión y desarrollo.
Este análisis proporciona a la empresa inmobiliaria una ventaja competitiva significativa, permitiéndole optimizar inversiones y maximizar beneficios en un entorno dinámico y en constante cambio.