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.
instalamos el paquete
devtools::install_github("dgonxalex80/paqueteMOD")
## Skipping install of 'paqueteDAT' from a github remote, the SHA1 (f93b7506) has not changed since last install.
## Use `force = TRUE` to force installation
library(paqueteMODELOS)
Para conocer los datos que contiene la base de datos miramos los 10 primeros datos de la tabla
head(vivienda,10)
Ejecutamos el comando str() para conocer a detalle la información de la base de datos a analizar
str(vivienda)
## Classes 'spec_tbl_df', 'tbl_df', 'tbl' and '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>
Obtenermos el resumen estadístico
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
La dimensión de la base de datos
dim(vivienda)
## [1] 8322 13
De lo anterior tenemos que la base de datos tiene 8322 filas y 13 columnas, de las 13 variables encontradas se tiene que 10 son numericas y 3 de texto.
vivienda$parquea <- ifelse(is.na(vivienda$parquea), 0, vivienda$parquea)
Visualizamos la información de la data modificada
summary(vivienda_nueva)
## id zona piso estrato
## Min. : 1 Length:4808 Length:4808 Min. :3.000
## 1st Qu.:2479 Class :character Class :character 1st Qu.:4.000
## Median :4474 Mode :character Mode :character Median :5.000
## Mean :4427 Mean :4.838
## 3rd Qu.:6413 3rd Qu.:6.000
## Max. :8316 Max. :6.000
## preciom areaconst parqueaderos banios
## Min. : 58.0 Min. : 40.0 Min. : 1.000 Min. : 0.000
## 1st Qu.: 244.5 1st Qu.: 85.0 1st Qu.: 1.000 1st Qu.: 2.000
## Median : 350.0 Median : 123.0 Median : 2.000 Median : 3.000
## Mean : 457.2 Mean : 174.8 Mean : 1.815 Mean : 3.219
## 3rd Qu.: 560.0 3rd Qu.: 225.0 3rd Qu.: 2.000 3rd Qu.: 4.000
## Max. :1999.0 Max. :1500.0 Max. :10.000 Max. :10.000
## habitaciones tipo barrio longitud
## Min. : 0.000 Length:4808 Length:4808 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.564 Mean :-76.53
## 3rd Qu.: 4.000 3rd Qu.:-76.52
## Max. :10.000 Max. :-76.46
## latitud parquea
## Min. :3.333 Min. : 1.000
## 1st Qu.:3.378 1st Qu.: 1.000
## Median :3.408 Median : 2.000
## Mean :3.414 Mean : 1.815
## 3rd Qu.:3.451 3rd Qu.: 2.000
## Max. :3.498 Max. :10.000
install.packages("ggplot2")
## package 'ggplot2' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Diego Ortiz\AppData\Local\Temp\RtmpiQmv5N\downloaded_packages
library(ggplot2)
# Histograma de precios de vivienda
ggplot(vivienda, aes(x = preciom)) +
geom_histogram(binwidth = 100, fill = "blue", color = "black") +
labs(title = "Histograma de Precios de Vivienda",
x = "Precio",
y = "Frecuencia")
Del histograma de precios podemos ver que la mayoria de viviendas cuestan menos de 500 millones
# Diagrama de barras de estratos
ggplot(vivienda, aes(x = factor(estrato))) +
geom_bar(fill = "green") +
labs(title = "Diagrama de Barras de Estratos",
x = "Estrato",
y = "Frecuencia")
La mayor cantidad de personas vive en el estrato 5, seguido del estrato 4, luego el 6 y por ultimo el estrato 3. por esto podemos identificar que la base de datos corresponden a personas de clase media alta.
# Gráfico de dispersión de área construida vs. precio
ggplot(vivienda_nueva, aes(x = areaconst, y = preciom)) +
geom_point(alpha = 0.5, color = "blue") +
labs(title = "Gráfico de Dispersiones de Área Construida vs. Precio",
x = "Área Construida",
y = "Precio")
Vemos que existe graficamente una relación entre el área contruida de la vivienda y su valor, es decir a mayor área construida mayor precio del inmueble.
# Diagrama de barras para la variable 'zona'
ggplot(vivienda_nueva, aes(x = zona, fill = zona)) +
geom_bar() +
labs(title = "Diagrama de Barras para Zona",
x = "Zona",
y = "Frecuencia")
La Zona Sur es la que mas participación tiene en la data, por otro lado la zona centro es la que menos tiene.
# Diagrama de barras para la variable 'tipo'
ggplot(vivienda_nueva, aes(x = tipo, fill = tipo)) +
geom_bar() +
labs(title = "Diagrama de Barras para Tipo de Vivienda",
x = "Tipo",
y = "Frecuencia")
En cuanto a tipo de vivienda se tiene que la cantidad de apartamentos es mayor que las casas
# Gráfico de dispersión de latitud y longitud por zona
ggplot(vivienda_nueva, aes(x = longitud, y = latitud, color = zona)) +
geom_point() +
labs(title = "Gráfico de Dispersiones de Latitud y Longitud por Zona",
x = "Longitud",
y = "Latitud")
Segun los registros, podriamos concluir que existen algunas viviendas que están mal parametrizadas peusto que la longitud y latitud las posicionan en zonas diferentes
El Análisis de Componentes Principales es una técnica estadística que se utiliza para reducir la dimensionalidad de un conjunto de datos mientras conserva la mayor cantidad posible de su variabilidad original. El PCA busca transformar un conjunto de variables correlacionadas en un nuevo conjunto de variables no correlacionadas llamadas componentes principales. Estos componentes principales son combinaciones lineales de las variables originales y están ordenados de manera que el primero captura la mayor varianza posible en los datos, el segundo captura la segunda mayor varianza, y así sucesivamente.
# Seleccionar las variables numéricas para el PCA
variables_numericas <- vivienda_nueva[, c("estrato", "preciom", "areaconst", "banios", "habitaciones")]
# Estandarizar los datos (convertir a Z-scores)
variables_estandarizadas <- scale(variables_numericas)
# Realizar el PCA
pca_resultado <- prcomp(variables_estandarizadas, scale = TRUE)
# Explorar los resultados del PCA
summary(pca_resultado)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5
## Standard deviation 1.7276 1.0783 0.64485 0.50008 0.43211
## Proportion of Variance 0.5969 0.2325 0.08317 0.05002 0.03734
## Cumulative Proportion 0.5969 0.8295 0.91264 0.96266 1.00000
# Explorar los valores propios (varianza explicada)
pca_valores_propios <- pca_resultado$sdev^2
proporcion_varianza_explicada <- pca_valores_propios / sum(pca_valores_propios)
# Gráfico de varianza explicada por componentes
fviz_screeplot(pca_resultado, addlabels = TRUE, ylim = c(0, 100))
La primera componente acumula el 59.7 % de la varianza total es decir
mas de la mtiad de la varianza observada.
# Seleccionar el número de componentes principales
num_componentes <- 2
# Obtener los valores transformados
coordenadas_componentes <- predict(pca_resultado, newdata = variables_estandarizadas)[, 1:num_componentes]
# Matriz de cargas
matriz_cargas <- pca_resultado$rotation[, 1:num_componentes]
# Imprimir la matriz de cargas
print(matriz_cargas)
## PC1 PC2
## estrato 0.3135372 0.69992307
## preciom 0.5021497 0.27812247
## areaconst 0.4987508 -0.17028101
## banios 0.5190448 -0.08887462
## habitaciones 0.3624641 -0.62917507
fviz_pca_var(pca_resultado,
col.var = "contrib",
gradient.cols = c("green", "red"),
repel = TRUE)
Se puede observar que las variables que estan en el cuarto cuadrante con variables que se asocian a la infraestructura del inmueble.
fviz_pca_biplot(pca_resultado,
col.var = "steelblue",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
repel = TRUE,
title = "Biplot de Componentes Principales",
habillage = as.factor(vivienda_nueva$zona),
geom = "point",
pointshape = 21, pointsize = 3,
fill.ind = "lightgray",
alpha.var = 0.6,
legend.title = "Zona",
ggtheme = theme_minimal())
podemos ver graficamente como se posicionan las diferentes zonas de la data.
Después de realizar el análisis de componentes principales (PCA) en nuestros datos, observamos que la primera componente explica el 59.7% de la variabilidad total de los datos, mientras que la segunda componente explica el 23.3%. En conjunto, estas dos componentes alcanzan a explicar un total del 83% de la variabilidad observada. Esto significa que estas dos componentes capturan la mayor parte de la información contenida en las cinco variables originales. El PCA nos ha permitido reducir la dimensionalidad de los datos, manteniendo una proporción significativa de su variabilidad original
El análisis de conglomerados, también conocido como análisis de clústeres, es una técnica de análisis de datos que se utiliza para agrupar objetos o elementos similares en subconjuntos llamados clústeres. El objetivo principal del análisis de conglomerados es encontrar patrones o estructuras en los datos que puedan no ser evidentes a simple vista. Se utiliza para descubrir grupos naturales o segmentos en un conjunto de datos, donde los elementos dentro de cada clúster son más similares entre sí que con los elementos en otros clústeres.
Para el análisis de conglomerados tendremos en cuenta las siguientes variables: estrato, preciom, areacons, banios, habitaciones y zona.
library(stats)
# Seleccionamos las variables
variables_conglomerados <- vivienda_nueva[, c("estrato", "preciom", "areaconst", "banios", "habitaciones")]
# Estandarizamos los datos
variables_estandarizadas <- scale(variables_conglomerados)
Determinamos el numero optimo Cluster
# Crear un vector para lose cuadrados
sumas_cuadrados <- vector("numeric", length = 10)
# Calcular las sumas de cuadrados
for (i in 1:10) {
resultado_conglomerados <- kmeans(variables_estandarizadas, centers = i)
sumas_cuadrados[i] <- resultado_conglomerados$tot.withinss
}
# Crear un gráfico de codo
grafico_codo <- ggplot(data = data.frame(Clusters = 1:10, Sumas_Cuadrados = sumas_cuadrados),
aes(x = Clusters, y = Sumas_Cuadrados)) +
geom_line() +
geom_point() +
labs(title = "Gráfico de Codo para Determinar Número de Clústeres", x = "Número de Clústeres", y = "Sumas de Cuadrados") +
theme_minimal()
print(grafico_codo)
Del gráfico de codo concluimos que el número optimo sería 4 puesto que es ahi donde empieza a aplanarse la recta.
# Realizar el análisis de componentes principales
pca_resultado <- prcomp(variables_estandarizadas)
# Obtener las dos primeras componentes principales
pc1 <- pca_resultado$x[, 1]
pc2 <- pca_resultado$x[, 2]
# Definimos la variable de la cantidad clusters
num_clusters <- 4
# Realizar el análisis de conglomerados con k-means
resultado_conglomerados <- kmeans(variables_estandarizadas, centers = num_clusters)
# Obtener la asignación de clúster
asignacion_cluster <- resultado_conglomerados$cluster
# Crear un dataframe con los datos originales
datos_con_clusters <- cbind(vivienda_nueva, Clusters = asignacion_cluster)
# Crear un gráfico de dispersión
ggplot(datos_con_clusters, aes(x = pc1, y = pc2, color = factor(Clusters))) +
geom_point(size = 3, alpha = 0.6) +
labs(title = "Visualización de Conglomerados en las Dos Primeras Dimensiones", x = "Dimensión 1 (PC1)", y = "Dimensión 2 (PC2)", color = "Clúster") +
theme_minimal()
# Conclusión
El análisis de conglomerados ha demostrado ser una herramienta esencial en la resolución del desafío planteado por la empresa líder en el sector inmobiliario. Al explorar detenidamente la exhaustiva base de datos de propiedades residenciales, hemos logrado revelar agrupamientos y patrones previamente ocultos, lo que nos ha brindado una comprensión más profunda de las dinámicas del mercado de viviendas urbanas. Este análisis nos ha permitido segmentar las propiedades en grupos con características similares, como estrato, precio y habitación. A través de esta segmentación, hemos identificado relaciones subyacentes entre estas variables, lo que a su vez ha mejorado nuestra comprensión de cómo diferentes grupos de propiedades pueden influir en nuestras decisiones estratégicas, en esto casa los 4 cluster seleccionados muestran gran realación en sus diferentes caracteristicas.
# Calculamos la matriz de distancias usando dist()
dist_matrix <- dist(variables_estandarizadas)
# Realizamos análisis jerárquico de conglomerados (AHC) con método Ward
modelo_hclust <- hclust(dist_matrix, method = "ward.D2")
# Graficamos el dendrograma
plot(modelo_hclust, hang = -1, main = "Dendrograma de Análisis Jerárquico")
El análisis de correspondencia es una técnica estadística utilizada para explorar y visualizar relaciones entre variables categóricas en un conjunto de datos. Es especialmente útil cuando se trabaja con tablas de contingencia, que son tablas que muestran la frecuencia con la que se observan combinaciones particulares de categorías en dos o más variables categóricas. El análisis de correspondencia permite revelar patrones subyacentes y relaciones entre las variables categóricas, lo que puede ayudar a entender mejor la estructura de los datos y facilitar la interpretación.
library(FactoMineR)
tabla <- table(vivienda_nueva$zona, vivienda_nueva$estrato)
tabla
##
## 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
library(FactoMineR)
library(ggplot2)
library(factoextra)
library(gridExtra)
##
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
Plano_ca <- CA(tabla)
El estrato 6 se localiza en la Zona Occidental. Los estratos 4 y 5 tienen su principal ubicación en las Zonas Sur y Norte respectivamente. El estrato 3 abarca tanto las Zonas Oriental como Central.
# Obtener los valores propios
valores_propios <- Plano_ca$eig
# Graficar el Scree Plot
fviz_screeplot(Plano_ca, addlabels = TRUE, ylim = c(0, 70)) +
ggtitle("Scree Plot del Análisis de Correspondencia") +
ylab("Porcentaje de Varianza Explicado") +
xlab("Ejes")
Del resultado concluimos que que la primera componente del análisis de correspondencia explica aproximadamente el 65.3% % de la variabilidad total de los datos, la segunda componente sigue con un 30,8%, y la tercera con un 3.9 %, las dos primeras componentes son altamente significativas y abarcan la mayoría de la variabilidad en los datos (96,1%). Esto confirma la estrecha relación entre estrato y zona en el proceso de segmentación del mercado inmobiliariO, ademas el estrato 6 se encuentra predominantemente en la Zona Oeste, mientras que los estratos 4 y 5 están mayormente ubicados en las Zonas Sur y Norte, respectivamente. Por su parte, el estrato 3 se reparte entre las Zonas Oriente y Centro. Los resultados destacan una relación significativa entre la ubicación de las zonas y los diferentes estratos