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 el 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.
El informe final debe incluir análisis detallados de los resultados obtenidos, las conclusiones clave y las recomendaciones específicas para guiar las decisiones estratégicas de la empresa inmobiliaria. Se espera que este análisis de datos proporcione ventajas competitivas en el mercado, optimizando la inversión y maximizando los beneficios en un entorno altamente competitivo y en constante cambio.
library(paqueteMODELOS)
library(dplyr)
library(ggplot2)
library(FactoMineR)
library(factoextra)
library(cluster)
data("vivienda")
vivienda <- as.data.frame(vivienda)
str(vivienda)
## 'data.frame': 8322 obs. of 13 variables:
## $ id : num 1147 1169 1350 5992 1212 ...
## $ zona : chr "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
## $ piso : chr NA NA NA "02" ...
## $ 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(*, "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>
View(vivienda)
Procedemos con una limpieza de datos para garantizar la calidad del análisis. Imputamos valores faltantes; la variable piso, estrato, parqueaderos, habitaciones y tipo por la moda de los datos, debido a que lo más probable es que ese sea el valor que corresponde.La variables precio y area la imputamos por la media debudi a que van a ser establecidas espus como variables numéricas y por último, para los NA de las variables barrio longitud y latitud simplemente eliminamos el registro completa que tenga NA debido a que eran muy pocos y son valores que no son sensatos de imputar por media o moda.
vivienda1 <- vivienda
vivienda1 <- vivienda1[!is.na(vivienda1$id), ]
vivienda1$piso[is.na(vivienda1$piso)] <- names(which.max(table(vivienda1$piso)))
vivienda1$estrato[is.na(vivienda1$estrato)] <- names(which.max(table(vivienda1$estrato)))
vivienda1$parqueaderos[is.na(vivienda1$parqueaderos)] <- as.numeric(names(which.max(table(vivienda1$parqueaderos))))
vivienda1$banios[is.na(vivienda1$banios)] <- as.numeric(names(which.max(table(vivienda1$banios))))
vivienda1$habitaciones[is.na(vivienda1$habitaciones)] <- as.numeric(names(which.max(table(vivienda1$habitaciones))))
vivienda1$tipo[is.na(vivienda1$tipo)] <- names(which.max(table(vivienda1$tipo)))
vivienda1$preciom[is.na(vivienda1$preciom)] <- mean(vivienda1$preciom, na.rm = TRUE)
vivienda1$areaconst[is.na(vivienda1$areaconst)] <- mean(vivienda1$areaconst, na.rm = TRUE)
vivienda1 <- vivienda1[!is.na(vivienda1$barrio), ]
vivienda1 <- vivienda1[!is.na(vivienda1$latitud), ]
vivienda1 <- vivienda1[!is.na(vivienda1$longitud), ]
A continuación se puede visualizar los cambios realizados
summary(vivienda1)
## id zona piso estrato
## Min. : 1 Length:8319 Length:8319 Length:8319
## 1st Qu.:2080 Class :character Class :character Class :character
## Median :4160 Mode :character Mode :character Mode :character
## Mean :4160
## 3rd Qu.:6240
## Max. :8319
## 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 : 1.000 Median : 3.000
## Mean : 433.9 Mean : 174.9 Mean : 1.674 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
## habitaciones tipo barrio longitud
## Min. : 0.000 Length:8319 Length:8319 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
## latitud
## Min. :3.333
## 1st Qu.:3.381
## Median :3.416
## Mean :3.418
## 3rd Qu.:3.452
## Max. :3.498
str(vivienda1)
## '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 : chr "02" "02" "02" "02" ...
## $ estrato : chr "3" "3" "3" "4" ...
## $ 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(*, "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>
Ahora bien, es importante eliminar cualquier posibilidad de erores tipográficos, y a continuación garantizamos la calidad de los matos por ese medio
#Eliminar errores tipográficos en columna barrio
vivienda1$barrio <- vivienda1$barrio %>%
tolower() %>%
trimws() %>%
gsub("[^a-záéíóúñ ]", "", .) %>%
gsub("aguablanca|agua blanca", "aguablanca", .) %>%
gsub("alf@rez real", "alférez real", .) %>%
gsub("alfonso lopez|alfonso lópez", "alfonso lópez", .)
A continuación garantizamos que las variables id, piso, precio, areaconst, parqueaderos, banios, habitaciones, longitud y latitud sean numericas mientras que las demás serán cateóricas.
# Establecer tipo de variable
vivienda1 <- vivienda1 %>%
mutate (
id = as.numeric(id),
zona = as.factor(zona),
piso = as.numeric(piso),
estrato = as.factor(estrato),
preciom = as.numeric(preciom),
areaconst = as.numeric(areaconst),
parqueaderos = as.numeric(parqueaderos),
banios = as.numeric(banios),
habitaciones = as.numeric(habitaciones),
tipo = as.factor(tipo),
barrio = as.factor(barrio),
longitud = as.numeric(longitud),
latitud = as.numeric(latitud)
)
Vamos a eliminar valores raros o atípicos. En el caso de la variable pisos vamos a eliminar las casas que tengán 5 o más, debido a que en la reañidad esto no tendría mucho sentido, con respecto a la variable baños eliminaremos los que tengan más de 8, y habitaciones más de 10.
#piso
unique(vivienda1$piso)
## [1] 2 1 3 4 5 6 7 8 9 10 11 12
table(vivienda1$piso, vivienda1$tipo)
##
## Apartamento Casa
## 1 430 430
## 2 1893 2192
## 3 573 524
## 4 545 62
## 5 564 3
## 6 243 2
## 7 200 4
## 8 211 0
## 9 146 0
## 10 128 2
## 11 84 0
## 12 83 0
table(vivienda1$piso)
##
## 1 2 3 4 5 6 7 8 9 10 11 12
## 860 4085 1097 607 567 245 204 211 146 130 84 83
vivienda1 <- vivienda1[!(vivienda1$tipo == "Casa" & vivienda1$piso >= 5), ]
table(vivienda1$piso, vivienda1$tipo)
##
## Apartamento Casa
## 1 430 430
## 2 1893 2192
## 3 573 524
## 4 545 62
## 5 564 0
## 6 243 0
## 7 200 0
## 8 211 0
## 9 146 0
## 10 128 0
## 11 84 0
## 12 83 0
str(vivienda1)
## 'data.frame': 8308 obs. of 13 variables:
## $ id : num 1147 1169 1350 5992 1212 ...
## $ zona : Factor w/ 5 levels "Zona Centro",..: 4 4 4 5 2 2 2 2 2 2 ...
## $ piso : num 2 2 2 2 1 1 1 1 2 2 ...
## $ estrato : Factor w/ 4 levels "3","4","5","6": 1 1 1 2 3 3 2 3 3 3 ...
## $ 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 : Factor w/ 2 levels "Apartamento",..: 2 2 2 2 1 1 1 1 2 2 ...
## $ barrio : Factor w/ 403 levels " de julio","acopi",..: 1 1 1 1 2 2 2 2 2 2 ...
## $ 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(*, "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>
# banios
unique(vivienda1$banios)
## [1] 3 2 5 4 7 6 1 0 8 10 9
table(vivienda1$banios)
##
## 0 1 2 3 4 5 6 7 8 9 10
## 45 496 2944 1992 1455 887 313 105 48 15 8
vivienda1 <- vivienda1[vivienda1$banios < 8, ]
table(vivienda1$banios)
##
## 0 1 2 3 4 5 6 7
## 45 496 2944 1992 1455 887 313 105
#habitaciones
unique(vivienda1$habitaciones)
## [1] 6 3 4 5 2 0 1 8 7 9 10
table(vivienda1$habitaciones)
##
## 0 1 2 3 4 5 6 7 8 9 10
## 65 59 924 4095 1726 671 307 164 125 65 36
vivienda1 <- vivienda1[vivienda1$habitaciones < 10, ]
table(vivienda1$habitaciones)
##
## 0 1 2 3 4 5 6 7 8 9
## 65 59 924 4095 1726 671 307 164 125 65
colSums(is.na(vivienda1))
## 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
Para efecto de este análisis haremos uso de las variables cuantitativas, razón por la cual, construiremos una tabla con ellas
variables_numericas <- vivienda1 %>%
select(preciom, areaconst, parqueaderos, piso, banios, habitaciones)
Posteriormente ralizamos la normalización de lo datos
variables_numericas_norm <- scale(variables_numericas)
En la siguiente tabla podemos visualizar la matriz de covarianza donde podemos observar que PC1 está fuertemente influenciado por la variable preciom, areaconst, parqueaderos y banios. Esto indica que PC1 representa un eje de tamaño y valor de la vivienda. PC2 tiene alta carga en piso y negativa en habitaciones, lo que sugiere que este componente representa la altura y número de habitaciones de la vivienda. PC3 destaca en parqueaderos y habitaciones, indicando una posible relación contraria entre estos factores. piso, tiene baja influencia en PC1, lo que indica que no es un factor importante en la diferenciación de las viviendas.
respca <- prcomp(variables_numericas_norm, scale = TRUE)
head(respca$rotation)[, 1:5]
## PC1 PC2 PC3 PC4 PC5
## preciom 0.47454983 0.285935033 0.23606151 0.31807911 0.2042062
## areaconst 0.48363215 -0.065610706 0.01317038 0.54264228 -0.5642409
## parqueaderos 0.42391288 0.293745098 0.35196252 -0.72123564 -0.2760425
## piso -0.09962773 0.790016155 -0.58754451 0.03387721 -0.1361340
## banios 0.48708567 0.005239601 -0.21577635 -0.01455173 0.7112237
## habitaciones 0.33767163 -0.451106673 -0.65456543 -0.28779295 -0.1983959
acp <- PCA(variables_numericas_norm, graph = FALSE)
Visualizamos el screeplot donde observamos que Se debe reducir la dimensionalidad del dataset manteniendo solo PC1 y PC2, ya que explican la mayoría de la variabilidad en los datos.
fviz_eig(respca, addlabels = TRUE, ylim = c(0, 100))
## contribución de las variables
Visualizamos en la contribución de las variables a los componentes principales. Aquí pareciera ser que los compradores están más influenciado por el precio y tamaño de las viviendas y no tanto por su ubicación en pisos altos.
fviz_pca_var(acp, col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"), repel = TRUE)
## gráfico de individuos
Observamos el gráfico de individuos en el espacio que la mayoría de los puntos están concentrados en el centro, lo que indica que la mayoría de las viviendas tienen características similares. El color indica el cos2 (calidad de representación), donde los puntos en rojo están mejor representados en el PCA.
fviz_pca_ind(acp, geom.ind = "point", col.ind = "cos2",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"), repel = TRUE)
## Biplot
En el siguiente Biplot El PCA no segmenta de forma clara los tipos de vivienda, por lo que podríamos explorar otras formas de análisis
fviz_pca_biplot(acp,
repel = TRUE,
habillage = vivienda1$tipo,
col.var = "#2E9FDF",
col.ind = c("#696969", "#E74C3C"))
print(fviz_pca_biplot)
## function (X, axes = c(1, 2), geom = c("point", "text"), geom.ind = geom,
## geom.var = c("arrow", "text"), col.ind = "black", fill.ind = "white",
## col.var = "steelblue", fill.var = "white", gradient.cols = NULL,
## label = "all", invisible = "none", repel = FALSE, habillage = "none",
## palette = NULL, addEllipses = FALSE, title = "PCA - Biplot",
## ...)
## {
## is.individuals.colored.by.variable <- .is_grouping_var(fill.ind) |
## .is_grouping_var(col.ind)
## is.variables.colored.by.variable <- .is_continuous_var(col.var) |
## .is_grouping_var(col.var)
## is.gradient.color <- .is_continuous_var(col.ind) | .is_continuous_var(col.var)
## is.gradient.fill <- .is_continuous_var(fill.ind) | .is_continuous_var(fill.var)
## is.discrete.color <- .is_grouping_var(col.ind) | .is_grouping_var(habillage) |
## .is_grouping_var(col.var)
## is.discrete.fill <- .is_grouping_var(fill.ind) | .is_grouping_var(fill.var) |
## .is_grouping_var(habillage) | (.is_grouping_var(col.ind) &
## addEllipses)
## var <- facto_summarize(X, element = "var", result = c("coord",
## "contrib", "cos2"), axes = axes)
## colnames(var)[2:3] <- c("x", "y")
## pca.ind <- get_pca_ind(X)
## ind <- data.frame(pca.ind$coord[, axes, drop = FALSE], stringsAsFactors = TRUE)
## colnames(ind) <- c("x", "y")
## r <- min((max(ind[, "x"]) - min(ind[, "x"])/(max(var[, "x"]) -
## min(var[, "x"]))), (max(ind[, "y"]) - min(ind[, "y"])/(max(var[,
## "y"]) - min(var[, "y"]))))
## ellipse.border.remove <- FALSE
## if (is.individuals.colored.by.variable & is.variables.colored.by.variable)
## ellipse.border.remove <- TRUE
## p <- fviz_pca_ind(X, axes = axes, geom = geom.ind, repel = repel,
## col.ind = col.ind, fill.ind = fill.ind, label = label,
## invisible = invisible, habillage = habillage, addEllipses = addEllipses,
## ellipse.border.remove = ellipse.border.remove, ...)
## p <- fviz_pca_var(X, axes = axes, geom = geom.var, repel = repel,
## col.var = col.var, fill.var = fill.var, label = label,
## invisible = invisible, scale. = r * 0.7, ggp = p, ...)
## if (!is.null(gradient.cols)) {
## if (is.gradient.color)
## p <- p + ggpubr::gradient_color(gradient.cols)
## if (is.gradient.fill)
## p <- p + ggpubr::gradient_fill(gradient.cols)
## }
## if (!is.null(palette)) {
## if (is.discrete.color)
## p <- p + ggpubr::color_palette(palette)
## if (is.discrete.fill)
## p <- p + ggpubr::fill_palette(palette)
## }
## p + labs(title = title)
## }
## <bytecode: 0x000001d779b2fd10>
## <environment: namespace:factoextra>
Los conglomerados para este caso no presentaron patrones claros que pudieramos identificar, procederemos entones con el análisis de correspondencia.
Seleccionamos las variables categóricas de interés
mca_data <- vivienda1 %>%
select(tipo, zona, estrato) %>%
mutate(across(everything(), as.factor))
Realizar el MCA
mca_result <- MCA(mca_data, graph = FALSE)
Creamos el Scree Plot donde se observa cómo se distribuye la varianza explicada entre los ejes. En este caso, El Dim1 captura el 21.1% de la varianza total. El Dim2 captura el 17%, y juntos estos dos ejes explican el 38.1% de la varianza. Los valores de los ejes restantes tienen menos peso, lo que sugiere que Dim1 y Dim2 son los más relevantes para interpretar los datos
fviz_screeplot(
mca_result,
addlabels = TRUE,
ylim = c(0, 100),
ggtheme = theme_minimal(),
barfill = "steelblue",
barcolor = "black",
title = "Scree Plot: Varianza Explicada por Ejes"
)
Creamos un Biplot
fviz_mca_var(
mca_result,
repel = TRUE
) +
ggtitle("Análisis de Correspondencias Múltiples: Tipo, Zona y Estrato")
A continuación se oberva que Dim1 Captura el 69.6% de la variación en los datos, probablemente asociada a las diferencias entre las zonas y sus combinaciones de estrato. Dim2 Captura una el 28% de la variación, más relacionada con características específicas de ciertos estratos o zonas. Zonas alejadas del centro como la Zona Oeste están más asociadas a estratos altos Zonas como Zona oriente y Zona centro están relacionadas con estratos bajos.
tabla_ampliada <- table(vivienda1$zona, vivienda1$estrato)
res_ac_ampliado <- CA(tabla_ampliada, graph = FALSE)
fviz_ca_biplot(res_ac_ampliado, axes = c(1, 2), repel = TRUE) +
ggtitle("Análisis de Correspondencia Ampliado: Zona vs Estrato") +
theme_minimal()
A continuación haremos un experimento, creando una categoría de precio alto precio medio y precio alto, aumentando o disminuyendo un 30% como criterio. Efectivamente vemos como la zona Oriente está muy cerca de la categoría “Alto” y zona Norte de la categoría “bajo”.
# Crear categorías de precios
vivienda1$precio_cat <- cut(vivienda1$preciom,
breaks = quantile(vivienda1$preciom, probs = seq(0, 1, 0.33), na.rm = TRUE),
labels = c("Bajo", "Medio", "Alto"), include.lowest = TRUE)
tabla <- table(vivienda1$zona, vivienda1$precio_cat)
res_ac <- CA(tabla, graph = FALSE)
fviz_ca_biplot(res_ac, repel = TRUE) +
ggtitle("Análisis de Correspondencia: Zona vs Categorías de Precio") +
theme_minimal()
En la siguiente gráfica podemos ver que se considera un precio “Alto”
para el estrato 6 y “bajo” para estratos 4 y 3. Esto ya lo intuíamos
pero se consideró importante hacerlo para darle solidez a las
afirmaciones que hemos hecho.
tabla <- table(vivienda1$estrato, vivienda1$precio_cat)
res_ac <- CA(tabla, graph = FALSE)
fviz_ca_biplot(res_ac, repel = TRUE) +
ggtitle("Análisis de Correspondencia: Estrato vs Categorías de Precio") +
theme_minimal()
Debido a que el informe arroja que las viviendas menos apetecidas se encuentran en la zona centro y Oriente, sería recomendable generar ofertas atratcivas para no perder la inversión en estos sectores.
Para los aspirantes a las viviendas de la Zona Oeste se podría realizar una inversión para brindarle más lujo a las viviendas, de esa manera no solo comprarían por las razones que analizamos anteriormente, sino que además al aumenta la percepción de “lujo” podrían estar dispuestos a pagar un poco más.