# Librerias a Utilizar
# install.packages("devtools") # solo una vez
# devtools::install_github("dgonxalex80/paqueteMETODOS")
library(paqueteMETODOS)
library(dplyr)
library(ggplot2)
library(gridExtra)
library(ggfortify)
library(mice)
library(factoextra)
library(tidyverse)
library(cluster)
library(tidyr)
library(ade4)
library(FactoMineR)
library(naniar)
# Se importa la base de datos
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>
Al cargar la base de datos se logra ver que, esta cuenta con 8322 registros u observaciones y 13 atributos los cuales se pueden clasificar de tipo cualitativa y de tipo cuantitativa, dentro de las cuantitativas encontramos 9 variables las cuales son: el ID o identificador de la vivienda, el piso, el estrato, el precio de la vivienda, el area construida, el numero de parqueaderos con que cuenta la vivienda, el numero de baños, el numero de habitaciones, y las coordenadas geograficas de longitud y latitud, del lado de las cualitativas estan: la zona, el tipo de vivienda, el barrio y el piso. Aqui detectamos que la variable piso es numerica, sin embargo el sistema la reconoce como de tipo caracter por lo que sera necesario convertirla a numerica ya que puede generar problemas mas adelante.
faltantes <- colSums(is.na(vivienda)) %>%
as.data.frame()
faltantes
## .
## id 3
## zona 3
## piso 2638
## estrato 3
## preciom 2
## areaconst 3
## parqueaderos 1605
## banios 3
## habitaciones 3
## tipo 3
## barrio 3
## longitud 3
## latitud 3
gg_miss_var(vivienda) # grafico de datos faltantes
vivienda2 <- na.omit(vivienda)
Como se puede observar en la grafica, las variables piso y parqueadero son las que mas datos faltantes tienen, con 2638 y 1605 cada una respectivamente y al momento de crear una nueva base de datos, eliminando las filas que no contienen esa informacion pasa de 8322 a 4808 observaciones, por lo que se esta perdiendo un 43% de la informacion, lo que hace que esta opcion no sea viable, una alternativa es reemplazar por la mediana de las variables donde hay faltantes.
# se convierte la variable piso de caracter a numerica para que al momento de rellenar con la mediana los datos faltantes se pueda realizar la operacion.
vivienda$piso <- as.numeric(vivienda$piso)
# Rellenar los valores faltantes con la mediana de cada columna
vivienda <- vivienda %>%
mutate(across(everything(), ~ ifelse(is.na(.), median(., na.rm = TRUE), .)))
gg_miss_var(vivienda) # grafico de datos faltantes
md.pattern(vivienda)
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## 8322 1 1 1 1 1 1 1 1 1
## 0 0 0 0 0 0 0 0 0
## tipo barrio longitud latitud
## 8322 1 1 1 1 0
## 0 0 0 0 0
Despues de haber reemplazado los datos faltantes por la mediana correspondiente a cada atributo, como se puede verificar en los 2 graficos, todas las variables no cuentas con datos faltantes.
summarytools::descr(vivienda)
## Descriptive Statistics
## vivienda
## N: 8322
##
## areaconst banios estrato habitaciones id latitud longitud
## ----------------- ----------- --------- --------- -------------- --------- --------- ----------
## Mean 174.92 3.11 4.63 3.61 4160.00 3.42 -76.53
## Std.Dev 142.94 1.43 1.03 1.46 2401.20 0.04 0.02
## Min 30.00 0.00 3.00 0.00 1.00 3.33 -76.59
## Q1 80.00 2.00 4.00 3.00 2081.00 3.38 -76.54
## Median 123.00 3.00 5.00 3.00 4160.00 3.42 -76.53
## Q3 229.00 4.00 5.00 4.00 6239.00 3.45 -76.52
## Max 1745.00 10.00 6.00 10.00 8319.00 3.50 -76.46
## MAD 84.51 1.48 1.48 1.48 3082.33 0.05 0.02
## IQR 149.00 2.00 1.00 1.00 4157.50 0.07 0.02
## CV 0.82 0.46 0.22 0.40 0.58 0.01 0.00
## Skewness 2.69 0.93 -0.18 1.64 0.00 0.03 0.65
## SE.Skewness 0.03 0.03 0.03 0.03 0.03 0.03 0.03
## Kurtosis 12.92 1.13 -1.11 3.99 -1.20 -1.15 0.58
## N.Valid 8322.00 8322.00 8322.00 8322.00 8322.00 8322.00 8322.00
## Pct.Valid 100.00 100.00 100.00 100.00 100.00 100.00 100.00
##
## Table: Table continues below
##
##
##
## parqueaderos piso preciom
## ----------------- -------------- --------- ---------
## Mean 1.87 3.53 433.87
## Std.Dev 1.01 2.19 328.61
## Min 1.00 1.00 58.00
## Q1 1.00 2.00 220.00
## Median 2.00 3.00 330.00
## Q3 2.00 4.00 540.00
## Max 10.00 12.00 1999.00
## MAD 1.48 1.48 207.56
## IQR 1.00 2.00 320.00
## CV 0.54 0.62 0.76
## Skewness 2.48 1.81 1.85
## SE.Skewness 0.03 0.03 0.03
## Kurtosis 10.58 3.36 3.67
## N.Valid 8322.00 8322.00 8322.00
## Pct.Valid 100.00 100.00 100.00
table(vivienda$tipo)
##
## Apartamento Casa
## 5103 3219
table(vivienda$zona)
##
## Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
## 124 1920 1198 351 4729
La tecnica que vamos a utilizar a continuacion es util para reducir las dimensiones de nuestra base de datos, con el fin de eliminar variables que se encuentren altamente correlacionadas evitando la redundancia de informacion, haciendo que el modelo que estamos a punto de construir sea mucho mas eficiente, hay que tener presente que, esta tecnica sera aplicada solo a las variables numericas y dentro de las variables numericas no se incluiran, el ID, Latitud y Longitud ya que estas variables no aportan informacion relevante para nuestro modelo, asi como la variable preciom, ya que es nuestro objetivo predecir.
names(vivienda)
## [1] "id" "zona" "piso" "estrato" "preciom"
## [6] "areaconst" "parqueaderos" "banios" "habitaciones" "tipo"
## [11] "barrio" "longitud" "latitud"
vivienda1 = vivienda[,c("piso" , "estrato", "areaconst","parqueaderos", "banios", "habitaciones")]
summarytools::descr(vivienda1)
## Descriptive Statistics
## vivienda1
## N: 8322
##
## areaconst banios estrato habitaciones parqueaderos piso
## ----------------- ----------- --------- --------- -------------- -------------- ---------
## Mean 174.92 3.11 4.63 3.61 1.87 3.53
## Std.Dev 142.94 1.43 1.03 1.46 1.01 2.19
## Min 30.00 0.00 3.00 0.00 1.00 1.00
## Q1 80.00 2.00 4.00 3.00 1.00 2.00
## Median 123.00 3.00 5.00 3.00 2.00 3.00
## Q3 229.00 4.00 5.00 4.00 2.00 4.00
## Max 1745.00 10.00 6.00 10.00 10.00 12.00
## MAD 84.51 1.48 1.48 1.48 1.48 1.48
## IQR 149.00 2.00 1.00 1.00 1.00 2.00
## CV 0.82 0.46 0.22 0.40 0.54 0.62
## Skewness 2.69 0.93 -0.18 1.64 2.48 1.81
## SE.Skewness 0.03 0.03 0.03 0.03 0.03 0.03
## Kurtosis 12.92 1.13 -1.11 3.99 10.58 3.36
## N.Valid 8322.00 8322.00 8322.00 8322.00 8322.00 8322.00
## Pct.Valid 100.00 100.00 100.00 100.00 100.00 100.00
Al haber hecho el resumen estadistico de las variables seleccionadas para hacer el analisis de componentes principales se evidencia que las variables no se encuentran en una misma escala, por lo que las varianzas seran muy dispares y puede afectar de manera considerable este analisis, por tal motivo es necesario normalizar la base de datos.
vivienda1z= scale(vivienda1)
summary(vivienda1z)
## piso estrato areaconst parqueaderos
## Min. :-1.1534 Min. :-1.5876 Min. :-1.0138 Min. :-0.8561
## 1st Qu.:-0.6969 1st Qu.:-0.6158 1st Qu.:-0.6640 1st Qu.:-0.8561
## Median :-0.2404 Median : 0.3559 Median :-0.3632 Median : 0.1314
## Mean : 0.0000 Mean : 0.0000 Mean : 0.0000 Mean : 0.0000
## 3rd Qu.: 0.2161 3rd Qu.: 0.3559 3rd Qu.: 0.3784 3rd Qu.: 0.1314
## Max. : 3.8683 Max. : 1.3277 Max. :10.9841 Max. : 8.0310
## banios habitaciones
## Min. :-2.17883 Min. :-2.4704
## 1st Qu.:-0.77823 1st Qu.:-0.4147
## Median :-0.07792 Median :-0.4147
## Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 0.62238 3rd Qu.: 0.2706
## Max. : 4.82419 Max. : 4.3821
# eleccion grafica del numero de componentes principales
prcomp(vivienda1z)
## Standard deviations (1, .., p=6):
## [1] 1.6416575 1.1182805 0.9218968 0.7780163 0.6042560 0.4838191
##
## Rotation (n x k) = (6 x 6):
## PC1 PC2 PC3 PC4 PC5
## piso 0.1288924 0.58059966 -0.76677312 0.2302186 0.07040589
## estrato -0.2734963 0.65241685 0.30081973 -0.4994753 -0.08014177
## areaconst -0.5195689 -0.06480016 -0.02721451 0.1001549 0.84301901
## parqueaderos -0.4291409 0.18677613 0.27009474 0.7649807 -0.33921470
## banios -0.5366085 0.05614132 -0.17178791 -0.2760830 -0.24108555
## habitaciones -0.4080737 -0.44161074 -0.46729390 -0.1614790 -0.32365166
## PC6
## piso 0.01980293
## estrato 0.39135817
## areaconst 0.06630550
## parqueaderos 0.08797456
## banios -0.73827117
## habitaciones 0.53783488
res.pca <- prcomp(vivienda1z)
fviz_eig(res.pca, addlabels = TRUE)
El anterior grafico muestra la varianza explicada por cada componente y se observa que el PC1 captura una varianza del 44.9% seguido del PC2 que tiene una varianza del 20.8% y del PC3 con 14.2%, estos 3 componentes se puede decir que son los mas significativos debido al aporte que en conjunto hacen casi de un 80% de la varianza explicada que tiene la base de datos.
# Visualizacion en el plano caretasiano
fviz_pca_var(res.pca,
col.var = "contrib", # Color by contributions to the PC
gradient.cols = c("#FF7F00", "#034D94"),
repel = TRUE # Avoid text overlapping
)
tal como lo muestra el siguiente grafico podemos ver que la variable area construida y baños tiene una alta contribución a la Dim1, lo que significa que estas variable es una de las que más influye en la variabilidad capturada por el primer componente, en cambio el estratoparqueaderos están más alineados con Dim2, lo que indica que contribuyen más a la variabilidad explicada por este segundo componente. areaconst, habitaciones y baños, tienen una contribución menor en comparación, ya que sus flechas son más cortas.
fviz_contrib(res.pca, choice = "var", axes = 1:2)
como se logra evidenciar en este grafico las variables que mas tienen peso en los 2 componentes principales son baños, estrato, area construida y habitaciones, en cambio parqueadero y piso tienen menos relevancia.
#Estimar el numero de clusters mediante el metodo wss
fviz_nbclust(vivienda1z, kmeans, method = "wss")
Tal como lo muestra la siguiente grafica al aplicar el metodo de codo el numero de cluster optimo es 4 ya que apartir de alli, la pendiente de las lineas no cambia abruptamente y se vuelve mas plana.
vivienda1z = as.data.frame(vivienda1z)
# Calculamos los 3 clusters.
num_cluster <- 4
# Aplicar algoritmo K-means
m_kmeans <- kmeans(vivienda1z, centers = num_cluster, nstart = 25)
# Agregar el resultado del clustering al dataset original
vivienda1z$cluster <- as.factor(m_kmeans$cluster)
A continuacion se hara el Análisis de Correspondencia el cual sera utilizado para representar posibles asociaciones entre las variables categóricas, con el fin de establecer si existe, patrones o estructuras en los datos.
iniciaremos con las variables zona y el estrato
tabla_cruzada<-table(vivienda$zona, vivienda$estrato)
tabla_cruzada
##
## 3 4 5 6
## Zona Centro 105 14 4 1
## Zona Norte 572 407 769 172
## Zona Oeste 54 84 290 770
## Zona Oriente 340 8 2 1
## Zona Sur 382 1616 1688 1043
tabla_cruzada<-table(vivienda$zona, vivienda$estrato)
tabla_cruzada
##
## 3 4 5 6
## Zona Centro 105 14 4 1
## Zona Norte 572 407 769 172
## Zona Oeste 54 84 290 770
## Zona Oriente 340 8 2 1
## Zona Sur 382 1616 1688 1043
# Prueba X2 para determinar si existe o no una asociación significativa entre las variables
chisq.test(tabla_cruzada)
##
## Pearson's Chi-squared test
##
## data: tabla_cruzada
## X-squared = 3831.8, df = 12, p-value < 2.2e-16
segun el resultado de la prueba chi cuadrada, esta recahza la hipotesis nula de que las variables son independientes, por tanto quiere decir que hay indicios de que hay una dependencia o asociacion entre la zona y el estrato.
# Análisis de correspondencia
resultados_ac <- CA(tabla_cruzada)
resultados_ac
## **Results of the Correspondence Analysis (CA)**
## The row variable has 5 categories; the column variable has 4 categories
## The chi square of independence between the two variables is equal to 3831.81 (p-value = 0 ).
## *The results are available in the following objects:
##
## name description
## 1 "$eig" "eigenvalues"
## 2 "$col" "results for the columns"
## 3 "$col$coord" "coord. for the columns"
## 4 "$col$cos2" "cos2 for the columns"
## 5 "$col$contrib" "contributions of the columns"
## 6 "$row" "results for the rows"
## 7 "$row$coord" "coord. for the rows"
## 8 "$row$cos2" "cos2 for the rows"
## 9 "$row$contrib" "contributions of the rows"
## 10 "$call" "summary called parameters"
## 11 "$call$marge.col" "weights of the columns"
## 12 "$call$marge.row" "weights of the rows"
# Análisis de correspondencia
resultados_ac <- CA(tabla_cruzada)
resultados_ac
## **Results of the Correspondence Analysis (CA)**
## The row variable has 5 categories; the column variable has 4 categories
## The chi square of independence between the two variables is equal to 3831.81 (p-value = 0 ).
## *The results are available in the following objects:
##
## name description
## 1 "$eig" "eigenvalues"
## 2 "$col" "results for the columns"
## 3 "$col$coord" "coord. for the columns"
## 4 "$col$cos2" "cos2 for the columns"
## 5 "$col$contrib" "contributions of the columns"
## 6 "$row" "results for the rows"
## 7 "$row$coord" "coord. for the rows"
## 8 "$row$cos2" "cos2 for the rows"
## 9 "$row$contrib" "contributions of the rows"
## 10 "$call" "summary called parameters"
## 11 "$call$marge.col" "weights of the columns"
## 12 "$call$marge.row" "weights of the rows"
segun el siguiente mapa podemos establecer que el la zona centro y la zona oriente pertenecen al estrato 3, la zona sur y Norte se encuentran los estratos 4 y 5 y por ultimo en la zona oeste es donde se ubica el estrato 6.
valores_prop <-resultados_ac$eig ; valores_prop
## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32216522 69.968477 69.96848
## dim 2 0.12750077 27.690868 97.65934
## dim 3 0.01077739 2.340655 100.00000
valores_prop <-resultados_ac$eig ; valores_prop
## eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32216522 69.968477 69.96848
## dim 2 0.12750077 27.690868 97.65934
## dim 3 0.01077739 2.340655 100.00000
fviz_screeplot(resultados_ac, addlabels = TRUE, ylim = c(0, 80))+ggtitle("")+
ylab("Porcentaje de varianza explicado") + xlab("Ejes")
Los resultados indican que el primer eje resume el 70% de los datos prepresentados en el plano factorial, mientras que los dos primeros ejes resumen un 97.7% la varianza de los datos.
vivienda$estrato <- as.character(vivienda$estrato)
varcategoricas <- vivienda[, c("tipo", "zona", "estrato")]
vivienda$estrato <- as.character(vivienda$estrato)
varcategoricas <- vivienda[, c("tipo", "zona", "estrato")]
resultados_ac2 <- MCA(varcategoricas)
Tal como se puede apreciar en las graficas la mayoria de los apartamentos vendidos se encuentran concentrados en la Zona Sur, en cambio el mayor porcentaje de casas vendidas se encuentra ubicada en la Zona Norte
library(sf)
# Leer el archivo Shapefile
mapacali <- st_read("C:/Users/HP/Downloads/mc_barrios/mc_barrios.shp")
## Reading layer `mc_barrios' from data source
## `C:\Users\HP\Downloads\mc_barrios\mc_barrios.shp' using driver `ESRI Shapefile'
## Simple feature collection with 335 features and 5 fields
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: 1054098 ymin: 860192.1 xmax: 1068492 ymax: 879000.7
## Projected CRS: MAGNA-SIRGAS / Cali urban grid
library(ggplot2)
library(dplyr)
library(leaflet)
library(leaflet.extras)
library(htmlwidgets)
# saco un resumen descriptivo de la base de datos en busqueda de NA
summary(vivienda)
## id zona piso estrato
## Min. : 1 Length:8322 Min. : 1.000 Length:8322
## 1st Qu.:2081 Class :character 1st Qu.: 2.000 Class :character
## Median :4160 Mode :character Median : 3.000 Mode :character
## Mean :4160 Mean : 3.527
## 3rd Qu.:6239 3rd Qu.: 4.000
## Max. :8319 Max. :12.000
## 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.867 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
## 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
## latitud
## Min. :3.333
## 1st Qu.:3.381
## Median :3.416
## Mean :3.418
## 3rd Qu.:3.452
## Max. :3.498
# Eliminar filas con valores faltantes en longitud y latitud
vivienda <- vivienda[complete.cases(vivienda$longitud, vivienda$latitud), ]
# Obtener la mediana de las coordenadas para centrar el mapa
origen <- c(median(vivienda$latitud), median(vivienda$longitud))
# Crear paletas de colores para precio
palette_precio <- colorNumeric(palette = "Blues", domain = vivienda$preciom)
# Crear el mapa coroplético
mapa1 <- leaflet(vivienda) %>%
setView(lng = median(vivienda$longitud), lat = median(vivienda$latitud), zoom = 13) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
radius = 5,
color = ~palette_precio(preciom),
fillColor = ~palette_precio(preciom), # Usar la misma paleta de colores para fillColor
fillOpacity = 0.8,
stroke = FALSE,
popup = ~paste("Precio:", preciom)
)
mapa1
segun el mapa realizado se puede observar por el color azul intenso, que las viviendas que tienen mayor precio estan ubicadas en la zona sur, la cual comprende los estratos 4 y 5, y tambien se logra identificar que en la zona oeste de la ciudad las viviendas se venden a un buen precio puesto que alla esta ubicado el estrato 6.
A la luz de los resultados hechos por el analisis de componentes principales se recomienda, que se preste mucha atencion al estrato en donde se construyen las viviendas, puesto que se descubrio que es una variable que explica mucho la varianza en el modelo y tal como se evidencio en el ultimo mapa realizado en los estratos mas altos las viviendas tienen un mayor valor.
tambien no se recomienda, que la inmobiliaria realice inversiones en la zona centro, y la zona oriente ya que se pudo evidenciar tanto en el mapa como en el analisis de conglomerados, que estas zonas las viviendas no alcanzan un buen precio.
por ultimo para tener en cuenta por parte de la inmobiliaria segun el analisis realizado por conglomerados, es que en la zona sur se pueda seguir enfocando en construir y vender apartamentos porque hay una fuerte demanda por este tipo de viviendas en cambio en la zona norte el fuerte son las casas, para que pueda segmentar estos 2 productos y maximizar sus gananacias