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.
se hace llamado de los datos “vivienda”
spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ id : num [1:8322] 1147 1169 1350 5992 1212 ...
$ zona : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
$ piso : chr [1:8322] NA NA NA "02" ...
$ estrato : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
$ preciom : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
$ areaconst : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
$ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
$ banios : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
$ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
$ tipo : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
$ barrio : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
$ longitud : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
$ latitud : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
- attr(*, "spec")=List of 3
..$ cols :List of 13
.. ..$ id : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ zona : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
.. ..$ piso : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
.. ..$ estrato : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ preciom : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ areaconst : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ parqueaderos: list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ banios : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ habitaciones: list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ tipo : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
.. ..$ barrio : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
.. ..$ longitud : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
.. ..$ latitud : list()
.. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
..$ default: list()
.. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
..$ delim : chr ";"
..- attr(*, "class")= chr "col_spec"
- attr(*, "problems")=<externalptr>
# Para encontrar valores vacíos en todo el conjunto de datos
library(mice)
head(vivienda)
# A tibble: 6 × 13
id zona piso estrato preciom areaconst parqueaderos banios habitaciones
<dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1147 Zona O… <NA> 3 250 70 1 3 6
2 1169 Zona O… <NA> 3 320 120 1 2 3
3 1350 Zona O… <NA> 3 350 220 2 2 4
4 5992 Zona S… 02 4 400 280 3 5 3
5 1212 Zona N… 01 5 260 90 1 2 3
6 1724 Zona N… 01 5 240 87 1 3 3
# ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
md.pattern(vivienda,rotate.names = TRUE)
preciom id zona estrato areaconst banios habitaciones tipo barrio longitud
4808 1 1 1 1 1 1 1 1 1 1
1909 1 1 1 1 1 1 1 1 1 1
876 1 1 1 1 1 1 1 1 1 1
726 1 1 1 1 1 1 1 1 1 1
1 1 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0
2 3 3 3 3 3 3 3 3 3
latitud parqueaderos piso
4808 1 1 1 0
1909 1 1 0 1
876 1 0 1 1
726 1 0 0 2
1 0 0 0 12
2 0 0 0 13
3 1605 2638 4275
vivienda2 <- data.frame(vivienda)
md.pattern(vivienda2,rotate.names = TRUE)
preciom id zona estrato areaconst banios habitaciones tipo barrio longitud
4808 1 1 1 1 1 1 1 1 1 1
1909 1 1 1 1 1 1 1 1 1 1
876 1 1 1 1 1 1 1 1 1 1
726 1 1 1 1 1 1 1 1 1 1
1 1 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0
2 3 3 3 3 3 3 3 3 3
latitud parqueaderos piso
4808 1 1 1 0
1909 1 1 0 1
876 1 0 1 1
726 1 0 0 2
1 0 0 0 12
2 0 0 0 13
3 1605 2638 4275
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 hace imputación de las variables parqueadero y piso. Se omiten aquellos registros que no esten completos. Quedando 8319 registros para el analisis
#imputar parqueaderos
vivienda2$parqueaderos[is.na(vivienda2$parqueaderos)] <-0
#imputar piso
vivienda2$piso[is.na(vivienda2$piso)] <-0
#imputar datos faltantes
vivienda2 <-na.omit(vivienda2)
md.pattern(vivienda2,rotate.names = TRUE)
/\ /\
{ `---' }
{ O O }
==> V <== No need for mice. This data set is completely observed.
\ \|/ /
`-----'
id zona piso estrato preciom areaconst parqueaderos banios habitaciones
8319 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0
tipo barrio longitud latitud
8319 1 1 1 1 0
0 0 0 0 0
El siguiente paso es convertir los registros de los campor piso,estrato,preciom,areaconst, banios, habitaciones en datos numericos.
#convertir en numerico los campos piso, preciom, aream , baños, habitaciones.
vivienda2$piso <-as.numeric(vivienda2$piso)
vivienda2$estrato <-as.numeric(vivienda2$estrato)
vivienda2$preciom <-as.numeric(vivienda2$preciom)
vivienda2$areaconst <-as.numeric(vivienda2$areaconst)
vivienda2$banios <-as.numeric(vivienda2$banios)
vivienda2$habitaciones <-as.numeric(vivienda2$habitaciones)
str(vivienda2)
'data.frame': 8319 obs. of 13 variables:
$ id : num 1147 1169 1350 5992 1212 ...
$ zona : chr "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
$ piso : num 0 0 0 2 1 1 1 1 2 2 ...
$ estrato : num 3 3 3 4 5 5 4 5 5 5 ...
$ preciom : num 250 320 350 400 260 240 220 310 320 780 ...
$ areaconst : num 70 120 220 280 90 87 52 137 150 380 ...
$ parqueaderos: num 1 1 2 3 1 1 2 2 2 2 ...
$ banios : num 3 2 2 5 2 3 2 3 4 3 ...
$ habitaciones: num 6 3 4 3 3 3 3 4 6 3 ...
$ tipo : chr "Casa" "Casa" "Casa" "Casa" ...
$ barrio : chr "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
$ longitud : num -76.5 -76.5 -76.5 -76.5 -76.5 ...
$ latitud : num 3.43 3.43 3.44 3.44 3.46 ...
- attr(*, "na.action")= 'omit' Named int [1:3] 8320 8321 8322
..- attr(*, "names")= chr [1:3] "8320" "8321" "8322"
Se crea una base de datos solo con datos numericos, en este se incluye los campos: -preciom -estrato -piso -areaconst -parqueaderos -barrio -habitaciones
Con el fin de evitar que las variables que tiene una escala con valores más grandes afecten las estimaciones realizadas (sesgos) se realiza la estandarización de las variables antes de proceder a realizar el proceso de estimación de los componentes principales.
vivienda2 <- vivienda2[,c("preciom","estrato","piso","areaconst","parqueaderos","banios","habitaciones")]
vivienda2= scale(vivienda2[,1:7])
head(vivienda2) # primeros 6 registros
preciom estrato piso areaconst parqueaderos banios
1 -0.5595498 -1.5872276 -0.9255638 -0.7339949 -0.3875522 -0.07793773
2 -0.3465670 -1.5872276 -0.9255638 -0.3842568 -0.3875522 -0.77811479
3 -0.2552886 -1.5872276 -0.9255638 0.3152194 0.4168506 -0.77811479
4 -0.1031580 -0.6156201 -0.2071010 0.7349051 1.2212534 1.32241640
5 -0.5291236 0.3559875 -0.5663324 -0.5940997 -0.3875522 -0.77811479
6 -0.5899759 0.3559875 -0.5663324 -0.6150839 -0.3875522 -0.07793773
habitaciones
1 1.6406840
2 -0.4147626
3 0.2703863
4 -0.4147626
5 -0.4147626
6 -0.4147626
prcomp(vivienda2)
Standard deviations (1, .., p=7):
[1] 1.8501262 1.1819381 0.9307555 0.6769022 0.6518585 0.4906918 0.4357238
Rotation (n x k) = (7 x 7):
PC1 PC2 PC3 PC4 PC5
preciom 0.47660417 0.1683184 -0.11405920 -0.01219188 0.3592424
estrato 0.32632057 0.5210267 -0.24346981 -0.54797999 -0.1712473
piso -0.05624508 0.5051515 0.84823031 0.04601540 0.1397874
areaconst 0.44355148 -0.2205624 0.03079337 0.20603152 0.6496296
parqueaderos 0.40706306 0.2474119 -0.08106990 0.72275475 -0.4872424
banios 0.46672129 -0.1339445 0.17622708 -0.33001544 -0.2103781
habitaciones 0.28798060 -0.5632233 0.41187588 -0.15400738 -0.3440872
PC6 PC7
preciom 0.21541366 -0.745587739
estrato -0.45625352 0.158093347
piso -0.02062750 0.008965092
areaconst -0.28414812 0.456572351
parqueaderos -0.04430878 0.069078491
banios 0.68056871 0.341805824
habitaciones -0.44623648 -0.298267787
Se elabora matriz de correlación.
#install.packages("FactoMineR")
#library("FactoMineR")
library(ggcorrplot)
corr_matrix <- cor(vivienda2)
ggcorrplot(corr_matrix)
library(tidyverse)
#install.packages("factoextra")
library(factoextra)
# Hacer PCA
r_pca <-prcomp(vivienda2)
#mostrar valores
#fviz_pca(r_pca,addlabels =TRUE)
fviz_eig(r_pca,addlabels =TRUE)
En este caso el primer componente principal explica el 48,9% de la
variabilidad contenida en la base de datos y entre los tres primeros se
casi el 80% de los datos (81.3), lo cual indicaría que con dos variable
(CP1.CP2) que se obtiene mediante una combinación lineal de las
variables se puede resumir gran parte de la variabilidad que contiene la
base de datos.
CP1: Preciom, estrato CP2:Piso, areaconst
#library(cont)
fviz_pca_var(r_pca,
col.var = "contrib", # Color by contributions to the pc
gradient.cols=c("#FF7F00","#034D94"),
repel = TRUE
)
Al visualizar las variables en el plano de los componentes principales permite identificar el sentido y la caracterización de los componentes.
fviz_pca_biplot(r_pca,label="Var",repel = TRUE)
informacion <- rbind(
vivienda[200,],
vivienda[1500,],
vivienda[5000,],
vivienda[8300,]
)
informacion<-as.data.frame(informacion)
rownames(informacion)=c("Vivienda 200","Vivienda 1500","Vivienda 5000","Vivienda 8300")
informacion
id zona piso estrato preciom areaconst parqueaderos
Vivienda 200 7617 Zona Oeste 05 6 950 217 3
Vivienda 1500 3635 Zona Sur 03 6 530 150 2
Vivienda 5000 7761 Zona Sur 01 5 350 176 1
Vivienda 8300 3490 Zona Sur 05 5 240 68 1
banios habitaciones tipo barrio longitud latitud
Vivienda 200 5 4 Apartamento aguacatal -76.55081 3.45659
Vivienda 1500 4 3 Casa ciudad jardín -76.52753 3.35735
Vivienda 5000 2 3 Casa pampalinda -76.55187 3.40384
Vivienda 8300 2 3 Apartamento zona sur -76.52673 3.37677
casos1 <- rbind(r_pca$x[200,1:2],r_pca$x[1500,1:2]) # CP1
rownames(casos1) = c("200","1500")
casos1 <- as.data.frame(casos1)
casos2 <- rbind(r_pca$x[5000,1:2], r_pca$x[8300,1:2]) # CP2
rownames(casos2) = c("5000","8300")
casos2 <- as.data.frame(casos2)
fviz_pca_ind(r_pca, col.ind = "#DEDEDE", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = "red", size = 3) +
geom_point(data = casos2, aes(x = PC1, y = PC2), color = "blue", size = 3)
datavivienda<- rbind(vivienda[200,],
vivienda[500,],
vivienda[5000,],
vivienda[8300,])
datavivienda
# A tibble: 4 × 13
id zona piso estrato preciom areaconst parqueaderos banios habitaciones
<dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 7617 Zona O… 05 6 950 217 3 5 4
2 7703 Zona O… <NA> 6 750 220 2 4 3
3 7761 Zona S… 01 5 350 176 1 2 3
4 3490 Zona S… 05 5 240 68 1 2 3
# ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
#library(factoextra)
#fviz_pca_biplot(r_pca,
#repel = TRUE,
#col.var = "#034A94", # Variables color
#col.ind = c("#DEDEDE") # Individuals color
#)
#habillage = vivienda2$preciom,
library(tidyverse)
#library(NbClust)
# distancia euclidiana
dist_emp <- dist(vivienda2, 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)
library(cluster)
fviz_nbclust(vivienda2,clara,method = "silhouette")+theme_classic()
plot(hc_emp, cex = 0.6, main = "Dendograma de Empresas", las=1,
ylab = "Distancia euclidiana", xlab = "Grupos")
rect.hclust(hc_emp, k = 2, border = 2:5)
La matriz de distancia se puede calcular usando la función dist (). Esta
función calcula y devuelve la matriz de distancia calculada utilizando
la medida de distancia especificada para calcular las distancias entre
las filas de una matriz de datos. Para ejecutar esta función, asegúrese
de que el paquete de estadísticas esté cargado usando la función require
().
El argumento x especifica una matriz numérica, un marco de datos o un objeto “dist”. El método del segundo argumento especifica la medida de distancia que se utilizará. El método debe ser uno de los siguientes:
“euclidiana”, “máximo”, “manhattan”, “canberra”, “binario” o “minkowski”
Calcule los resultados del objeto dist_emp como una matriz utilizando la función as.matrix () y especifique el número de filas y columnas que se imprimirán entre corchetes.
#dendograma <- hclust(dist_emp, method = "average")
#grp <- cutree(dendograma, k = 4)
#grp
# Imprimi la matriz de distancias
output = as.matrix(dist_emp)[1:7, 1:7]
round(output, digits = 3)
1 2 3 4 5 6 7
1 0.000 2.210 2.051 3.550 2.940 2.854 2.542
2 2.210 0.000 1.270 3.126 1.996 2.123 1.428
3 2.051 1.270 0.000 2.681 2.434 2.547 1.755
4 3.550 3.126 2.681 0.000 3.166 2.772 2.834
5 2.940 1.996 2.434 3.166 0.000 0.703 1.295
6 2.854 2.123 2.547 2.772 0.703 0.000 1.465
7 2.542 1.428 1.755 2.834 1.295 1.465 0.000
El método “dist” de as.matrix() y as.dist() se puede utilizar para la conversión entre objetos de la clase “dist” y matrices de distancia convencionales.
d = as.dist(output)
d
1 2 3 4 5 6
2 2.2097029
3 2.0514514 1.2704690
4 3.5496871 3.1260947 2.6810844
5 2.9395131 1.9956184 2.4338183 3.1656366
6 2.8539548 2.1231837 2.5474208 2.7716020 0.7031296
7 2.5415399 1.4279160 1.7549518 2.8340236 1.2948155 1.4645720
library(factoextra)
dist_emp <- dist(vivienda2, method = "euclidean")
dendograma <- hclust(dist_emp, method = "average")
# plot(dendograma, cex = 0.6, hang = -1)
barplot(sort(dendograma$height, decreasing = TRUE), horiz = TRUE,
main = "Agregaciones (distancias euclidianas)",
col = "lightblue", ylab = "Nodo", xlab = "Peso", xlim = c(0, 2.5))
library(tidyverse)
library(cluster)
# distancia euclidiana
dist_emp <- dist(vivienda2, 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 = 2)
# Calcular el coeficiente de Silhouette
sil <- silhouette(cluster_assigments, dist(vivienda2))
sil_avg <- mean(sil[,3])
# Imprimir el coeficiente de Silhouette promedio
cat("Coeficiente de Silhouette promedio k=2 : ", sil_avg)
Coeficiente de Silhouette promedio k=2 : 0.5382836
El agrupamiento jerárquico es un análisis de agrupamiento sobre un conjunto de diferencias y métodos para analizarlo. Dicho agrupamiento se realiza mediante el uso de la hclust() función en el paquete de estadísticas .
El argumento despecifica una estructura de disimilitud producida por la dist() función. El segundo argumento es el method que especifica el método de aglomeración que se utilizará.
En el ejercicio se identifican dos cluster, con un coeficiente de Silhouette 0,5382.
vivienda3 <- vivienda[,c("tipo","zona","barrio")]
vivienda3$tipo <- as.factor(vivienda3$tipo)
vivienda3$zona <- as.factor(vivienda3$zona)
vivienda3$barrio <- as.factor(vivienda3$barrio)
Para el analisis de correspondencia se utilizan los campos tipo y zona, se eliminan los campos vacios.
library(mice)
md.pattern(vivienda3, rotate.names = TRUE)
tipo zona barrio
8319 1 1 1 0
3 0 0 0 3
3 3 3 9
library(mice)
vivienda3 <- na.omit(vivienda3)
grafico <-md.pattern(vivienda3, rotate.names = TRUE)
/\ /\
{ `---' }
{ O O }
==> V <== No need for mice. This data set is completely observed.
\ \|/ /
`-----'
library(FactoMineR)
tabla <- table(vivienda3$tipo, vivienda3$zona)
tabla
Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
Apartamento 24 1198 1029 62 2787
Casa 100 722 169 289 1939
Con la información suministrada en la tabla, se puede concluir que tanto en apartamentos y casas, la mayor concentración esta en el sur de la ciudad.
chisq.test(tabla)
Pearson's Chi-squared test
data: tabla
X-squared = 690.93, df = 4, p-value < 2.2e-16
El resultado indica que se rechaza la hipótesis de independencia de las variables (p-value: 0.0000), indicando grado tipo de relación entre ellas.
library(FactoMineR)
library(factoextra)
library(gridExtra)
library(dplyr)
resultados_ac <- CA(tabla)
valores_prop <-resultados_ac$eig