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.
Se realiza la carga de los datos, se muestra el resumen de la estructura, el tipo de datos en los atributos y finalmente la validación de vacíos.
data("vivienda")
datos <- vivienda
head(datos)
#Validamos cuantos datos hay vacíos
colSums(is.na(datos))
## id zona piso estrato preciom areaconst
## 3 3 2638 3 2 3
## parqueaderos banios habitaciones tipo barrio longitud
## 1605 3 3 3 3 3
## latitud
## 3
#Eliminamos los datos faltantes que en este caso son muy pocos respecto al universo (3 datos faltantes)
datos <- datos[!is.na(datos$id), ]
#Verificamos que lo datos faltantes hayan sido eliminados
nrow(datos)
## [1] 8319
colSums(is.na(datos))
## id zona piso estrato preciom areaconst
## 0 0 2635 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 1602 0 0 0 0 0
## latitud
## 0
str(datos)
## tibble [8,319 × 13] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:8319] 1147 1169 1350 5992 1212 ...
## $ zona : chr [1:8319] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
## $ piso : chr [1:8319] NA NA NA "02" ...
## $ 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 ...
## $ parqueaderos: num [1:8319] 1 1 2 3 1 1 2 2 2 2 ...
## $ 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" ...
## $ barrio : chr [1:8319] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
## $ 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 ...
Los faltantes para cada uno de los atributos es significativo, por lo que eliminar los datos faltantes no es una opción y pasamos a la imputación de datos, para el piso los hacemos con la moda y para parqueaderos utilizamos la media.
# función para calcular la moda
calcular_moda <- function (x){
uniq_x <- unique(na.omit(x))
uniq_x[which.max(tabulate(match(x, uniq_x)))]
}
moda <- calcular_moda(datos$piso)
#Imputar los datos en la varible piso
datos$piso <- ifelse(is.na(datos$piso), moda, datos$piso)
print(colSums(is.na(datos)))
## id zona piso estrato preciom areaconst
## 0 0 0 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 1602 0 0 0 0 0
## latitud
## 0
# Calcular la media
media <- mean(datos$parqueaderos, na.rm = TRUE)
# Redondear al mayor valor
media <- ceiling(media)
#Se imputan los datos de los parqueaderos con la media
datos$parqueaderos <- ifelse(is.na(datos$parqueaderos), media, datos$parqueaderos)
print(colSums(is.na(datos)))
## 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
#Pie para la distribución por zona
f <- table(datos$zona)
porcentajes <- prop.table(f) * 100
etiquetas <- paste0(names(f), ": ", round(porcentajes, 1), "%")
pie(f, labels = etiquetas, main = "Distribución de viviendas por zonas")
#Pie para la distribución por estrato
f1 <- table(datos$estrato)
p <- prop.table(f1) * 100
e <- paste0(names(f1), ": ", round(p, 1), "%")
pie(f1, labels = e, main = "Distribución de viviendas por estrato")
boxplot(preciom ~ zona, data = datos, main = "Diagrama de cajas y bigotes", xlab = "Categoria", ylab = "Valor", col = rainbow(5), border = "black")
De acuerdo con lo mostrado en las gráficas anteriores.
# Crear un mapa con ggplot2
ggplot(datos, aes(x = longitud, y = latitud)) +
geom_point(color = "blue", size = 0.5) +
labs(title = "Distribución de viviendas en Cali", x = "Longitud", y = "Latitud") +
theme_minimal()
El análisis de componentes principales busca principalmente disminuir la dimensionalidad de un conjunto de datos mientras se conserva la mayor cantidad posible de variabilidad en los datos originales. Se siguieron los siguientes pasos.
## tibble [8,319 × 7] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:8319] 1147 1169 1350 5992 1212 ...
## $ 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 ...
## $ parqueaderos: num [1:8319] 1 1 2 3 1 1 2 2 2 2 ...
## $ 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 ...
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
## id estrato preciom areaconst parqueaderos banios habitaciones
## 8319 1 1 1 1 1 1 1 0
## 0 0 0 0 0 0 0 0
## Standard deviations (1, .., p=6):
## [1] 1.8346512 1.0957956 0.7890282 0.6229765 0.4869034 0.4307517
##
## Rotation (n x k) = (6 x 6):
## PC1 PC2 PC3 PC4 PC5 PC6
## estrato 0.3053339 -0.6314557 0.46567443 0.1939375 0.4568797 -0.2117342
## preciom 0.4805544 -0.2515172 -0.01744926 -0.2627551 -0.1791828 0.7774030
## areaconst 0.4567966 0.1902844 -0.11350866 -0.7257528 0.1839350 -0.4262574
## parqueaderos 0.3938199 -0.1258597 -0.77914893 0.4397503 0.1113150 -0.1273612
## banios 0.4705181 0.1517863 0.32361761 0.2846612 -0.6935003 -0.2981118
## habitaciones 0.3011546 0.6803785 0.24115808 0.3036753 0.4816521 0.2530344
Se toman los dos primeros componentes principales ya que con solo dos logramos explicar el 76% de la varianza de las variables.
## Variable PCA_1 PCA_2
## estrato estrato 0.3053339 -0.6314557
## preciom preciom 0.4805544 -0.2515172
## areaconst areaconst 0.4567966 0.1902844
## parqueaderos parqueaderos 0.3938199 -0.1258597
## banios banios 0.4705181 0.1517863
## habitaciones habitaciones 0.3011546 0.6803785
Podemos indentificar en este análisis de variables que la Dimensión 1 explica el 56,1%, mientras que la Dimensión 2 explica el 20%.
Por otro lado las variable preciom está fuertemente relacionada con la dimensión 1, como también lo están las variables área contruida y baños, sin embargo estas están mucho más cerca en su correlación. Si bien parqueadero tiene una corelación mayor con la dimensión 1 que con la dimensión 2 esta es menor que las mencionadas anteriormente. Por otro lado el estrato y las habitaciones están más fuertemente corelacionadas con la dimensión 2.
Se pueden observar algunas agrupaciones que están relacionadas con el precio y el número de baños con el que cuenta la vivienda, se puede determinar que las viviendas con menor precio pueden llegar a tener un número alto de baños peor cuando hacemos otra relación entre el precio de la vivienda y el estrato logramos identificar que estas son de un estrato más bajo.
##
## 01 02 03 04 05 06 07 08 09 10 11 12
## Zona Centro 33 71 8 5 5 0 0 0 0 0 2 0
## Zona Norte 177 1074 189 129 117 33 33 39 32 27 33 37
## Zona Oeste 86 514 134 99 84 80 57 43 41 28 20 12
## Zona Oriente 74 206 54 8 8 0 0 0 0 1 0 0
## Zona Sur 490 2220 712 366 353 132 114 129 73 74 29 34
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
##
## Principal inertias (eigenvalues):
##
## dim value % cum% scree plot
## 1 0.033106 64.0 64.0 ****************
## 2 0.012289 23.8 87.8 ******
## 3 0.005418 10.5 98.3 ***
## 4 0.000896 1.7 100.0
## -------- -----
## Total: 0.051709 100.0
##
##
## Rows:
## name mass qlt inr k=1 cor ctr k=2 cor ctr
## 1 | ZnCn | 15 707 132 | -566 702 144 | 44 4 2 |
## 2 | ZnNr | 231 968 190 | -75 132 39 | 189 836 668 |
## 3 | ZnOs | 144 883 332 | 323 874 453 | 31 8 11 |
## 4 | ZnOr | 42 906 266 | -534 873 363 | -103 33 36 |
## 5 | ZnSr | 568 833 80 | 3 1 0 | -78 832 282 |
##
## Columns:
## name mass qlt inr k=1 cor ctr k=2 cor ctr
## 1 | 01 | 103 813 197 | -269 736 227 | -87 77 64 |
## 2 | 02 | 491 982 94 | -78 614 90 | 60 368 145 |
## 3 | 03 | 132 857 89 | -10 3 0 | -172 854 318 |
## 4 | 04 | 73 775 41 | 148 752 48 | -26 23 4 |
## 5 | 05 | 68 596 38 | 120 492 29 | -55 104 17 |
## 6 | 06 | 29 871 188 | 533 861 253 | -58 10 8 |
## 7 | 07 | 25 945 97 | 439 938 143 | -40 8 3 |
## 8 | 08 | 25 964 46 | 296 928 67 | -59 36 7 |
## 9 | 09 | 18 937 66 | 417 886 92 | 100 51 14 |
## 10 | 10 | 16 997 24 | 284 996 38 | 6 0 0 |
## 11 | 11 | 10 932 61 | 193 120 11 | 502 812 207 |
## 12 | 12 | 10 886 58 | 80 21 2 | 511 865 212 |
## List of 16
## $ sv : num [1:4] 0.182 0.1109 0.0736 0.0299
## $ nd : logi NA
## $ rownames : chr [1:5] "Zona Centro" "Zona Norte" "Zona Oeste" "Zona Oriente" ...
## $ rowmass : num [1:5] 0.0149 0.2308 0.144 0.0422 0.5681
## $ rowdist : num [1:5] 0.6754 0.2063 0.3453 0.5711 0.0855
## $ rowinertia: num [1:5] 0.0068 0.00982 0.01717 0.01376 0.00416
## $ rowcoord : num [1:5, 1:4] -3.111 -0.4115 1.7745 -2.9333 0.0169 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:5] "Zona Centro" "Zona Norte" "Zona Oeste" "Zona Oriente" ...
## .. ..$ : chr [1:4] "Dim1" "Dim2" "Dim3" "Dim4"
## $ rowsup : logi(0)
## $ colnames : chr [1:12] "01" "02" "03" "04" ...
## $ colmass : num [1:12] 0.1034 0.491 0.1319 0.073 0.0682 ...
## $ coldist : num [1:12] 0.3141 0.0993 0.1864 0.1704 0.1706 ...
## $ colinertia: num [1:12] 0.0102 0.00484 0.00458 0.00212 0.00198 ...
## $ colcoord : num [1:12, 1:4] -1.4807 -0.4273 -0.0565 0.8125 0.6575 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:12] "01" "02" "03" "04" ...
## .. ..$ : chr [1:4] "Dim1" "Dim2" "Dim3" "Dim4"
## $ colsup : logi(0)
## $ N : int [1:5, 1:12] 33 177 86 74 490 71 1074 514 206 2220 ...
## $ call : language ca.matrix(obj = obj)
## - attr(*, "class")= chr "ca"
El gráfico nos pemite establecer las relaciones y validardas de acuerdo con la distancia que hay entre cada una de las variables.
Los dos primeros componentes resumen el 87,8% de los datos.
Las zonas sur y oeste son las que tienen viviendas con un mayor número de pisos.
La zona centro y oriente seguramente por la antiguedad no son muy altas, estas se ubican usualmente en el centro de la ciudad
La zonas en donde la inmobiliaria podría enfocar sus esfuerzos de venta para personas que quieran vivir en pisos altos está en la zona su y oeste de la ciudad, esta zona seguramente está llena de nuevas construcciones y desarrollos.
Uno de los estratos que podría ser de importante desarrollo para la inmobiliaria son las viviendas que quedan en el estrato 4 donde al valor de la vivienda es mayor y el número de baños y es menor que en algunas viviendas en otras zonas.
Hay un número importante de viviendas que están por debajo 1,000 millones de pesos pero en la que las construcciones tienen en promedio 3 baños, sin embargo, las que pueden generar mayor valor para la compañía son las que están en los estratos 3 y 4.