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 (PCA): 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 preferencias del mercado.
Análisis de Conglomerados (Clustering): Agrupar las propiedades residenciales en segmentos homogéneos con características similares para entender las dinámicas y demandas 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) y las variables numéricas (precio, área construida, número de parqueaderos, baños, habitaciones) para identificar patrones de comportamiento del 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.
Empecemos
#devtools::install_github("centromagis/paqueteMODELOS", force = TRUE)
library(paqueteMODELOS)
## Cargando paquete requerido: boot
## Cargando paquete requerido: broom
## Warning: package 'broom' was built under R version 4.4.3
## Cargando paquete requerido: GGally
## Warning: package 'GGally' was built under R version 4.4.3
## Cargando paquete requerido: ggplot2
## Warning: package 'ggplot2' was built under R version 4.4.3
## Cargando paquete requerido: gridExtra
## Cargando paquete requerido: knitr
## Warning: package 'knitr' was built under R version 4.4.3
## Cargando paquete requerido: summarytools
## Warning: package 'summarytools' was built under R version 4.4.3
data("vivenda")
## Warning in data("vivenda"): data set 'vivenda' not found
str(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>
# Mostrar las primeras filas del conjunto de datos
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>
# Mostrar las dimensiones del conjunto de datos (número de filas y columnas)
dim(vivienda)
## [1] 8322 13
El conjunto de datos analizado está conformado por 8.322
registros, cada uno correspondiente a una vivienda individual.
Para cada registro se dispone de 13 variables que
describen sus características, incluyendo atributos tanto
cuantitativos como cualitativos.
Esta estructura ofrece una base sólida para un análisis estadístico y
exploratorio, ya que combina un volumen considerable de observaciones
con un conjunto de variables suficientemente diverso para identificar
patrones, relaciones y
segmentaciones dentro del mercado inmobiliario.
# Mostrar las dimensiones del conjunto de datos (número de filas y columnas)
str(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>
library(ggplot2)
# Gráfico de dispersión entre 'areaconst' y 'preciom' con color arcoíris
ggplot(vivienda, aes(x = areaconst, y = preciom, color = areaconst)) +
geom_point() +
scale_color_gradient(low = "blue", high = "red") +
ggtitle("Relación entre área construida y precio")
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).
El gráfico evidencia una relación positiva entre el
área construida y el precio de las viviendas: a mayor área construida,
mayor es el valor de la propiedad.
La relación observada sigue una tendencia lineal con
pendiente positiva, lo que indica que el incremento en
el área construida se asocia con un incremento proporcional en el
precio.
No obstante, se aprecia una alta dispersión de las
observaciones alrededor de la línea de tendencia, lo que sugiere la
influencia de otros factores no incluidos en la relación bivariada.
colnames(vivienda)
## [1] "id" "zona" "piso" "estrato" "preciom"
## [6] "areaconst" "parqueaderos" "banios" "habitaciones" "tipo"
## [11] "barrio" "longitud" "latitud"
#LIMPIEZA DE DATOS
# Eliminando las columnas 'id', 'piso', 'barrio' y 'parqueaderos' usando subset()
vivienda_ <- subset(vivienda, select = -c(id, piso, barrio, parqueaderos))
# Eliminando filas con valores faltantes
vivienda_ <- vivienda_[complete.cases(vivienda_), ]
# Conteo de valores faltantes
sum(is.na(vivienda_))
## [1] 0
str(vivienda_)
## spc_tbl_ [8,319 × 9] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ zona : chr [1:8319] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
## $ estrato : num [1:8319] 3 3 3 4 5 5 4 5 5 5 ...
## $ preciom : num [1:8319] 250 320 350 400 260 240 220 310 320 780 ...
## $ areaconst : num [1:8319] 70 120 220 280 90 87 52 137 150 380 ...
## $ banios : num [1:8319] 3 2 2 5 2 3 2 3 4 3 ...
## $ habitaciones: num [1:8319] 6 3 4 3 3 3 3 4 6 3 ...
## $ tipo : chr [1:8319] "Casa" "Casa" "Casa" "Casa" ...
## $ longitud : num [1:8319] -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ latitud : num [1:8319] 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>
str(vivienda_)
## spc_tbl_ [8,319 × 9] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ zona : chr [1:8319] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
## $ estrato : num [1:8319] 3 3 3 4 5 5 4 5 5 5 ...
## $ preciom : num [1:8319] 250 320 350 400 260 240 220 310 320 780 ...
## $ areaconst : num [1:8319] 70 120 220 280 90 87 52 137 150 380 ...
## $ banios : num [1:8319] 3 2 2 5 2 3 2 3 4 3 ...
## $ habitaciones: num [1:8319] 6 3 4 3 3 3 3 4 6 3 ...
## $ tipo : chr [1:8319] "Casa" "Casa" "Casa" "Casa" ...
## $ longitud : num [1:8319] -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ latitud : num [1:8319] 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>
Tras el proceso de depuración de datos, que incluyó la eliminación de las columnas id, piso, barrio y parqueadero, así como la exclusión de las filas con valores faltantes, la base de datos resultante está conformada por 8.319 registros y 9 variables.
Las variables disponibles son: zona, estrato,
preciom, areaconst, banios,
habitaciones, tipo, longitud y
latitud, abarcando tanto datos de tipo carácter
(chr) como numérico (num).
Esta estructura reducida optimiza el análisis, ya que conserva
únicamente las variables más relevantes para el estudio del mercado
inmobiliario, manteniendo un balance entre calidad y volumen de la
información.
#Distribución por zonas.
El análisis de la distribución de inmuebles por zona revela una concentración marcada en la zona sur, que representa el 56,8 % del total de registros. Le siguen la zona norte con un 23,1 %, la zona oeste con un 14,4 %, la zona oriente con un 4,2 % y, finalmente, la zona centro con un 1,5 %.
Estos resultados indican que más de la mitad de la oferta inmobiliaria registrada se ubica en la zona sur, lo que sugiere una alta densidad de propiedades en este sector y posibles implicaciones en términos de demanda, precios y desarrollo urbano.
conteo_valoreszona <- table(vivienda$zona )
conteo_valoreszona_df <- as.data.frame(conteo_valoreszona )
#conteo_mayores_a_100 <- sum(conteo_valores_df$Freq > 100)
#conteo_mayores_a_100 <- as.data.frame(conteo_mayores_a_100 )
#conteo_mayores_a_100
# print(conteo_valoreszona_df)
# Obtener los datos de la columna "Proporciones"
datos <- conteo_valoreszona_df$Freq
# Etiquetas para las secciones
etiquetas <- round(conteo_valoreszona_df$Freq / sum(conteo_valoreszona_df$Freq), 3)*100
# Colores para las secciones (opcional)
colores <- c("red", "purple", "orange", "green", "blue")
# Crear el diagrama de sectores con etiquetas en la mitad
pie(datos, labels = etiquetas, col = colores, clockwise = TRUE, radius = 1, init.angle = 90)
leyenda_etiquetas <- conteo_valoreszona_df$Var1
legend("topright", legend = leyenda_etiquetas, fill = colores, bty = "n")
# 1.Análisis de Componentes Principales (PCA)
Para el desarrollo del Análisis de Componentes Principales (ACP) se considerarán las siguientes variables: zona, estrato, precio, área construida, baños, número de habitaciones y tipo de inmueble.
La selección de estas variables responde a su relevancia en la
caracterización de las propiedades, abarcando tanto atributos
categóricos (zona, estrato, tipo
de inmueble) como cuantitativos (precio,
área construida, baños, número de
habitaciones).
Esta combinación permite capturar de manera integral los factores clave
que influyen en la variación del mercado inmobiliario y facilita la
identificación de patrones y relaciones subyacentes.
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Adjuntando el paquete: 'dplyr'
## The following object is masked from 'package:gridExtra':
##
## combine
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
vivienda <- vivienda %>% mutate(zona = replace(zona,
zona == "Zona Centro", 1))
vivienda <- vivienda %>% mutate(zona = replace(zona,
zona == "Zona Norte", 2))
vivienda <- vivienda %>% mutate(zona = replace(zona,
zona == "Zona Oeste", 3))
vivienda <- vivienda %>% mutate(zona = replace(zona,
zona == "Zona Oriente",
4))
vivienda <- vivienda %>% mutate(zona = replace(zona,
zona == "Zona Sur", 5))
vivienda$zona <- as.numeric(vivienda$zona)
# Tipo
vivienda <- vivienda %>% mutate(tipo = replace(tipo,
tipo == "Casa", 1))
vivienda <- vivienda %>% mutate(tipo = replace(tipo,
tipo == "Apartamento", 2))
vivienda$tipo <- as.numeric(vivienda$tipo)
head(vivienda,3) # Tabla
## # A tibble: 3 × 13
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1147 4 <NA> 3 250 70 1 3 6
## 2 1169 4 <NA> 3 320 120 1 2 3
## 3 1350 4 <NA> 3 350 220 2 2 4
## # ℹ 4 more variables: tipo <dbl>, barrio <chr>, longitud <dbl>, latitud <dbl>
La gráfica indica que no se presentan datos faltantes
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.4.3
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
vivienda_2 <- scale(vivienda_[, 2:5])
# Realizar ACP y visualizar el gráfico
res.pca <- prcomp(vivienda_2)
fviz_eig(res.pca, addlabels = TRUE)
El primer componente principal (CP1) explica el 67 % de la variabilidad total del conjunto de datos, lo que indica que gran parte de la información contenida en las variables originales puede representarse a través de esta dimensión.
En conjunto, los dos primeros componentes principales (CP1 y CP2) concentran el 86 % de la variabilidad total, evidenciando que la mayor parte de la estructura de los datos puede capturarse en un espacio bidimensional.
El gráfico del ACP sugiere que es posible resumir la información esencial de la base de datos mediante una sola dimensión (CP1), lo que facilita la interpretación y reduce la complejidad del análisis sin una pérdida significativa de información.
# Definir los colores personalizados
colores_personalizados <- c("red", "blue")
# Personalizar el gráfico
fviz_pca_var(res.pca,
col.var = "contrib",
gradient.cols = colores_personalizados,
repel = TRUE,
# Opciones adicionales (opcional)
# axis.lty = 1,
# legend.title = "Contribución a la variabilidad",
# legend.position = "top",
# point.size = 4
)
La visualización de las variables en el plano definido por los componentes principales permite interpretar el sentido y la caracterización de cada componente, a partir de la orientación y magnitud de los vectores propios de la matriz de covarianzas (Σ).
En este análisis, el primer componente principal (CP1) se encuentra fuertemente asociado con las variables estrato y precio, lo que sugiere que esta dimensión captura principalmente el efecto socioeconómico y el valor monetario de las propiedades.
Por su parte, el segundo componente principal (CP2) presenta una mayor relación con la variable área construida, indicando que esta dimensión refleja en gran medida el tamaño físico de los inmuebles.
casos1 <- rbind(res.pca$x[98,1:2],res.pca$x[778,1:2]) # CP1
rownames(casos1) = c("6000","8300")
casos1 <- as.data.frame(casos1)
casos2 <- rbind(res.pca$x[6,1:2], res.pca$x[462,1:2]) # CP2
rownames(casos2) = c("002","3000")
casos2 <- as.data.frame(casos2)
fviz_pca_ind(res.pca, col.ind = "#DEDEDE", gradient.cols = c("#00FFFF", "#7FFF00", "#FF1493")) +
geom_point(data = casos1, aes(x = PC1, y = PC2), color = "#FFFF00", size = 3) +
geom_point(data = casos2, aes(x = PC1, y = PC2), color = "#DA70D6", size = 3)
En la representación gráfica del ACP se identifica una región en la que las observaciones presentan una mayor asociación con las variables de mayor peso en el primer componente principal (precio, estrato y área construida).
En contraste, la vivienda 002 se localiza en una zona alejada de dicho sector, lo que indica una menor asociación con estas variables, sugiriendo que sus características difieren del patrón general capturado por CP1.
# Cargar los datos
library(mice)
## Warning: package 'mice' was built under R version 4.4.3
##
## Adjuntando el paquete: 'mice'
## The following object is masked from 'package:stats':
##
## filter
## The following objects are masked from 'package:base':
##
## cbind, rbind
if (!exists("vivienda_"))
variables_clustering <- select(vivienda_, estrato, preciom, areaconst, banios, habitaciones)
# Seleccionar las variables relevantes para el clustering
variables_clustering <- select(vivienda_, estrato, preciom, areaconst, banios, habitaciones)
# Escalar las variables si es necesario
variables_clustering_scaled <- scale(variables_clustering)
# Determinar el número óptimo de clusters usando el método del codo
wcss <- numeric(10)
for (i in 1:10) {
kmeans_fit <- kmeans(variables_clustering_scaled, centers = i, nstart = 10)
wcss[i] <- kmeans_fit$tot.withinss
}
# Graficar el método del codo
plot(1:10, wcss, type = "b", pch = 19, frame = FALSE,
xlab = "Número de clusters (k)", ylab = "WCSS")
# Ajustar el modelo k-means con el número óptimo de clusters
k_optimo <- 3
set.seed(123)
modelo_kmeans <- kmeans(variables_clustering_scaled, centers = k_optimo, nstart = 10)
# Asignar las etiquetas de cluster a cada observación en los datos
cluster_labels <- as.factor(modelo_kmeans$cluster)
# Agregar las etiquetas de cluster al conjunto de datos original
vivienda_limpia_con_clusters <- mutate(vivienda_, cluster = cluster_labels)
# Visualizar los clusters en función de algunas variables relevantes
ggplot(vivienda_limpia_con_clusters, aes(x = estrato, y = preciom, color = cluster)) +
geom_point() +
labs(title = "Clusters de Propiedades Residenciales",
x = "Estrato Socioeconómico",
y = "Precio de la Propiedad") +
theme_minimal() +
scale_color_discrete(name = "Cluster")
El gráfico “Clusters de Propiedades Residenciales”
muestra una correlación positiva entre el estrato
socioeconómico, el precio de la propiedad y la distribución de los
clusters.
Se observa un incremento en el número de clusters conforme aumenta el
estrato socioeconómico, con una mayor concentración en los
estratos 5 y 6 en comparación con los estratos
1 y 2. De forma paralela, el precio de la
propiedad tiende a incrementarse junto con el estrato
socioeconómico.
En cuanto a la composición de los grupos:
- Cluster 1: Presenta una distribución similar en los
estratos 3, 4 y 5, con menor presencia en el estrato
6.
- Cluster 2: Predomina en los estratos 5 y
6.
- Cluster 3: Se concentra principalmente en los
estratos 3 y 4, con una presencia menor en el estrato
6.
Estos resultados sugieren que los clusters capturan patrones diferenciados en la relación entre características socioeconómicas y valor de las propiedades.
# Calcular la matriz de correlación
correlation_matrix <- cor(variables_clustering_scaled)
# Convertir la matriz de correlación en un marco de datos
correlation_df <- as.data.frame(as.table(correlation_matrix))
colnames(correlation_df) <- c("Var1", "Var2", "Correlation")
# Graficar la matriz de correlación como un mapa de calor
ggplot(data = correlation_df, aes(x = Var1, y = Var2, fill = Correlation)) +
geom_tile() +
scale_fill_gradient2(low = "green", high = "blue", mid = "white", midpoint = 0) +
theme_minimal() +
labs(title = "Matriz de Correlación")
El análisis de correlación revela los siguientes hallazgos principales:
En síntesis, el número de habitaciones, el número de
baños y el área construida se encuentran correlacionados
positivamente con el precio de la propiedad.
Asimismo, el estrato socioeconómico presenta una correlación
fuerte con el precio, lo que sugiere que el nivel
socioeconómico del sector es un factor clave en la valoración de los
inmuebles.
# Gráfico de Densidad (Distribución de Precios por Cluster)
ggplot(vivienda_limpia_con_clusters, aes(x = preciom, fill = cluster)) +
geom_density(alpha = 0.5) +
labs(title = "Distribución de Precios por Cluster", x = "Precio", y = "Densidad") +
theme_minimal()
El análisis de la distribución de precios por cluster muestra los siguientes patrones:
Estos resultados sugieren que la segmentación por clusters diferencia no solo las características estructurales y socioeconómicas de las propiedades, sino también su posicionamiento en términos de precio.
# Mapa de Clusters (Si tienes datos geoespaciales)
ggplot(vivienda_limpia_con_clusters, aes(x = longitud, y = latitud, color = cluster)) +
geom_point() +
labs(title = "Mapa de Clusters", x = "Longitud", y = "Latitud", color = "Cluster") +
theme_minimal()
De acuerdo con la representación geográfica, el Cluster 1 concentra la mayor cantidad de observaciones y presenta una dispersión amplia a lo largo de todo el territorio analizado.
El Cluster 2, en contraste, cuenta con un menor número de registros y una mayor concentración espacial, lo que indica una dispersión significativamente más reducida.
Por último, el Cluster 3 es el grupo con menor volumen de datos; sin embargo, su patrón espacial muestra una dispersión similar a la del Cluster 1, aunque con menor densidad de puntos.
Análisis de Correspondencia : Examinar la relación entre las variables categóricas (tipo de vivienda, zona y barrio) y las variables numéricas (precio, área construida, número de parqueaderos, baños, habitaciones) para identificar patrones de comportamiento del mercado inmobiliario
# Se establece la semilla para la aleatoriedad
set.seed(1234)
# Se toma una muestra aleatoria de 4000 viviendas
vivienda <- sample_n(vivienda, 2000)
# Se convierte la variable "estrato" a factor
vivienda$estrato <- as.factor(vivienda$estrato)
# Se analiza el patrón de datos faltantes
md.pattern(vivienda, rotate.names = TRUE)
## preciom id zona estrato areaconst banios habitaciones tipo barrio longitud
## 1155 1 1 1 1 1 1 1 1 1 1
## 474 1 1 1 1 1 1 1 1 1 1
## 214 1 1 1 1 1 1 1 1 1 1
## 156 1 1 1 1 1 1 1 1 1 1
## 1 1 0 0 0 0 0 0 0 0 0
## 0 1 1 1 1 1 1 1 1 1
## latitud parqueaderos piso
## 1155 1 1 1 0
## 474 1 1 0 1
## 214 1 0 1 1
## 156 1 0 0 2
## 1 0 0 0 12
## 1 371 631 1012
library(FactoMineR)
## Warning: package 'FactoMineR' was built under R version 4.4.3
tabla <- table(vivienda$zona, vivienda$estrato)
# Se asignan nombres a las columnas de la tabla
colnames(tabla) <- c("Estrato3", "Estrato4", "Estrato5", "Estrato6")
# Se realiza la prueba de chi-cuadrado
chisq.test(tabla)
##
## Pearson's Chi-squared test
##
## data: tabla
## X-squared = 1012, df = 12, p-value < 2.2e-16
resultados_ac <- CA(tabla)
El gráfico permite identificar y validar relaciones espaciales y socioeconómicas entre las observaciones:
En términos de análisis dimensional:
- Dimensión 1 (Dim 1): Explica el 68,31
% de la variabilidad total de los datos.
- Dimensión 2 (Dim 2): Explica el 26,89
% de la variabilidad total de los datos.
El grado de representatividad del análisis se evalúa mediante la varianza acumulada, calculada a partir de los valores propios (eigenvalues) de la matriz de discrepancias, lo que permite cuantificar la proporción de información retenida por las dos primeras dimensiones.
# Se crea un gráfico de scree plot con colores personalizados
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80), col = "blue") +
ggtitle("") +
ylab("Porcentaje de varianza explicado") +
xlab("Ejes")
Las dos primeras dimensiones juntas explican el 95.19% de la varianza total en los datos.Esto significa que las dos primeras dimensiones son suficientes para capturar la mayor parte de la información en los datos.
El Análisis de Componentes Principales (ACP)
permitió identificar las variables que explican la mayor proporción de
la variabilidad en el precio de la vivienda.
El primer componente principal (CP1) explica el
67 % de la variabilidad total, mientras que la
combinación de CP1 y CP2 alcanza el 86
%.
La interpretación de las cargas factoriales muestra que el CP1 está
principalmente asociado con estrato, precio y área
construida.
En el Análisis de Conglomerados (k-means), la
segmentación se realizó a partir de variables clave relacionadas con las
características socioeconómicas y estructurales de las
propiedades.
Se identificó una correlación positiva entre el
estrato socioeconómico, el precio de la propiedad y la
distribución de los clusters.
El Cluster 1 se caracteriza por una predominancia de
apartamentos, el Cluster 3 por una mayor presencia de
casas, y el Cluster 2 presenta una distribución
equilibrada entre ambos tipos de propiedad.
El Análisis de Correlación evidenció una
fuerte relación positiva entre el número de
habitaciones y el número de baños, así como entre el
estrato socioeconómico y el precio de la
propiedad.
Además, se observaron correlaciones moderadas entre el
número de habitaciones y el área construida, así como
entre el número de baños y el precio de la
propiedad.
Finalmente, el Análisis de Correspondencia Múltiple
(ACM) permitió explorar las asociaciones entre variables
categóricas y numéricas.
Se identificó una asociación significativa entre zona y
estrato, destacando que el estrato 6 se concentra en
la Zona Oeste, mientras que los estratos 4 y 5
se localizan principalmente en las Zonas Sur y
Norte.
Las dos primeras dimensiones del ACM explican el 95,19
% de la información total, lo que confirma su efectividad en la
reducción de la dimensionalidad y en la representación
de las relaciones clave entre variables.