# Instalación de paquetes necesarios (descomentar si es necesario)
# install.packages(c("tidyverse", "FactoMineR", "factoextra", "cluster", "ca"))
library(paqueteMODELOS)
## Loading required package: boot
## Loading required package: broom
## Loading required package: GGally
## Loading required package: ggplot2
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
## Loading required package: gridExtra
## Loading required package: knitr
## Loading required package: summarytools
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ lubridate 1.9.3 ✔ tibble 3.2.1
## ✔ purrr 1.0.2 ✔ tidyr 1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::combine() masks gridExtra::combine()
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ✖ tibble::view() masks summarytools::view()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(FactoMineR)
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(cluster)
library(ca)
data("vivienda")
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")=
## .. cols(
## .. id = col_double(),
## .. zona = col_character(),
## .. piso = col_character(),
## .. estrato = col_double(),
## .. preciom = col_double(),
## .. areaconst = col_double(),
## .. parqueaderos = col_double(),
## .. banios = col_double(),
## .. habitaciones = col_double(),
## .. tipo = col_character(),
## .. barrio = col_character(),
## .. longitud = col_double(),
## .. latitud = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
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
# Porcentaje de datos faltantes por variable
missing_data <- sapply(vivienda, function(x) sum(is.na(x)) / length(x) * 100)
missing_data
## id zona piso estrato preciom areaconst
## 0.03604903 0.03604903 31.69911079 0.03604903 0.02403268 0.03604903
## parqueaderos banios habitaciones tipo barrio longitud
## 19.28622927 0.03604903 0.03604903 0.03604903 0.03604903 0.03604903
## latitud
## 0.03604903
# Eliminación de filas con valores NA en variables críticas
vivienda_clean <- vivienda %>%
filter(!is.na(id), !is.na(zona), !is.na(estrato), !is.na(preciom),
!is.na(areaconst), !is.na(banios), !is.na(habitaciones),
!is.na(tipo), !is.na(barrio), !is.na(longitud), !is.na(latitud))
# Imputación de valores faltantes
# Imputación para 'piso' con la moda
moda_piso <- names(sort(table(vivienda_clean$piso), decreasing = TRUE))[1]
vivienda_clean$piso[is.na(vivienda_clean$piso)] <- moda_piso
# Imputación para 'parqueaderos' con la mediana
mediana_parqueaderos <- median(vivienda_clean$parqueaderos, na.rm = TRUE)
vivienda_clean$parqueaderos[is.na(vivienda_clean$parqueaderos)] <- mediana_parqueaderos
Se decidió aplicar una estrategia combinada para el tratamiento de
valores faltantes. Las variables con menos del 1% de datos faltantes
fueron tratadas mediante la eliminación de dichas observaciones, ya que
el impacto en la muestra es mínimo. Para las variables piso
y parqueaderos, que presentan un porcentaje significativo
de datos faltantes (31.69% y 19.28%, respectivamente), se aplicó
imputación utilizando la moda y la mediana. Esta decisión permite
mantener la robustez del análisis, minimizar la pérdida de información y
garantizar la validez estadística de los resultados.
# Seleccionar variables numéricas para PCA
# Se escogen variables relevantes para identificar patrones y reducir dimensionalidad
vivienda_num <- vivienda_clean %>% select(estrato, preciom, areaconst, parqueaderos, banios, habitaciones)
# Normalización de los datos
# Se aplica escalado para garantizar que todas las variables tengan la misma influencia
vivienda_num <- scale(vivienda_num)
# Aplicación del PCA utilizando FactoMineR
# Esta técnica descompone la variabilidad en componentes ortogonales
pca_result <- PCA(vivienda_num, graph = FALSE)
# Visualización del Scree Plot
# El Scree Plot muestra la proporción de varianza explicada por cada componente principal
fviz_eig(pca_result)
# Biplot de los dos primeros componentes principales
# Este gráfico permite visualizar cómo se distribuyen los datos en función de los componentes
fviz_pca_biplot(pca_result, repel = TRUE)
El Análisis de Componentes Principales (PCA) permitió reducir la dimensionalidad del conjunto de datos manteniendo la mayor cantidad posible de información. A partir del Scree Plot, se identificó cuántos componentes son relevantes para explicar la varianza de los datos.
En el Biplot, se observó la relación entre las variables originales y los componentes principales. Esto ayuda a comprender qué factores tienen mayor peso en la variabilidad de los precios y el tamaño de las viviendas.
Hallazgos Claves: 1. Los primeros componentes principales explican un porcentaje significativo de la varianza. 2. Las variables con mayor influencia en los componentes principales están relacionadas con el tamaño y precio de la vivienda. 3. Este análisis sienta las bases para la segmentación del mercado mediante técnicas de Clustering.
📌 Análisis detallado de las gráficas:
1. Scree Plot - El primer componente principal explica más del 50% de la variabilidad total. - El segundo componente aporta aproximadamente un 20% adicional. - A partir del tercer componente, la contribución a la varianza es mucho menor. - La gráfica tiene un “codo” pronunciado en el segundo componente, lo que sugiere que con dos componentes principales se puede explicar la mayor parte de la variabilidad de los datos.
📝 Interpretación: Se puede concluir que reducir la dimensionalidad del conjunto de datos a dos componentes principales es una buena estrategia, ya que capturan más del 70% de la información.
2. PCA Biplot - Precio (preciom) y estrato están altamente correlacionados con el primer componente. - Área construida (areaconst) y número de habitaciones tienen una relación importante con el segundo componente. - Parqueaderos y baños tienen un menor impacto en la variabilidad de los datos.
📝 Interpretación: - El primer componente está dominado por factores socioeconómicos, lo que sugiere que el precio y el estrato son determinantes en la segmentación del mercado inmobiliario. - El segundo componente está influenciado por características estructurales de la vivienda, como el tamaño y número de habitaciones.
El objetivo del clustering es agrupar las viviendas en segmentos con características similares para identificar patrones dentro del mercado inmobiliario.
# Selección de variables relevantes basadas en el PCA
vivienda_cluster <- vivienda_clean %>% select(estrato, preciom, areaconst, parqueaderos, banios, habitaciones)
vivienda_cluster <- scale(vivienda_cluster)
# Determinación del número óptimo de clusters con el método del codo
fviz_nbclust(vivienda_cluster, kmeans, method = "wss")
## Warning: did not converge in 10 iterations
# Aplicación del algoritmo K-Means con el número óptimo de clusters
set.seed(123) # Fijar semilla para reproducibilidad
kmeans_result <- kmeans(vivienda_cluster, centers = 3, nstart = 100, iter.max = 100)
# Visualización de los clusters
fviz_cluster(kmeans_result, data = vivienda_cluster)
# Aplicación del algoritmo K-Medoids (PAM) como alternativa a K-Means
pam_result <- pam(vivienda_cluster, k = 3)
# Visualización de los clusters generados por PAM
fviz_cluster(pam_result, data = vivienda_cluster)
# Creación de tabla de contingencia entre variables categóricas relevantes
contingencia <- table(vivienda_clean$zona, vivienda_clean$tipo)
# Eliminar filas y columnas con solo ceros
contingencia <- contingencia[rowSums(contingencia) > 0, colSums(contingencia) > 0]
# Verificación de la tabla
print(contingencia)
##
## Apartamento Casa
## Zona Centro 24 100
## Zona Norte 1198 722
## Zona Oeste 1029 169
## Zona Oriente 62 289
## Zona Sur 2787 1939
# Aplicar test de independencia de chi-cuadrado
chisq_test <- chisq.test(contingencia)
# Extraer coordenadas de correspondencia de filas y columnas
coord_filas <- chisq_test$observed / rowSums(chisq_test$observed)
coord_columnas <- t(chisq_test$observed / colSums(chisq_test$observed))
# Verificar estructura antes de graficar
print(dim(coord_filas))
## [1] 5 2
print(dim(coord_columnas))
## [1] 2 5
# Graficar manualmente con mejoras
plot(coord_filas, coord_columnas, col = "blue",
xlab = "Dim 1", ylab = "Dim 2", main = "Análisis de Correspondencia - Chi-Square")
# Agregar etiquetas con mejor ajuste
text(coord_filas, labels = rownames(contingencia), col = "red", cex = 0.7, pos = 4)
text(coord_columnas, labels = colnames(contingencia), col = "blue", cex = 0.7, pos = 2)
El Análisis de Correspondencia basado en la prueba de independencia
de Chi-Cuadrado permite visualizar la relación entre
las variables categóricas zona y
tipo de vivienda. En la gráfica obtenida:
Esta representación gráfica facilita la interpretación del comportamiento del mercado inmobiliario y ayuda a segmentar mejor las zonas con base en el tipo de vivienda predominante.
# Visualización de la distribución de precios en cada zona
ggplot(vivienda_clean, aes(x = zona, y = preciom, fill = zona)) +
geom_boxplot() +
labs(title = "Distribución de Precios por Zona", x = "Zona", y = "Precio (millones)") +
theme_minimal()
# Visualización de la relación entre estrato y precio
ggplot(vivienda_clean, aes(x = as.factor(estrato), y = preciom, fill = as.factor(estrato))) +
geom_boxplot() +
labs(title = "Relación entre Estrato y Precio", x = "Estrato", y = "Precio (millones)") +
theme_minimal()
# Gráfico de dispersión entre área construida y precio
ggplot(vivienda_clean, aes(x = areaconst, y = preciom)) +
geom_point(alpha = 0.5, color = "blue") +
labs(title = "Relación entre Área Construida y Precio", x = "Área Construida (m2)", y = "Precio (millones)") +
theme_minimal()
Se confirma una correlación positiva entre el estrato socioeconómico y el precio de las viviendas. Los estratos más bajos (3 y 4) muestran precios más homogéneos y concentrados en un rango medio-bajo. En estratos más altos (5 y 6), la dispersión de precios es significativamente mayor, reflejando la diversidad de propiedades dentro de estos segmentos. Los valores extremos en el estrato 6 sugieren que existen propiedades de lujo que pueden influir en la percepción de los precios en este sector. Relación entre Área Construida y Precio
Existe una relación clara entre el tamaño de la vivienda y el precio. Se evidencia un patrón de crecimiento exponencial, donde las viviendas más grandes presentan un incremento pronunciado en el precio. Aunque la mayoría de los datos siguen esta tendencia, algunos puntos dispersos en la parte superior derecha del gráfico indican la presencia de viviendas con áreas extremadamente grandes y precios muy elevados. El comportamiento de los datos sugiere que el precio por metro cuadrado varía según la ubicación y el estrato, lo que podría requerir un análisis más detallado en futuros estudios. Implicaciones para el Mercado Inmobiliario Segmentación del Mercado: La diferenciación de precios por zona y estrato permite a los inversionistas y compradores tomar decisiones estratégicas sobre en qué áreas invertir. Impacto del Tamaño en el Precio: Los desarrolladores inmobiliarios pueden usar estos hallazgos para diseñar propiedades en función de la demanda en cada sector. Oportunidades de Negocio: Se identifican áreas con precios más homogéneos que pueden representar oportunidades de inversión segura, mientras que las zonas con alta dispersión de precios pueden ser más riesgosas pero con potencial de alta rentabilidad. Estrategias de Venta: Los agentes inmobiliarios pueden adaptar sus estrategias según la zona y el estrato, destacando características clave como área construida y ubicación.