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 consiste 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.
# devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
data("vivienda")
library(tidyverse)
library(mice)
library(psych)
library(corrplot)
library(dplyr)
library(factoextra)
library(RColorBrewer)
library(FactoMineR)
dimension <- dim(vivienda)
dimension
## [1] 8322 13
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
Para el análisis Se eliminan datos no relevantes del data frame como son la altitud, la longitud, y el barrio, creamos otra variable sin estos atributos.
vivienda_1 <- subset(vivienda, select = -c(longitud, latitud, barrio))
head(vivienda_1,5)
## # A tibble: 5 × 10
## 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
## # ℹ 1 more variable: tipo <chr>
str(vivienda_1)
## tibble [8,322 × 10] (S3: 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" ...
El dataset contiene:
* 4 variables categóricas: zona, piso, tipo,
estrato.
* 5 variables numéricas: preciom,areaconst,
parqueaderos,banios,habitaciones.
* 1 variable munerica tipo
indice. * se observa que la variable piso contiene NAs.
vivienda_1 %>%
group_by(zona) %>%
summarise(n = n(), .groups = "drop")
## # A tibble: 6 × 2
## zona n
## <chr> <int>
## 1 Zona Centro 124
## 2 Zona Norte 1920
## 3 Zona Oeste 1198
## 4 Zona Oriente 351
## 5 Zona Sur 4726
## 6 <NA> 3
vivienda_1 %>%
group_by(tipo) %>%
summarise(n = n(), .groups = "drop")
## # A tibble: 3 × 2
## tipo n
## <chr> <int>
## 1 Apartamento 5100
## 2 Casa 3219
## 3 <NA> 3
vivienda_1 %>%
group_by(piso) %>%
summarise(n = n(), .groups = "drop") %>%
arrange(desc(n)) %>%
head(20)
## # A tibble: 13 × 2
## piso n
## <chr> <int>
## 1 <NA> 2638
## 2 02 1450
## 3 03 1097
## 4 01 860
## 5 04 607
## 6 05 567
## 7 06 245
## 8 08 211
## 9 07 204
## 10 09 146
## 11 10 130
## 12 11 84
## 13 12 83
vivienda %>%
group_by(barrio) %>%
summarise(n = n(), .groups = "drop") %>%
arrange(desc(n)) %>%
head(5)
## # A tibble: 5 × 2
## barrio n
## <chr> <int>
## 1 valle del lili 1008
## 2 ciudad jardín 516
## 3 pance 409
## 4 la flora 366
## 5 santa teresita 262
resumen <- describe(vivienda$preciom)
resumen
## vars n mean sd median trimmed mad min max range skew kurtosis
## X1 1 8320 433.89 328.65 330 374.43 207.56 58 1999 1941 1.85 3.67
## se
## X1 3.6
vivienda_2 = vivienda[,c(2:13)]
md.pattern(vivienda_2, rotate.names = TRUE)
## preciom zona estrato areaconst banios habitaciones tipo barrio longitud
## 4808 1 1 1 1 1 1 1 1 1
## 1909 1 1 1 1 1 1 1 1 1
## 876 1 1 1 1 1 1 1 1 1
## 726 1 1 1 1 1 1 1 1 1
## 1 1 0 0 0 0 0 0 0 0
## 2 0 0 0 0 0 0 0 0 0
## 2 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 11
## 2 0 0 0 12
## 3 1605 2638 4272
Observamos que:
Hay 4808 registros con datos completos para todos los atributos.
Hay 2785 registros con datos para todas las variables excepto
parqueaderos.
Hay 1 registro que solo tiene datos para lel atributo
preciom.
Hay 2 registros que no tienen datos para ninguna de las
variables.
El atributo parqueaderos y piso presentan datos faltantes en 1602 de
los registros.
esta variable es relevante para determinar el precio
de las viviendas,
se decide eliminar los registros que no presentan
datos completos,
de esta manera, se construirá un conjunto de datos
sin registros faltantes.
vivienda_2 <- na.omit(vivienda_2)
md.pattern(vivienda_2, rotate.names = TRUE)
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
## zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo
## 4808 1 1 1 1 1 1 1 1 1
## 0 0 0 0 0 0 0 0 0
## barrio longitud latitud
## 4808 1 1 1 0
## 0 0 0 0
boxplot(vivienda_2$preciom~ vivienda_2$zona, data = vivienda_2, col = c("blue", "purple", "green","red","cyan" ), ylab = "Precio", xlab = "Zona")
boxplot(vivienda_2$preciom ~ vivienda_2$estrato,
data = vivienda_2, col = c("red", "blue", "purple", "green"),
ylab = "Precio", xlab = "Estrato")
var_numericas <- vivienda_2[, c("preciom","estrato", "areaconst",
"habitaciones", "banios","parqueaderos")]
correlacion<-round(cor(var_numericas), 1)
corrplot(correlacion, method="number", type="upper")
Para el atributo preciom se observa una correlación fuerte con
estrato,
areaconst, banios y parqueaderos, indica que un aumento en
cualquiera de esas
características podría impactar directamente en
el precio.
vivienda_3 <- vivienda_2 %>%
mutate(zona = case_when(
zona == "Zona Centro" ~ 1,
zona == "Zona Norte" ~ 2,
zona == "Zona Oeste" ~ 3,
zona == "Zona Oriente" ~ 4,
zona == "Zona Sur" ~ 5,
TRUE ~ NA_real_ # Si existe alguna categoría no especificada, será convertida a NA
))
head(vivienda_3,5)
## # A tibble: 5 × 12
## zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 5 02 4 400 280 3 5 3 Casa
## 2 2 01 5 260 90 1 2 3 Aparta…
## 3 2 01 5 240 87 1 3 3 Aparta…
## 4 2 01 4 220 52 2 2 3 Aparta…
## 5 2 01 5 310 137 2 3 4 Aparta…
## # ℹ 3 more variables: barrio <chr>, longitud <dbl>, latitud <dbl>
vivienda_3 <- vivienda_3 %>%
mutate(tipo = case_when(
tipo == "Casa" ~ 1,
tipo == "Apartamento" ~ 2,
TRUE ~ NA_real_ # Si existe alguna categoría no especificada, será convertida a NA
))
head(vivienda_3,5)
## # A tibble: 5 × 12
## zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 5 02 4 400 280 3 5 3 1
## 2 2 01 5 260 90 1 2 3 2
## 3 2 01 5 240 87 1 3 3 2
## 4 2 01 4 220 52 2 2 3 2
## 5 2 01 5 310 137 2 3 4 2
## # ℹ 3 more variables: barrio <chr>, longitud <dbl>, latitud <dbl>
vivienda_3$piso <- as.numeric(as.factor(vivienda_3$piso))
head(vivienda_3,5)
## # A tibble: 5 × 12
## zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 5 2 4 400 280 3 5 3 1
## 2 2 1 5 260 90 1 2 3 2
## 3 2 1 5 240 87 1 3 3 2
## 4 2 1 4 220 52 2 2 3 2
## 5 2 1 5 310 137 2 3 4 2
## # ℹ 3 more variables: barrio <chr>, longitud <dbl>, latitud <dbl>
Validamos que los atributos sean numéricos.
var_numericas <- vivienda_3[, c("zona","piso","preciom","estrato","areaconst", "habitaciones", "banios","parqueaderos")]
str(var_numericas)
## tibble [4,808 × 8] (S3: tbl_df/tbl/data.frame)
## $ zona : num [1:4808] 5 2 2 2 2 2 2 2 2 2 ...
## $ piso : num [1:4808] 2 1 1 1 1 2 2 2 2 2 ...
## $ preciom : num [1:4808] 400 260 240 220 310 320 780 625 750 520 ...
## $ estrato : num [1:4808] 4 5 5 4 5 5 5 4 5 6 ...
## $ areaconst : num [1:4808] 280 90 87 52 137 150 380 355 237 98 ...
## $ habitaciones: num [1:4808] 3 3 3 3 4 6 3 5 6 2 ...
## $ banios : num [1:4808] 5 2 3 2 3 4 3 5 6 2 ...
## $ parqueaderos: num [1:4808] 3 1 1 2 2 2 2 3 2 2 ...
## - attr(*, "na.action")= 'omit' Named int [1:3514] 1 2 3 11 20 28 29 30 31 32 ...
## ..- attr(*, "names")= chr [1:3514] "1" "2" "3" "11" ...
Procedemos al escalamiento de atributos
vivienda_escalados<- scale(var_numericas)
vivienda_escalados<- as.data.frame(vivienda_escalados)
head(vivienda_escalados)
## zona piso preciom estrato areaconst habitaciones
## 1 0.7275272 -0.7053307 -0.1756310 -0.9046263 0.7609789 -0.4241459
## 2 -1.6547322 -1.0793910 -0.6055839 0.1749079 -0.6129041 -0.4241459
## 3 -1.6547322 -1.0793910 -0.6670057 0.1749079 -0.6345970 -0.4241459
## 4 -1.6547322 -1.0793910 -0.7284276 -0.9046263 -0.8876807 -0.4241459
## 5 -1.6547322 -1.0793910 -0.4520293 0.1749079 -0.2730489 0.3272519
## 6 -1.6547322 -0.7053307 -0.4213184 0.1749079 -0.1790463 1.8300475
## banios parqueaderos
## 1 1.3178809 1.0779092
## 2 -0.9022913 -0.7415001
## 3 -0.1622339 -0.7415001
## 4 -0.9022913 0.1682046
## 5 -0.1622339 0.1682046
## 6 0.5778235 0.1682046
var_numericas<- vivienda_escalados%>% dplyr::select(piso, preciom, areaconst, parqueaderos, banios, habitaciones, estrato, zona)
viviendas_inm.pca <- prcomp(var_numericas)
viviendas_inm.pca
## Standard deviations (1, .., p=8):
## [1] 1.8934907 1.1729607 1.0065147 0.8877098 0.6872507 0.5838310 0.4943041
## [8] 0.4245549
##
## Rotation (n x k) = (8 x 8):
## PC1 PC2 PC3 PC4 PC5
## piso 0.1006163 -0.56695684 -0.14550751 0.78786052 0.1398137
## preciom -0.4616542 -0.23721827 0.01726248 -0.07707993 0.1182165
## areaconst -0.4509652 0.15963075 -0.09855926 0.03582193 0.2274388
## parqueaderos -0.4259240 -0.12741728 0.03413680 -0.13216843 0.6117680
## banios -0.4623089 0.07067348 -0.01515671 0.19441374 -0.2980012
## habitaciones -0.3105711 0.49406708 -0.22227209 0.41374895 -0.3268759
## estrato -0.2857550 -0.53792764 0.25462414 -0.23388724 -0.5790675
## zona -0.0114495 0.20520022 0.92367866 0.30148738 0.0975535
## PC6 PC7 PC8
## piso 0.03226654 0.05540952 -0.05366996
## preciom 0.31811769 -0.20054345 0.75430225
## areaconst 0.64623223 0.29951276 -0.44844054
## parqueaderos -0.61350699 0.14115618 -0.11464616
## banios -0.13937949 -0.72620381 -0.32809451
## habitaciones -0.27269427 0.41678388 0.28970914
## estrato -0.08800133 0.38143735 -0.14451077
## zona 0.04711732 0.02244820 0.03800297
fviz_eig(viviendas_inm.pca, addlabels = TRUE)
prop_varianza <- viviendas_inm.pca$sdev^2/sum(viviendas_inm.pca$sdev^2)
round(prop_varianza*100, 2)
## [1] 44.82 17.20 12.66 9.85 5.90 4.26 3.05 2.25
prop_varianza_acum <- cumsum(prop_varianza)
round(prop_varianza_acum*100, 2)
## [1] 44.82 62.01 74.68 84.53 90.43 94.69 97.75 100.00
ggplot(data = data.frame(prop_varianza_acum, pc = 1:8),
aes(x = pc, y = prop_varianza_acum, group = 1)) +
geom_point() +
geom_line() +
theme_bw() +
labs(x = "Componente principal",
y = "Prop. varianza explicada acumulada")
Observamos que las primeras 4 componentes explican el 84.53% de la varianza observada.
scree(var_numericas,main ="Grafico de Sedimentacion")
fviz_pca_var(viviendas_inm.pca,
col.var = "contrib", #
gradient.cols = c("#FF7F00", "#034D94"),
repel = TRUE
)
fviz_contrib(viviendas_inm.pca, choice = "var", axes = 1, top = 10) # PC1
Se observa que el PC 1 esta asociado a los baños, el precio,
el
área construida,y los parqueaderos.
fviz_contrib(viviendas_inm.pca, choice = "var", axes = 2, top = 10) # PC2
Se observa que el PC 2 está asociado al piso, estrato y las habitaciones.
fviz_contrib(viviendas_inm.pca, choice = "var", axes = 3, top = 10) # PC3
Se observa que el PC 3 está asociado a la zona.
fviz_contrib(viviendas_inm.pca, choice = "var", axes = 4, top = 10) # PC4
Se observa que el PC 4 se encuentra asociado al piso y las
habitaciones
# Obtenemos las puntuaciones (scores) en la primera componente principal (PC1)
scores <- viviendas_inm.pca$x
# Seleccionar los índices de los valores más altos y más bajos en PC1 y PC2
casos_extremos <- c(
which.max(scores[,1]), # Índice del valor máximo en PC1
which.min(scores[,1]), # Índice del valor mínimo en PC1
which.max(scores[,2]), # Índice del valor máximo en PC2
which.min(scores[,2]) # Índice del valor mínimo en PC2
)
casos1 <- rbind(viviendas_inm.pca$x[casos_extremos[1],1:2],viviendas_inm.pca$x[casos_extremos[2],1:2]) # CP1
rownames(casos1) = c(as.character(casos_extremos[1]), as.character(casos_extremos[2]))
casos1 <- as.data.frame(casos1)
casos2 <- rbind(viviendas_inm.pca$x[casos_extremos[3],1:2],viviendas_inm.pca$x[casos_extremos[4],1:2]) # CP2
rownames(casos2) = c(as.character(casos_extremos[3]), as.character(casos_extremos[4]))
casos2 <- as.data.frame(casos2)
fviz_pca_ind(viviendas_inm.pca, col.ind = "#DEDEDE", gradient.cols = c("#2E9FDF", "#E7B800", "#FC4E07")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = c("#2E9FDF", "#E7B800"), size = 3) +
geom_point(data = casos2, aes(x = PC1, y = PC2), color = c("#FF7F00", "#034D94"), size = 3)
inm_caso_extremo <- vivienda_3[casos_extremos, ]
inm_caso_extremo
## # A tibble: 4 × 12
## zona piso estrato preciom areaconst parqueaderos banios habitaciones tipo
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 5 1 3 160 50 1 1 1 2
## 2 5 4 6 1600 836 8 9 5 1
## 3 2 3 3 370 1440 1 4 10 1
## 4 3 12 6 1500 236 3 5 3 2
## # ℹ 3 more variables: barrio <chr>, longitud <dbl>, latitud <dbl>
El primer componenete explica el 44,82% de la varianza observada
y está
asociado a los baños, el precio, el área construida,y los
parqueaderos.
El segundo componente explica el 17.20% de la varianza observada
y está
asociado al piso, estrato y las habitaciones.
El tercer componente explica el 12,66% de la varianza observada y
está
asociado a la zona.
El cuarto componente explica el 9.85% de la varianza observada y
esta
asociado al piso y las habitaciones.
Los cuatro componnetes principales representan un 84,53% de la
varianza
acumulada.
En este análisis se requiere agrupar las propiedades en grupos
homogéneos,
con características similares para poder concluir qué
elementos difieren la
oferta de los inmuebles en diferentes zonas
de la ciudad.
cluster_vars <- vivienda_3 %>% dplyr::select(piso, preciom, areaconst, parqueaderos, banios, habitaciones, estrato, tipo, zona)
cluster_vars
## # A tibble: 4,808 × 9
## piso preciom areaconst parqueaderos banios habitaciones estrato tipo zona
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2 400 280 3 5 3 4 1 5
## 2 1 260 90 1 2 3 5 2 2
## 3 1 240 87 1 3 3 5 2 2
## 4 1 220 52 2 2 3 4 2 2
## 5 1 310 137 2 3 4 5 2 2
## 6 2 320 150 2 4 6 5 1 2
## 7 2 780 380 2 3 3 5 1 2
## 8 2 625 355 3 5 5 4 1 2
## 9 2 750 237 2 6 6 5 1 2
## 10 2 520 98 2 2 2 6 2 2
## # ℹ 4,798 more rows
inm_escalado_cluster <- scale(cluster_vars)
inm_escalado_cluster <- as.data.frame(inm_escalado_cluster)
set.seed(123)
fviz_nbclust(inm_escalado_cluster, kmeans, method = "silhouette") +
labs(subtitle = "Silhouette method")
#### 3. Determinación del metodo del codo.
set.seed(123)
wss <- numeric()
for(h in 1:10){
b<-kmeans(inm_escalado_cluster,h)
wss[h]<-b$tot.withinss #scintra
}
wss
## [1] 43263.00 30465.33 26267.71 22184.12 20407.79 18361.24 17462.50 16811.93
## [9] 15556.40 14436.77
wss1 <- data.frame(cluster=c(1:10),wss)
wss1
## cluster wss
## 1 1 43263.00
## 2 2 30465.33
## 3 3 26267.71
## 4 4 22184.12
## 5 5 20407.79
## 6 6 18361.24
## 7 7 17462.50
## 8 8 16811.93
## 9 9 15556.40
## 10 10 14436.77
plot(1:10, wss, type = "b", pch = 19, frame = FALSE,
xlab = "Número de clusters K",
ylab = "Suma de las distancias dentro de los clusters",
main = "Método del Codo")
de <- dist(inm_escalado_cluster, method = "manhattan")
hc_emp <- hclust(de, method = "complete" )
cluster_assigments <- cutree(hc_emp, k = 4)
assigned_cluster <- inm_escalado_cluster %>% mutate(cluster = as.factor(cluster_assigments))
table(assigned_cluster$cluster)
##
## 1 2 3 4
## 604 2900 1260 44
color = c("#2E9FDF", "#E7B800","#FC4E07","blue")
ggplot(assigned_cluster, aes(x = cluster)) +
geom_bar(fill = color) +
labs(title = "Distribución de viviendas en cada clúster",
x = "Clúster",
y = "Cantidad de viviendas") +
theme_minimal() +
geom_text(stat='count', aes(label=..count..), vjust=-0.5)
colors <- brewer.pal(n = 10, name = "Set3")
ggplot(assigned_cluster, aes(x = preciom, y = areaconst, color = factor(cluster))) +
geom_point() +
labs(title = "Relación entre precio y área construida por clúster",
x = "Precio",
y = "Área construida",
color = "Clúster") +
theme(legend.position = "bottom")
plot(hc_emp, labels = FALSE, hang = -1, main = "Dendrograma del Clustering Jerárquico")
rect.hclust(hc_emp, k = 3, border = 1:7) # Agrega rectángulos alrededor de los clusters
set.seed(123) # Fijar la semilla para la reproducibilidad
kmeans_result <- kmeans(inm_escalado_cluster, centers = 4, nstart = 25)
assigned_cluster2 <- inm_escalado_cluster %>%
as.data.frame() %>%
mutate(cluster = as.factor(kmeans_result$cluster))
table(assigned_cluster2$cluster)
##
## 1 2 3 4
## 1126 2033 541 1108
ggplot(assigned_cluster2, aes(x = preciom, y = areaconst, color = cluster)) +
geom_point(size = 1) +
labs(title = "Clusters Identificados por K-means",
x = "Área Construida",
y = "Precio M2") +
theme_minimal()
# Análisis de conglomerados con k-means
num_clusters <- 4
kmeans_result <- kmeans(viviendas_inm.pca$x[, 1:2], centers = num_clusters)
# Agregar la información de los clusters al conjunto de datos original
vivienda_escalados$cluster <- as.factor(kmeans_result$cluster)
# Graficar las puntuaciones de los componentes principales coloreadas por cluster
ggplot(vivienda_escalados, aes(x = viviendas_inm.pca$x[, 1], y = viviendas_inm.pca$x[, 2], color = cluster)) +
geom_point() +
labs(title = "Resultados del Análisis de Conglomerados")
La cantidad de clusters que sugieren los métodos es entre 2 y 4, se
escoge
k=4. Con el modelo K-means se generaron 4 grupos con
características similares.
Este análisis aplica solo a variables categóricas,interesa conocer la
relación entre zona, estrato y tipo.
datos_categoricos <- vivienda_2 %>% dplyr::select(zona, estrato, tipo)
tablaZonaEstrato <- table(datos_categoricos$zona, datos_categoricos$estrato)
tablaZonaEstrato
##
## 3 4 5 6
## Zona Centro 33 3 0 0
## Zona Norte 141 184 482 79
## Zona Oeste 19 51 181 502
## Zona Oriente 94 2 1 0
## Zona Sur 147 973 1195 721
chisq.test(tablaZonaEstrato)
##
## Pearson's Chi-squared test
##
## data: tablaZonaEstrato
## X-squared = 2172.8, df = 12, p-value < 2.2e-16
El resultado indica que se rechaza la hipótesis de independencia
(hipótesis nula) de las variables Zona~estrato (p-value: 0.0000),
indicando algún grado de relación entre ellas.
resultados_ac <- CA(tablaZonaEstrato)
De este gráfico podemos concluir lo siguiente: - Las viviendas del
Oeste son
estrato 6 - Las viviendas de la zona norte y sur son
principalmente del
estrato 4 y 5 - Las viviendas del oriente y
centro son en su mayoría estrato 3.
valores_prop <-resultados_ac$eig
valores_prop
## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.29526876 65.338252 65.33825
## dim 2 0.13919088 30.800716 96.13897
## dim 3 0.01744831 3.861032 100.00000
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")
Este gráfico nos muestra el porcentaje de varianza de cada
componente,
el primer componente explica el 65,3% del total de la
varianza y la segunda
el 30.8%. las dos primeras componentes
explican el 96.1% de la varianza de los datos.
Con el fin de obtener un mayor grado de detalle en cuanto a la
relación de
zona y estrato se procede a evaluar el efecto del tipo
de inmueble, para
esto se va a crear una columna que relacione el
tipo y la zona y se
compararán contra el estrato.
datos_categoricos <- datos_categoricos %>%
mutate(zona_tipo = paste(zona, tipo, sep = "-"))
datos_categoricos
## # A tibble: 4,808 × 4
## zona estrato tipo zona_tipo
## <chr> <dbl> <chr> <chr>
## 1 Zona Sur 4 Casa Zona Sur-Casa
## 2 Zona Norte 5 Apartamento Zona Norte-Apartamento
## 3 Zona Norte 5 Apartamento Zona Norte-Apartamento
## 4 Zona Norte 4 Apartamento Zona Norte-Apartamento
## 5 Zona Norte 5 Apartamento Zona Norte-Apartamento
## 6 Zona Norte 5 Casa Zona Norte-Casa
## 7 Zona Norte 5 Casa Zona Norte-Casa
## 8 Zona Norte 4 Casa Zona Norte-Casa
## 9 Zona Norte 5 Casa Zona Norte-Casa
## 10 Zona Norte 6 Apartamento Zona Norte-Apartamento
## # ℹ 4,798 more rows
tablaZonaEstrato2 <- table(datos_categoricos$zona_tipo, datos_categoricos$estrato)
tablaZonaEstrato2
##
## 3 4 5 6
## Zona Centro-Apartamento 2 2 0 0
## Zona Centro-Casa 31 1 0 0
## Zona Norte-Apartamento 107 114 348 63
## Zona Norte-Casa 34 70 134 16
## Zona Oeste-Apartamento 10 34 153 472
## Zona Oeste-Casa 9 17 28 30
## Zona Oriente-Apartamento 15 1 1 0
## Zona Oriente-Casa 79 1 0 0
## Zona Sur-Apartamento 79 657 784 340
## Zona Sur-Casa 68 316 411 381
resultados_ac <- CA(tablaZonaEstrato2)
summary(resultados_ac)
##
## Call:
## CA(X = tablaZonaEstrato2)
##
## The chi square of independence between the two variables is equal to 2331.031 (p-value = 0 ).
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3
## Variance 0.302 0.164 0.019
## % of var. 62.263 33.873 3.864
## Cumulative % of var. 62.263 96.136 100.000
##
## Rows
## Iner*1000 Dim.1 ctr cos2 Dim.2
## Zona Centro-Apartamento | 2.297 | 1.448 0.578 0.759 | -0.002
## Zona Centro-Casa | 62.567 | 2.932 18.952 0.914 | 0.868
## Zona Norte-Apartamento | 35.146 | 0.370 5.972 0.513 | -0.206
## Zona Norte-Casa | 12.363 | 0.280 1.375 0.336 | -0.366
## Zona Oeste-Apartamento | 137.217 | -0.528 12.837 0.282 | 0.839
## Zona Oeste-Casa | 0.837 | -0.005 0.000 0.001 | 0.219
## Zona Oriente-Apartamento | 27.040 | 2.662 8.300 0.927 | 0.726
## Zona Oriente-Casa | 163.124 | 2.991 49.319 0.913 | 0.903
## Zona Sur-Apartamento | 37.692 | -0.093 1.099 0.088 | -0.286
## Zona Sur-Casa | 6.541 | -0.139 1.570 0.724 | 0.054
## ctr cos2 Dim.3 ctr cos2
## Zona Centro-Apartamento 0.000 0.000 | 0.815 2.951 0.241 |
## Zona Centro-Casa 3.052 0.080 | 0.227 1.832 0.005 |
## Zona Norte-Apartamento 3.412 0.159 | -0.296 61.479 0.328 |
## Zona Norte-Casa 4.317 0.573 | -0.146 6.000 0.091 |
## Zona Oeste-Apartamento 59.631 0.714 | -0.062 2.877 0.004 |
## Zona Oeste-Casa 0.509 0.999 | 0.003 0.001 0.000 |
## Zona Oriente-Apartamento 1.135 0.069 | 0.186 0.654 0.005 |
## Zona Oriente-Casa 8.255 0.083 | 0.204 3.680 0.004 |
## Zona Sur-Apartamento 19.256 0.839 | 0.084 14.697 0.073 |
## Zona Sur-Casa 0.433 0.109 | 0.067 5.829 0.167 |
##
## Columns
## Iner*1000 Dim.1 ctr cos2 Dim.2
## 3 | 263.068 | 1.665 82.918 0.951 | 0.375
## 4 | 47.058 | -0.074 0.462 0.030 | -0.377
## 5 | 33.362 | -0.041 0.212 0.019 | -0.249
## 6 | 141.336 | -0.428 16.408 0.350 | 0.582
## ctr cos2 Dim.3 ctr cos2
## 3 7.737 0.048 | 0.026 0.319 0.000 |
## 4 21.819 0.761 | 0.197 52.491 0.209 |
## 5 14.620 0.720 | -0.150 46.503 0.261 |
## 6 55.824 0.649 | 0.022 0.688 0.001 |
El estrato 6 corresponde en su mayoría a los apartamentos y las
casas del
oeste con una pequeña presencia de casas en el
sur.
Los apartamentos del sur y el norte están predominantemente en
estratos 4 y 5.
Los apartamentos de la zona norte y la casas del norte están el
estrato
4 y 5.
La zona oriente tanto para casas como para apartamentos
corresponden al
estrato 3.
Los apartamentos de la zona centro no son principalmente del
estrato 3
también se aprecia tendencia a 4 y 5.
Existe gran oferta inmobiliaria en la zona sur principalmente en
apartamentos
lo cual podría constituir una oportunidad de inversión
dada la alta oferta.
La zona oeste es la zona con mayor valorizaciónconformada en su
mayoría
por casas, esto constituye una alternativa para posibles
inversionistas
que esten buscando un rápido incremento en su
patrimonio.
Los costos de los inmuebles van desde los 58 MMCOP hasta 1999
MMCOP con un
promedio de 330 MMCOP.
El área cosntruida de los inmuebles varía desde los 30 m2 hasta
1747 m2 siendo
el promedio de 175 m2.
Para establecer estartegias efectivas de venta se debe segmentar
a los
potenciales compradores en función de sus necesidades y
requerimientos.