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.
En el preprocesamiento de datos se hace un tratamiento a los valores
faltantes, principalmente de las variables piso y parqueaderos, cuyos
registros nulos son cerca de un 40% del total de registros. A estas dos
variables se les reemplazó los valores faltantes por la moda.No se les
eliminó sus valores nulos, debido a que se perdería gran parte de sus
datos.
datos <- read.csv(file = 'C:/Jorge Gomez/Maestria/Metodos y simulacion estadistica/vivienda.csv',
header = TRUE,
sep = ";")
Tratamiento de valores faltantes:
Para los valores faltantes se imputa la moda como método para abordar valores faltantes.
datos$areaconst <- gsub(",", ".", datos$areaconst)
imputar_moda <- function(x) {
moda <- names(sort(table(x), decreasing = TRUE))[1]
x_imputada <- ifelse(is.na(x), moda, x)
return(x_imputada)
}
datos <- as.data.frame(lapply(datos, imputar_moda))
Se convierten a numéricos y categoricos las diferentes variables
datos <- as.data.frame(lapply(datos, imputar_moda))
# Convertir a enteros las variables numéricas convertidas de texto
datos$piso <- as.integer(datos$piso)
datos$preciom <- as.integer(datos$preciom)
datos$areaconst <- as.numeric(datos$areaconst)
datos$parqueaderos <- as.integer(datos$parqueaderos)
datos$banios <- as.integer(datos$banios)
datos$habitaciones <- as.integer(datos$habitaciones)
datos$zona <- factor(datos$zona, levels = c("Zona Centro", "Zona Norte", "Zona Oeste", "Zona Oriente", "Zona Sur"))
datos$estrato <- as.factor(datos$estrato)
datos$tipo <- factor(datos$tipo, levels = c("Casa", "Apartamento"))
datos$barrio <- as.factor(datos$barrio)
# Eliminar filas con valores faltantes
datos <- na.omit(datos)
Para este método solo se utilizan variables
numéricas.
library(psych)
library(factoextra)
datosPCA <- datos[, c("piso", "preciom", "areaconst", "parqueaderos", "banios", "habitaciones")]
head(datosPCA)
## piso preciom areaconst parqueaderos banios habitaciones
## 1 2 250 70 1 3 6
## 2 2 320 120 1 2 3
## 3 2 350 220 2 2 4
## 4 2 400 280 3 5 3
## 5 1 260 90 1 2 3
## 6 1 240 87 1 3 3
Se escalan los datos, paso necesario para realizar el análisis de componentes principales. El escalamiento se realiza restando la media y dividiendolo con la desviación estándar.
datosPCA <- scale(datosPCA)
head(datosPCA)
## piso preciom areaconst parqueaderos banios habitaciones
## 1 -0.5231243 -0.5595498 -0.7339949 -0.6343338 -0.07793773 1.6406840
## 2 -0.5231243 -0.3465670 -0.3842568 -0.6343338 -0.77811479 -0.4147626
## 3 -0.5231243 -0.2552886 0.3152194 0.3063120 -0.77811479 0.2703863
## 4 -0.5231243 -0.1031580 0.7349051 1.2469577 1.32241640 -0.4147626
## 5 -0.9554580 -0.5291236 -0.5940997 -0.6343338 -0.77811479 -0.4147626
## 6 -0.9554580 -0.5899759 -0.6150839 -0.6343338 -0.07793773 -0.4147626
Se realizan el test de Barlett y el coeficiente KMO para
verificar la correlación entre las variables.
# test de Bartlett
test_bartlett <- cortest.bartlett(datosPCA)
## R was not square, finding R from data
print(test_bartlett)
## $chisq
## [1] 22180.89
##
## $p.value
## [1] 0
##
## $df
## [1] 15
# coeficiente KMO
kmo_resultado <- KMO(datosPCA)
print(kmo_resultado)
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = datosPCA)
## Overall MSA = 0.75
## MSA for each item =
## piso preciom areaconst parqueaderos banios habitaciones
## 0.64 0.70 0.80 0.86 0.77 0.62
-> Test de Barlett:
El resultado arroja que hay evidencia suficiente para rechazar la
hipótesis nula y que al menos una de las variables esta correlacionada
con otra, por lo que realizar el PCA resulta adecuado para reducir la
dimensionalidad.
-> KMO:
El valor de kmo es 0.75, lo que sugiere que los datos tienen una adecuación razonable para el análisis factorial, incluyendo el PCA.
Se realiza el análisis de componentes
principales
resultado_pca <- prcomp(datosPCA)
A continuacion, se observa la varianza explicada por cada
componente principal
fviz_eig(resultado_pca, addlabels = TRUE, ylim = c(0, 100))
summary(resultado_pca)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 1.7876 1.0425 0.8951 0.6317 0.57010 0.43864
## Proportion of Variance 0.5326 0.1811 0.1335 0.0665 0.05417 0.03207
## Cumulative Proportion 0.5326 0.7137 0.8473 0.9138 0.96793 1.00000
Como se observa, los tres primeros componentes explican la mayor parte de la varianza con un 84%, lo cual puede sugeririr que es suficiente con utilizar esos 3 componentes.
Se hace un análisis de los loadings o cargas de cada componente para verificar el aporte de cada variable en las componentes.
loadings <- resultado_pca$rotation
print(loadings)
## PC1 PC2 PC3 PC4 PC5
## piso 0.1017998 -0.800271394 0.574890748 -0.02933253 0.1311150
## preciom -0.4700094 -0.288185116 -0.251236150 -0.34105599 -0.2366324
## areaconst -0.4831504 0.060931000 -0.003161386 -0.54350252 0.5640787
## parqueaderos -0.4171612 -0.304374739 -0.382312384 0.70538969 0.2792254
## banios -0.4863201 0.003284964 0.230949296 0.04288848 -0.6971766
## habitaciones -0.3532180 0.424438070 0.637864165 0.29666713 0.2112042
## PC6
## piso -0.02552613
## preciom 0.67868021
## areaconst -0.38634625
## parqueaderos -0.10783500
## banios -0.47143371
## habitaciones 0.39446169
PC1: La variable piso tiene una contribución positiva pero baja en esta componente. Por el contrario, las variables precio, area construida, parqueaderos, baños y habitaciones tienen una contribución negativa pero más alta.
PC2: Se destaca la contribución de la variable piso a la segunda componente, la cual tiene una contribución positiva.
PC3: Se destaca la contribución positiva y alta de las variables piso y habitaciones en la tercer componente.
Se observa el círculo de correlaciones
#Entre el componente 1 y 2
fviz_pca_var(resultado_pca, axes = c(1, 2), col.var = "blue")
#Entre el componente 1 y 3
fviz_pca_var(resultado_pca, axes = c(1, 3), col.var = "blue")
Todas las variables se encuentran alejadas del origen, lo que indica que tienen una influencia importante en cada componente.
La variable piso esta más correlacionada con la componente 1, en contraparte, las variables area construida, baños, precio y parqueaderos están mas correlacionadas entre si y con la componente 2 de forma negativa.
Se observa una correlación positiva alta entre el precio del inmueble y los parqueaderos
Se utilizan solo variables numéricas para el algoritmo k-means, el cual solo recibe este tipo de variables.
library(tidyverse)
library(cluster)
datosClusters <- datos[, c("piso", "preciom", "areaconst", "parqueaderos", "banios", "habitaciones")]
head(datosClusters)
## piso preciom areaconst parqueaderos banios habitaciones
## 1 2 250 70 1 3 6
## 2 2 320 120 1 2 3
## 3 2 350 220 2 2 4
## 4 2 400 280 3 5 3
## 5 1 260 90 1 2 3
## 6 1 240 87 1 3 3
Se escalan las variables numéricas, esto debido a que
los variables con registros altos pueden generar que el cálculo de las
distancias en el algoritmo no sea óptimo.
datosClusters <- datosClusters %>%
select_if(is.numeric) %>%
scale()
Se realiza la técnica del codo para determinar el número
adecuado de clusters a realizar
wss <- numeric(10)
for (i in 1:10) {
wss[i] <- sum(kmeans(datosClusters, centers = i)$withinss)
}
wss <- numeric(10)
for (i in 1:10) {
wss[i] <- sum(kmeans(datosClusters, centers = i)$withinss)
}
# Graficar el codo
plot(1:10, wss, type = "b", pch = 19, frame = FALSE,
xlab = "Número de clusters", ylab = "Within-cluster sum of squares")
El resultado sugiere que donde ya no hay una mejora significativa en
el número de agrupamientos es con 2 clusters.
Se entrena el algoritmo k-means
set.seed(123)
kmeans_model <- kmeans(datosClusters, centers = 2)
Se grafica en dos dimensiones los clusters generados y
los registros que entraron en cada grupo
clusplot(datosClusters, kmeans_model$cluster, color=T, shade=T, lines=0)
Se realiza el método de silhouette para determinar que
tan bien agrupa el algoritmo a los datos.
silhouette_vals <- silhouette(kmeans_model$cluster, dist(datosClusters))
mean_silhouette <- mean(silhouette_vals[, 3])
mean_silhouette
## [1] 0.4060821
El valor de 0.406 sugiere que, en promedio, los clusters tienen
una buena cohesión dentro de ellos y una separación razonable con otros
clusters, siendo el 1 el valor maximo a conseguir, por lo que esta en un
valor adecuado.
## 3.Análisis de Correspondencia
Para este método solo se utilizan variables categóricas.
library(ca)
library(FactoMineR)
library(factoextra)
library(naniar)
library(tidyverse)
library(easypackages)
datosCorres <- datos[, c("zona", "estrato", "tipo")]
head(datosCorres)
## zona estrato tipo
## 1 Zona Oriente 3 Casa
## 2 Zona Oriente 3 Casa
## 3 Zona Oriente 3 Casa
## 4 Zona Sur 4 Casa
## 5 Zona Norte 5 Apartamento
## 6 Zona Norte 5 Apartamento
Se ilustran diagramas de columnas para las 3 variables
categóricas, buscando que no haya alguna variable con pocos registros
que distorsione el análisis.
for (i in 1:3){
plot(datosCorres[,i], main = colnames(datosCorres)[i],
ylab = "Cantidad", col ="steelblue", las = 2)
}
Se realiza un test de chi-cuadrado para verificar la
independencia de las variables categóricas.
tabla_contingencia <- table(datosCorres$zona, datosCorres$estrato, datosCorres$tipo)
matriz_contingencia <- as.matrix(tabla_contingencia)
resultado_chi_cuadrado <- chisq.test(matriz_contingencia)
print(resultado_chi_cuadrado)
##
## Chi-squared test for given probabilities
##
## data: matriz_contingencia
## X-squared = 14946, df = 39, p-value < 2.2e-16
Dado que el valor p es extremadamente bajo, rechazamos la
hipótesis nula y se concluye que hay una asociación significativa entre
las categorías, por lo que vale la pena realizar el análisis de
correspondencia para reducir la dimensionalidad.
Se ejecuta el análisis de correspondencia
mca_lb <- MCA(datosCorres, graph = FALSE)
mca_lb
## **Results of the Multiple Correspondence Analysis (MCA)**
## The analysis was performed on 8319 individuals, described by 3 variables
## *The results are available in the following objects:
##
## name description
## 1 "$eig" "eigenvalues"
## 2 "$var" "results for the variables"
## 3 "$var$coord" "coord. of the categories"
## 4 "$var$cos2" "cos2 for the categories"
## 5 "$var$contrib" "contributions of the categories"
## 6 "$var$v.test" "v-test for the categories"
## 7 "$var$eta2" "coord. of variables"
## 8 "$ind" "results for the individuals"
## 9 "$ind$coord" "coord. for the individuals"
## 10 "$ind$cos2" "cos2 for the individuals"
## 11 "$ind$contrib" "contributions of the individuals"
## 12 "$call" "intermediate results"
## 13 "$call$marge.col" "weights of columns"
## 14 "$call$marge.li" "weights of rows"
eig_val <- factoextra::get_eigenvalue(mca_lb)
head(eig_val)
## eigenvalue variance.percent cumulative.variance.percent
## Dim.1 0.5620882 21.07831 21.07831
## Dim.2 0.4531232 16.99212 38.07043
## Dim.3 0.3796450 14.23669 52.30711
## Dim.4 0.3334444 12.50416 64.81128
## Dim.5 0.3233137 12.12426 76.93554
## Dim.6 0.2717762 10.19161 87.12715
fviz_screeplot(mca_lb, addlabels = TRUE)
La gráfica muestra el procentaje de varianza explicada por cada
dimensión. En este caso, la dimension 1 explica el 21% de la varianza y
la dimensión 2 el 17%.
Contribución de cada variable a las dimensiones.
fviz_mca_var(mca_lb,
choice = "mca.cor",
repel = TRUE,
ggtheme = theme_minimal()
)
Según los resultados, se tiene que la variable de tipo es la que
mas contribuye a la primera dimensión. Ademas, la variable zona y
estrato estan correlacionadas dado su cercania en el gráfico.
Gracias al analisis de componentes principales se puede determinar que la variable mas estrechamente correlacionada con el precio de los inmuebles es el parqueadero, por lo que viviendas con esta características pueden llegar a ser atractivas para los clientes.
El análisis de conglomerados sugiere que se pueden armar 2 grupos de viviendas cuyas características son similares e intentar realizar diferentes estrateías de marketing enfocadas a alguno de esos dos segmentos.
El análisis de correspondencias indica que el estrato y la zona estan estrechamente correlacionados, lo cual a priori parece algo intuitivo. Ademas el piso puede explicar gran parte de la varianza, por lo que la cantidad de pisos en el caso de las casas y la ubicación del apartamento en el edificio, puede influir en la variabilidad en la preferencia de los clientes.