Actividad 1. Modelos estadisticos para toma de decisiones - Juan Esteban Pupo Morales

library(paqueteMODELOS)
## Cargando paquete requerido: boot
## Cargando paquete requerido: broom
## Warning: package 'broom' was built under R version 4.5.3
## Cargando paquete requerido: GGally
## Warning: package 'GGally' was built under R version 4.5.3
## Cargando paquete requerido: ggplot2
## Warning: package 'ggplot2' was built under R version 4.5.3
## Cargando paquete requerido: gridExtra
## Warning: package 'gridExtra' was built under R version 4.5.3
## Cargando paquete requerido: knitr
## Cargando paquete requerido: summarytools
## Warning: package 'summarytools' was built under R version 4.5.3
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.3
## Warning: package 'dplyr' was built under R version 4.5.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.1.6
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ lubridate 1.9.5     ✔ tibble    3.3.1
## ✔ purrr     1.2.1     ✔ tidyr     1.3.2
## ── 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)
## Warning: package 'FactoMineR' was built under R version 4.5.3
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.5.3
## Welcome to factoextra!
## Want to learn more? See two factoextra-related books at https://www.datanovia.com/library/principal-component-methods
library(cluster)
## Warning: package 'cluster' was built under R version 4.5.3
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
head(vivienda)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1147 Zona O… <NA>        3     250        70            1      3            6
## 2  1169 Zona O… <NA>        3     320       120            1      2            3
## 3  1350 Zona O… <NA>        3     350       220            2      2            4
## 4  5992 Zona S… 02          4     400       280            3      5            3
## 5  1212 Zona N… 01          5     260        90            1      2            3
## 6  1724 Zona N… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

La base contiene 8.322 viviendas y 13 variables, incluyendo variables numéricas (precio, área construida, baños, habitaciones, etc.) y categóricas (zona, tipo, barrio, piso).

#Tabla con el calculo de medidas de tendencia central junto con el coneto de datos faltantes por variables

library(dplyr)
library(knitr) 
library(kableExtra)
## 
## Adjuntando el paquete: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows
library(tibble)
library(tidyr)# para kable


# Supongamos que trabajas con el dataset vivenda
vars_cuantitativas_reales <- vivienda %>%
  select(preciom,areaconst, banios, parqueaderos, habitaciones,estrato)

df_long <- vars_cuantitativas_reales %>%
  pivot_longer(cols = everything(),
               names_to = "Variable",
               values_to = "Valor")

tabla_resumen <- df_long %>%
  group_by(Variable) %>%
  summarise(
    Media = mean(Valor, na.rm = TRUE),
    Mediana = median(Valor, na.rm = TRUE),
    SD = sd(Valor, na.rm = TRUE),
    Min = min(Valor, na.rm = TRUE),
    Q1 = quantile(Valor, 0.25, na.rm = TRUE),
    Q3 = quantile(Valor, 0.75, na.rm = TRUE),
    Max = max(Valor, na.rm = TRUE),
    NA_count = sum(is.na(Valor)) 
  )

# Mostrar con kable
kable(tabla_resumen, caption = "Resumen de variables numéricas con NA") %>%
kable_styling(bootstrap_options = c("striped"))
Resumen de variables numéricas con NA
Variable Media Mediana SD Min Q1 Q3 Max NA_count
areaconst 174.934938 123 142.964126 30 80 229 1745 3
banios 3.111311 3 1.428210 0 2 4 10 3
estrato 4.633610 5 1.029222 3 4 5 6 3
habitaciones 3.605361 3 1.459537 0 3 4 10 3
parqueaderos 1.835194 2 1.124909 1 1 2 10 1605
preciom 433.891947 330 328.647244 58 220 540 1999 2

Como se ve en la tabla, la variable “Parqueaderos” maneja una cantidad considerbale de datos faltantes NA, 1605. Estos deben representar en realidad valores iguales a 0 que no fueron diligenciados.

Para evitar perder información relevante se reemplazarán todos los NA de la variable Parqueadores por valores de 0.

Para las demás variables numericas, al tener en promedio menos de 3 datos faltantes, se decidirá por eliminar esas filas.

df2 <- vivienda %>%
  mutate(parqueaderos = ifelse(is.na(parqueaderos), 0, parqueaderos))

Para poder trabajar con las variables numericas, se deberá realizar un proceso de estandarización:

datos_num <- df2 %>%
  select(preciom, areaconst, parqueaderos,
         banios, habitaciones,estrato) %>%
  na.omit()

datos_std <- scale(datos_num)
summary(datos_std)
##     preciom          areaconst        parqueaderos         banios        
##  Min.   :-1.1437   Min.   :-1.0138   Min.   :-1.1920   Min.   :-2.17847  
##  1st Qu.:-0.6508   1st Qu.:-0.6640   1st Qu.:-0.3876   1st Qu.:-0.77811  
##  Median :-0.3161   Median :-0.3633   Median :-0.3876   Median :-0.07794  
##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.00000  
##  3rd Qu.: 0.3228   3rd Qu.: 0.3782   3rd Qu.: 0.4169   3rd Qu.: 0.62224  
##  Max.   : 4.7620   Max.   :10.9822   Max.   : 6.8521   Max.   : 4.82330  
##   habitaciones        estrato       
##  Min.   :-2.4702   Min.   :-1.5872  
##  1st Qu.:-0.4148   1st Qu.:-0.6156  
##  Median :-0.4148   Median : 0.3560  
##  Mean   : 0.0000   Mean   : 0.0000  
##  3rd Qu.: 0.2704   3rd Qu.: 0.3560  
##  Max.   : 4.3813   Max.   : 1.3276

Etapa 3. Análisis de Componentes Principales (PCA)

pca <- prcomp(datos_std, center = TRUE, scale. = TRUE)

summary(pca)
## Importance of components:
##                           PC1    PC2    PC3     PC4     PC5     PC6
## Standard deviation     1.8481 1.1222 0.6780 0.65924 0.49098 0.43579
## Proportion of Variance 0.5692 0.2099 0.0766 0.07243 0.04018 0.03165
## Cumulative Proportion  0.5692 0.7791 0.8557 0.92817 0.96835 1.00000

Como podemos ver, los componentes 1 y 2 explican la mayor parte de la variación, con un 76%. Eso significa que con esas dos nuevas variables se captura una gran parte de la información de las 6 variables originales.

library(FactoMineR)
library(factoextra)
library(cluster)
fviz_eig(pca, addlabels = TRUE)

fviz_pca_biplot(pca,
                repel = TRUE,
                
                col.var = "red",
                col.ind = "gray")

pca$rotation
##                    PC1        PC2        PC3         PC4         PC5        PC6
## preciom      0.4781754  0.1883533 -0.0359721 -0.36062553  0.21967777 -0.7458339
## areaconst    0.4417250 -0.2388377 -0.2878930 -0.61783592 -0.27859384  0.4534506
## parqueaderos 0.4096354  0.2607395 -0.6565763  0.57091588 -0.04760414  0.0700729
## banios       0.4668745 -0.1921461  0.3633148  0.18500105  0.67876421  0.3437503
## habitaciones 0.2847775 -0.6813261  0.2111757  0.34936005 -0.44521273 -0.2997240
## estrato      0.3306904  0.5816950  0.5551021  0.07749341 -0.46143880  0.1587620

Etapa 4. Análisis de Conglomerados (Clustering)

fviz_nbclust(datos_std, kmeans, method = "wss") 

set.seed(123)

km <- kmeans(datos_std, centers = 3)

km$size
## [1]  999 2084 5236
datos_cluster <- datos_num
datos_cluster$grupo <- factor(km$cluster)
fviz_cluster(km,
             data = datos_std,
             ellipse.type = "convex",
             ggtheme = theme_minimal())

aggregate(datos_num,
          by = list(Grupo = km$cluster),
          mean)
##   Grupo  preciom areaconst parqueaderos   banios habitaciones  estrato
## 1     1 445.3784  297.4792     1.214214 4.408408     6.365365 3.953954
## 2     2 856.1209  296.3820     2.796545 4.508637     3.909789 5.716411
## 3     3 263.6673  103.2166     1.009549 2.307678     2.957601 4.332315

El grupo 1 representa viviendas grandes, con muchas habitaciones y baños, pero de precio medio. Podrían ser casas amplias en estratos medios.

El grupo 2 representa las viviendas más costosas, con más parqueaderos y en estratos altos. Son propiedades de lujo o de mayor nivel socioeconómico.

El grupo 3 corresponde a viviendas más pequeñas y económicas, con menos habitaciones y área reducida.

Etapa 5. Análisis de Correspondencias

library(FactoMineR)
library(factoextra)
library(dplyr)



# Seleccionamos variables categóricas

barrios_top <- vivienda %>%
  count(barrio, sort = TRUE) %>%
  slice(1:15) %>%
  pull(barrio)

vivienda2 <- vivienda %>%
  filter(barrio %in% barrios_top)




tabla <- vivienda2 %>% 
  select(tipo, zona, barrio) %>%
  mutate(across(everything(), as.factor))

# Análisis de correspondencias múltiples
ca <- MCA(tabla, graph = FALSE)



fviz_mca_biplot(ca, repel = TRUE)

Para que el MCA fuese mucho más legible, se decidió por filtrar los barrios a un maximo 15 categorías. Se evidencia que la distribución del tipo de vivienda en la ciudad no es homogénea:

Norte y Oeste: predominio de apartamentos, asociados a barrios como La Flora, Prados del Norte, Santa Teresita y Normandía.

Sur: mayor diversidad, con barrios de casas tradicionales (Ciudad Jardín, Pance) y otros de alta densidad de apartamentos (Valle del Lili).

Centro y Oriente: baja oferta, con poca representatividad en el mercado.

tabla2 <- table(vivienda2$barrio, vivienda2$tipo,
                vivienda2$zona)
tabla2
## , ,  = Zona Centro
## 
##                   
##                    Apartamento Casa
##   acopi                      0    0
##   aguacatal                  0    0
##   ciudad jardín              0    0
##   el caney                   0    0
##   el ingenio                 0    0
##   el limonar                 0    0
##   el refugio                 0    0
##   la flora                   0    0
##   la hacienda                0    0
##   los cristales              0    0
##   normandía                  0    0
##   pance                      0    0
##   prados del norte           1    0
##   santa teresita             0    0
##   valle del lili             0    0
## 
## , ,  = Zona Norte
## 
##                   
##                    Apartamento Casa
##   acopi                     87   70
##   aguacatal                  0    0
##   ciudad jardín              3    0
##   el caney                   0    0
##   el ingenio                 0    0
##   el limonar                 0    0
##   el refugio                 0    0
##   la flora                 266   99
##   la hacienda                0    0
##   los cristales              0    0
##   normandía                  0    0
##   pance                      0    0
##   prados del norte          93   31
##   santa teresita             2    0
##   valle del lili             3    1
## 
## , ,  = Zona Oeste
## 
##                   
##                    Apartamento Casa
##   acopi                      0    0
##   aguacatal                 97   11
##   ciudad jardín              0    0
##   el caney                   0    0
##   el ingenio                 0    0
##   el limonar                 0    0
##   el refugio                 0    0
##   la flora                   0    0
##   la hacienda                0    0
##   los cristales            137   17
##   normandía                149    4
##   pance                      0    0
##   prados del norte           1    0
##   santa teresita           242   12
##   valle del lili             0    0
## 
## , ,  = Zona Oriente
## 
##                   
##                    Apartamento Casa
##   acopi                      0    0
##   aguacatal                  0    0
##   ciudad jardín              0    0
##   el caney                   0    0
##   el ingenio                 0    0
##   el limonar                 0    0
##   el refugio                 0    0
##   la flora                   0    0
##   la hacienda                0    0
##   los cristales              0    0
##   normandía                  0    0
##   pance                      1    0
##   prados del norte           0    0
##   santa teresita             0    0
##   valle del lili             0    0
## 
## , ,  = Zona Sur
## 
##                   
##                    Apartamento Casa
##   acopi                      1    0
##   aguacatal                  1    0
##   ciudad jardín            218  295
##   el caney                 124   84
##   el ingenio               128   74
##   el limonar                59   76
##   el refugio                77   43
##   la flora                   1    0
##   la hacienda              108   56
##   los cristales              0    0
##   normandía                  1    0
##   pance                    205  203
##   prados del norte           0    0
##   santa teresita             6    0
##   valle del lili           837  167

Etapa 6. Visualizaciones adicionales

ggplot(vivienda,
       aes(preciom)) +
  geom_histogram(bins = 30) +
  theme_minimal()
## Warning: Removed 2 rows containing non-finite outside the scale range
## (`stat_bin()`).

Distribución de precios

ggplot(vivienda,
       aes(zona, preciom)) +
  geom_boxplot() +
  coord_flip()
## Warning: Removed 2 rows containing non-finite outside the scale range
## (`stat_boxplot()`).

Precio por zona

ggplot(vivienda,
       aes(longitud, latitud,
           color = preciom)) +
  geom_point(alpha = 0.5) +
  scale_color_viridis_c() +
  theme_minimal()
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).

Mapa simple con coordenadas

vivienda$precio_m2 <- vivienda$preciom / vivienda$areaconst
aggregate(precio_m2 ~ zona, data = vivienda, mean)
##           zona precio_m2
## 1  Zona Centro  1.745886
## 2   Zona Norte  2.448327
## 3   Zona Oeste  3.644159
## 4 Zona Oriente  1.442864
## 5     Zona Sur  2.720418
aggregate(preciom ~ zona, data = vivienda, mean)
##           zona  preciom
## 1  Zona Centro 309.6935
## 2   Zona Norte 345.6083
## 3   Zona Oeste 677.5801
## 4 Zona Oriente 228.5299
## 5     Zona Sur 426.5184
aggregate(areaconst ~ zona, data = vivienda, mean)
##           zona areaconst
## 1  Zona Centro  194.0424
## 2   Zona Norte  161.1222
## 3   Zona Oeste  196.3992
## 4 Zona Oriente  192.3307
## 5     Zona Sur  173.3122

Tablas relacionales donde se agrupan variables que permitan determinar relaciones y patrones relevantes. ## Conclusiones

Reducción de dimensionalidad (PCA)

Los dos primeros componentes principales explican el 76% de la variabilidad.

Esto significa que variables como precio, área construida, parqueaderos y baños concentran la mayor parte de la información relevante para entender el mercado. En la práctica, la empresa puede simplificar sus modelos de valoración priorizando estas características.

Segmentación de mercado (Clustering)

Se identificaron tres grupos principales de vivienda:

Grupo 1: Casas grandes de precio medio en estratos medios.

Grupo 2: Viviendas de lujo, con más parqueaderos y ubicadas en estratos altos.

Grupo 3: Viviendas pequeñas y económicas, con menor área y menos habitaciones. Esta segmentación permite diseñar estrategias diferenciadas de venta y marketing según el perfil socioeconómico.

Patrones de localización (Correspondencias)

En el Norte y Oeste predominan los apartamentos, asociados a barrios como La Flora, Prados del Norte y Normandía.

En el Sur se observa mayor diversidad: barrios de casas tradicionales (Ciudad Jardín, Pance) y zonas de alta densidad de apartamentos (Valle del Lili).

El Centro y Oriente tienen baja representatividad en la oferta. Esto evidencia que la tipología de vivienda está fuertemente ligada a la zona, lo cual es clave para orientar inversiones.

Recomendaciones

Optimizar inversión: Priorizar proyectos en zonas con alta demanda de apartamentos (Norte y Oeste) y diversificar en el Sur según el perfil del barrio.

Segmentar campañas de marketing: Dirigir mensajes diferenciados para viviendas de lujo vs. viviendas económicas.

Valorar atributos clave: Precio, área construida y número de baños/parqueaderos deben ser los principales factores en la fijación de precios.

Explorar oportunidades en zonas subrepresentadas: El Centro y Oriente pueden ser nichos de inversión si se desarrollan proyectos innovadores que respondan a la baja oferta actual.