Actividad 1 / Evaluación del mercado inmobiliario urbano

Problema

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.

Retos

El reto principal consisten en realizar un análisis integral y multidimensional de la base de datos para obtener una comprensión del mercado inmobiliario urbano. Se requiere aplicar diversas técnicas de análisis de datos, incluyendo:

EDA

Análisis Exploratorio Datos inicial:

# Cargar archivo de datos
library(paqueteNIV)
data(vivienda)

# Ver encabezado / primeras filas
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>
# Resumen datos
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
# Estructura datos
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>
# Tipo objeto datos importados
typeof(vivienda)
## [1] "list"
# Ver últimas filas
tail(vivienda)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  6417 Zona S… <NA>        6    1800       400            3      6            5
## 2  6998 Zona S… <NA>        6    1000       189            3      5            4
## 3  8139 Zona S… <NA>        5     530       142            2      4            4
## 4    NA <NA>    <NA>       NA      NA        NA           NA     NA           NA
## 5    NA <NA>    <NA>       NA      NA        NA           NA     NA           NA
## 6    NA <NA>    <NA>       NA     330        NA           NA     NA           NA
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
# Dataframe datos vivienda
vivienda_df = as.data.frame(vivienda)

# Descartar 3 últimas filas
vivienda_df = vivienda_df %>% 
  slice(1:(n() - 3)) %>%
  arrange(id)

# Selección variables categóricas (character / string)
vivienda_df_chr = vivienda_df %>%
  select(where(is.character))

# Identificación valores únicos variables categóricas
vivienda_df_chr_unq = lapply(vivienda_df_chr, unique)

# Valores únicos por variable
for (col in names(vivienda_df_chr_unq)) {
  if (col != 'barrio') # Debido a la cantidad entradas, duplicados y 
    # nombres mal escritos se omite impresión de variable / columna barrio
    cat('Valores únicos', col, ':', paste(vivienda_df_chr_unq[[col]], collapse = ', '), '\n')
}
## Valores únicos zona : Zona Sur, Zona Oeste, Zona Oriente, Zona Norte, Zona Centro 
## Valores únicos piso : 02, 03, NA, 05, 09, 06, 04, 10, 08, 01, 12, 07, 11 
## Valores únicos tipo : Casa, Apartamento
# Cantidad de barrios en el dataframe (sin consolidar / limpiar)
length(vivienda_df_chr_unq[['barrio']])
## [1] 436
# Cantidad de NaN / nulls por variable
colSums(is.na(vivienda_df))
##           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
# Limpiar NA
vivienda_df_na = na.omit(vivienda_df)

Luego se procede la generación de gráficos descriptivos para las variables del dataframe.

# Selección variables numéricas (numeric / double)
vivienda_df_num = vivienda_df %>%
  select(where(is.numeric))

# Diagrama de cajas de todas las variables
boxplot(vivienda_df_num,
        main='Diagrama de caja vivienda', ylab='Valor',
        xlab='Variables')

# Histogramas / boxplot para cada variable numérica
par(mfrow = c(2, 2))

for (col in names(vivienda_df_num)) {
  if (col != 'id')
    hist(vivienda_df_num[[col]], main = col, xlab = col)
}

# Columnas númericas
colnames(vivienda_df_num)
## [1] "id"           "estrato"      "preciom"      "areaconst"    "parqueaderos"
## [6] "banios"       "habitaciones" "longitud"     "latitud"
# Variables númericas para análisis
vivienda_df_num_cor = vivienda_df_num %>% 
  select(-all_of(c('id', 'latitud', 'longitud')))

vivienda_df_num_na = na.omit(vivienda_df_num_cor)

str(vivienda_df_num_na)
## 'data.frame':    6717 obs. of  6 variables:
##  $ estrato     : num  6 4 6 6 6 6 5 4 6 5 ...
##  $ preciom     : num  880 1200 1280 1300 513 870 310 240 690 220 ...
##  $ areaconst   : num  237 800 346 600 160 490 82.5 80 150 92 ...
##  $ parqueaderos: num  2 3 4 4 2 3 1 1 2 2 ...
##  $ banios      : num  5 6 6 7 4 6 2 2 5 3 ...
##  $ habitaciones: num  4 7 5 5 4 5 3 3 4 3 ...
##  - attr(*, "na.action")= 'omit' Named int [1:1602] 3 13 15 16 22 29 40 47 58 62 ...
##   ..- attr(*, "names")= chr [1:1602] "3" "13" "15" "16" ...
# Matriz dispersión / scatterplot entre variables
par(mfrow = c(1, 1))
pairs(vivienda_df_num_cor)

# Mapa de calor / heatmap entre variables
heatmap(as.matrix(vivienda_df_num_na),
        cexCol = 0.8)

# Tipo vivienda por zona
ggplot(vivienda_df, aes(fill=tipo, y=tipo, x=zona)) + 
    geom_bar(position='stack', stat='identity')

# Torta tipo de vivienda
ggplot(data = as.data.frame(table(vivienda_df$tipo)), aes(x = '', y = Freq, fill = Var1)) +
  geom_bar(stat = 'identity', width = 1) +
  coord_polar('y', start = 0) +
  labs(title = 'Porcentaje de Tipos de Vivienda')

prop.table(table(vivienda_df$tipo)) * 100
## 
## Apartamento        Casa 
##    61.30545    38.69455
# Torta zonas
ggplot(data = as.data.frame(table(vivienda_df$zona)), aes(x = '', y = Freq, fill = Var1)) +
  geom_bar(stat = 'identity', width = 1) +
  coord_polar('y', start = 0) +
  labs(title = 'Porcentaje de Zonas')

prop.table(table(vivienda_df$zona)) * 100
## 
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur 
##     1.490564    23.079697    14.400769     4.219257    56.809713
# Torta estratos
ggplot(data = as.data.frame(table(vivienda_df$estrato)), aes(x = '', y = Freq, fill = Var1)) +
  geom_bar(stat = 'identity', width = 1) +
  coord_polar('y', start = 0) +
  labs(title = 'Porcentaje de Estratos')

prop.table(table(vivienda_df$estrato)) * 100
## 
##        3        4        5        6 
## 17.46604 25.59202 33.05686 23.88508
# Precios por zona
ggplot(vivienda, aes(x=zona, y=preciom, fill=zona)) +
  geom_boxplot() +
  labs(title = 'Precios de vivienda por zona',
       x = 'Zona',
       y = 'Precio (millones de pesos)')

# Precios por tipo vivienda
ggplot(vivienda, aes(x=tipo, y=preciom, fill=tipo)) +
  geom_boxplot() +
  labs(title = 'Precios por tipo de vivienda',
       x = 'Tipo vivienda',
       y = 'Precio (millones de pesos)')

# Dispersión del área versus el precio
ggplot(vivienda_df, aes(x = areaconst, y = preciom)) + 
  geom_point(color = 'steelblue') +
  geom_smooth(method = 'lm', se = FALSE, color = 'slategray') +
  labs(title = 'Relación entre el precio y el área construida de vivienda',
       x = 'Área construida de la vivienda (metros cuadrados)',
       y = 'Precio de la vivienda (millones de pesos)')
## `geom_smooth()` using formula = 'y ~ x'

# Dispersión del área versus el precio por zona de la vivienda
ggplot(vivienda, aes(x = areaconst, y = preciom, color=zona, alpha=0.3)) +
  geom_point() +
  labs(title = 'Relación entre el precio, el área construida y la zona de la vivienda',
       x = 'Área construida de la vivienda (metros cuadrados)',
       y = 'Precio de la vivienda (millones de pesos)')

# Dispersión de la zona versus el precio por zona de la vivienda
ggplot(vivienda, aes(x = zona, y = preciom, color=estrato, alpha=0.3)) +
  geom_point() +
  labs(title = 'Relación entre el precio, el estrato y la zona de la vivienda',
       x = 'Estrato',
       y = 'Precio de la vivienda (millones de pesos)')

Ubicación espacial de las viviendas con leaflet:

# Mapa interactivo con 'leaflet'
map = leaflet(data = vivienda_df) %>%
  addTiles()

# Inclusión marcadores para cada vivienda en el mapa
map = map %>%
  addMarkers(lng = ~longitud, lat = ~latitud, clusterOptions = markerClusterOptions())

# Visualización mapa (hmtl_output)
map
# Guardado mapa / exportado a imagen / pdf
# mapshot(map, file = '~/map.png')
# knitr::include_graphics('map.png')

Con el análisis exploratorio del conjunto de datos claro, procedemos a realizar los diferentes análisis requeridos en la actividad.

Reto 1

Análisis de Componentes Principales: Reducir la dimensionalidad del conjunto de datos y visualizar la estructura de las variables en componentes principales para identificar características clave que influyen en la variación de precios y preferencias del mercado.

# Verificar datos faltantes
md.pattern(vivienda_df_num_na)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

##      estrato preciom areaconst parqueaderos banios habitaciones  
## 6717       1       1         1            1      1            1 0
##            0       0         0            0      0            0 0
# Escalar datos
vivienda_df_scl = vivienda_df_num_na %>%
  scale()

vivienda_df_scl = as.data.frame(vivienda_df_scl)

head(vivienda_df_scl)
##      estrato   preciom  areaconst parqueaderos    banios habitaciones
## 1  1.2318711 1.2270643  0.3876728    0.1465058 1.2639704    0.2852449
## 2 -0.8746661 2.1821653  4.2946860    1.0354668 1.9885044    2.4841622
## 4  1.2318711 2.4209406  1.1440928    1.9244277 1.9885044    1.0182173
## 5  1.2318711 2.4806344  2.9067595    1.9244277 2.7130384    1.0182173
## 6  1.2318711 0.1316828 -0.1466789    0.1465058 0.5394364    0.2852449
## 7  1.2318711 1.1972174  2.1433999    1.0354668 1.9885044    1.0182173
# Análisis de componentes principales / PCA
vivienda_df_pca = prcomp(vivienda_df_scl, scale. = TRUE)

vivienda_df_pca
## Standard deviations (1, .., p=6):
## [1] 1.8664857 1.1059274 0.7067478 0.5996120 0.4943519 0.4355974
## 
## Rotation (n x k) = (6 x 6):
##                     PC1        PC2        PC3         PC4        PC5        PC6
## estrato      -0.2953982 -0.6377404 -0.5431029 -0.07074563 -0.4349440 -0.1299429
## preciom      -0.4704788 -0.2394751  0.1081038  0.29100096  0.2659341  0.7444545
## areaconst    -0.4502724  0.2044012  0.2594726  0.65721148 -0.3038390 -0.4048503
## parqueaderos -0.4278010 -0.1513045  0.6161907 -0.62045124 -0.1192404 -0.1233864
## banios       -0.4652553  0.1598972 -0.3695544 -0.14075513  0.6782753 -0.3762054
## habitaciones -0.2986104  0.6676068 -0.3313085 -0.27132051 -0.4165440  0.3290044
# Resumen PCA
summary(vivienda_df_pca)
## Importance of components:
##                           PC1    PC2     PC3     PC4     PC5     PC6
## Standard deviation     1.8665 1.1059 0.70675 0.59961 0.49435 0.43560
## Proportion of Variance 0.5806 0.2039 0.08325 0.05992 0.04073 0.03162
## Cumulative Proportion  0.5806 0.7845 0.86772 0.92765 0.96838 1.00000
# Elección componentes principales
fviz_eig(vivienda_df_pca, addlabels = TRUE)

# Visualización componentes principales en el plano
fviz_pca_var(vivienda_df_pca,
             col.var = 'contrib',
             gradient.cols = c('skyblue',  'salmon'),
             repel = TRUE)

# Contribución de variables al PC1
fviz_contrib(vivienda_df_pca, choice = 'var', axes = 1, top = 10)

# Contribución de variables al PC1
fviz_contrib(vivienda_df_pca, choice = 'var', axes = 2, top = 10)

# # Visualización de individuales
# fviz_pca_ind(vivienda_df_pca, col.ind = 'cos2',
#              gradient.cols = c('skyblue', 'gold', 'salmon'),
#              repel = TRUE)

# # Visualización de individuales y variables
# fviz_pca_biplot(vivienda_df_pca, repel = TRUE)

Reto 2.

Análisis de Conglomerados: Agrupar las propiedades residenciales en segmentos homogéneos con características similares para entender las dinámicas y demandas específicas en diferentes partes de la ciudad y en diferentes estratos socio económicos.

  • Análisis zona / precio
# Selección df precio y zona
vivienda_prz = vivienda_df %>%
  select(zona, preciom)

vivienda_prz$zona = factor(vivienda_prz$zona, 
                              levels = c('Zona Centro', 'Zona Norte', 
                                         'Zona Oeste', 'Zona Oriente', 
                                         'Zona Sur'))
# Estructura datos
str(vivienda_prz)
## 'data.frame':    8319 obs. of  2 variables:
##  $ zona   : Factor w/ 5 levels "Zona Centro",..: 5 3 5 5 5 5 5 5 5 5 ...
##  $ preciom: num  880 1200 250 1280 1300 513 870 310 240 690 ...
# Factor a numérico
vivienda_prz = vivienda_prz %>%
  mutate(zona = as.integer(zona))

# Escalar datos
vivienda_prz_scl = vivienda_prz %>%
  scale()

vivienda_prz_scl = as.data.frame(vivienda_prz_scl)

# Distancias euclidianas
vivienda_prz_dist = dist(vivienda_prz_scl, method = 'euclidean')
# vivienda_prz_dist

# Clúster jerárquico método complete
vivienda_prz_hclust = hclust(vivienda_prz_dist, method = 'complete')

# Determinación pertenencia cada observación
vivienda_prz_cutree = cutree(vivienda_prz_hclust, k = 5)

# Asignación clústeres
vivienda_prz_cluster = vivienda_prz_scl %>%
  mutate(cluster = as.factor(vivienda_prz_cutree))

# gráfico de puntos
ggplot(vivienda_prz_cluster, aes(x = zona, y = preciom, color = cluster)) +
  geom_point(size = 4) +
  geom_text(aes(label = cluster), vjust = -.8)

# Dendograma zonas / precio
plot(vivienda_prz_hclust, cex = 0.6, main = 'Dendograma de zonas / precios',
     las=1, ylab = 'Distancia euclidiana', xlab = 'Grupos')
rect.hclust(vivienda_prz_hclust, k = 5, border = 2:5)

# Silueta zona / precio
vivienda_prz_sil= silhouette(vivienda_prz_cutree, vivienda_prz_dist)
mean(vivienda_prz_sil[, 3])
## [1] 0.5809917
  • Análisis estrato / precio
# Selección df precio y estrato
vivienda_pre = vivienda_df %>%
  select(estrato, preciom)

vivienda_pre = na.omit(vivienda_pre)

# Estructura datos
str(vivienda_pre)
## 'data.frame':    8319 obs. of  2 variables:
##  $ estrato: num  6 4 5 6 6 6 6 5 4 6 ...
##  $ preciom: num  880 1200 250 1280 1300 513 870 310 240 690 ...
# Escalar datos
vivienda_pre_scl = vivienda_pre %>%
  scale()

vivienda_pre_scl = as.data.frame(vivienda_pre_scl)

# Distancias euclidianas
vivienda_pre_dist = dist(vivienda_pre_scl, method = 'euclidean')
# vivienda_pre_dist

# Clúster jerárquico método complete
vivienda_pre_hclust = hclust(vivienda_pre_dist, method = 'complete')

# Determinación pertenencia cada observación
vivienda_pre_cutree = cutree(vivienda_pre_hclust, k = 4)

# Asignación clústeres
vivienda_prz_cluster = vivienda_prz_scl %>%
  mutate(cluster = as.factor(vivienda_prz_cutree))

# gráfico de puntos
ggplot(vivienda_prz_cluster, aes(x = zona, y = preciom, color = cluster)) +
  geom_point(size = 4) +
  geom_text(aes(label = cluster), vjust = -.8)

# Dendograma estrato / precio
plot(vivienda_prz_hclust, cex = 0.6, main = 'Dendograma de estratos / precio', 
     las=1, ylab = 'Distancia euclidiana', xlab = 'Grupos')
rect.hclust(vivienda_prz_hclust, k = 4, border = 2:5)

# Silueta estrato / precio
vivienda_pre_sil= silhouette(vivienda_pre_cutree, vivienda_pre_dist)
mean(vivienda_pre_sil[, 3])
## [1] 0.5135364
  • Análisis zona / estrato
# Selección df zona y estrato
vivienda_df_ze = vivienda_df %>%
  select(zona, estrato)

vivienda_df_ze$zona = factor(vivienda_df_ze$zona, 
                              levels = c('Zona Centro', 'Zona Norte', 
                                         'Zona Oeste', 'Zona Oriente', 
                                         'Zona Sur'))

vivienda_df_ze = na.omit(vivienda_df_ze)

# Factor a numérico
vivienda_df_ze = vivienda_df_ze %>%
  mutate(zona = as.integer(zona))

# Escalar datos
vivienda_df_ze_scl = vivienda_df_ze %>%
  scale()

vivienda_df_ze_scl = as.data.frame(vivienda_df_ze_scl)

# Distancias euclidianas
vivienda_df_ze_dist = dist(vivienda_df_ze_scl, method = 'euclidean')
# vivienda_df_ze_dist

# Clúster jerárquico método complete
vivienda_df_ze_hclust = hclust(vivienda_df_ze_dist, method = 'complete')

# Determinación pertenencia cada observación
vivienda_df_ze_cutree = cutree(vivienda_df_ze_hclust, k = 5)

# Asignación clústeres
vivienda_df_ze_cluster = vivienda_df_ze_scl %>%
  mutate(cluster = as.factor(vivienda_df_ze_cutree))

# gráfico de puntos
ggplot(vivienda_df_ze_cluster, aes(x = zona, y = estrato, color = cluster)) +
  geom_point(size = 4) +
  geom_text(aes(label = cluster), vjust = -.8)

# Dendograma zona / estrato
plot(vivienda_df_ze_hclust, cex = 0.6, main = 'Dendograma de zonas / estratos',
     las=1, ylab = 'Distancia euclidiana', xlab = 'Grupos')
rect.hclust(vivienda_df_ze_hclust, k = 5, border = 2:5)

# Silueta zona / estrato
vivienda_df_ze_sil= silhouette(vivienda_df_ze_cutree, vivienda_df_ze_dist)
mean(vivienda_df_ze_sil[, 3])
## [1] 0.6489482

Reto 3

Análisis de Correspondencia : Examinar la relación entre las variables categóricas (tipo de vivienda, zona y barrio) para identificar patrones de comportamiento del mercado inmobiliario.

  • Análisis zona / estrato
# Tabla contingencia zona / estrato
vivienda_table_ze = table(vivienda_df$zona, vivienda_df$estrato)
vivienda_table_ze
##               
##                   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 1685 1043
# Prueba Chi-Squared
chisq.test(vivienda_table_ze)
## 
##  Pearson's Chi-squared test
## 
## data:  vivienda_table_ze
## X-squared = 3830.4, df = 12, p-value < 2.2e-16
# Análisis Correspondencia 
vivienda_ze_ac = CA(vivienda_table_ze)

# Valores propios
vivienda_ze_vp = vivienda_ze_ac$eig
vivienda_ze_vp
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1 0.32215213              69.965515                          69.96551
## dim 2 0.12745096              27.680002                          97.64552
## dim 3 0.01084108               2.354483                         100.00000
#  Gráfico varianza
fviz_screeplot(vivienda_ze_ac, addlabels = TRUE) + 
  ggtitle('') +
  ylab('Porcentaje de varianza explicado') + 
  xlab('Ejes')

  • Análisis zona / barrio
# Tabla contingencia zona / barrio
vivienda_table_zb = table(vivienda_df$zona, vivienda_df$barrio)
# vivienda_table_zb

# Prueba Chi-Squared
chisq.test(vivienda_table_zb)
## 
##  Pearson's Chi-squared test
## 
## data:  vivienda_table_zb
## X-squared = 29343, df = 1740, p-value < 2.2e-16
# Análisis Correspondencia 
vivienda_zb_ac = CA(vivienda_table_zb)

# Valores propios
vivienda_zb_vp = vivienda_zb_ac$eig
vivienda_zb_vp
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1  0.9619479               27.27168                          27.27168
## dim 2  0.9298275               26.36105                          53.63272
## dim 3  0.8951910               25.37909                          79.01181
## dim 4  0.7403118               20.98819                         100.00000
#  Gráfico varianza
fviz_screeplot(vivienda_zb_ac, addlabels = TRUE) + 
  ggtitle('') +
  ylab('Porcentaje de varianza explicado') + 
  xlab('Ejes')

  • Análisis estrato / barrio
# Tabla contingencia estrato / barrio
vivienda_table_eb = table(vivienda_df$estrato, vivienda_df$barrio)
# vivienda_table_eb

# Prueba Chi-Squared
chisq.test(vivienda_table_eb)
## Warning in chisq.test(vivienda_table_eb): Chi-squared approximation may be
## incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  vivienda_table_eb
## X-squared = 14933, df = 1305, p-value < 2.2e-16
# Análisis Correspondencia 
vivienda_eb_ac = CA(vivienda_table_eb)

fviz_ca_biplot(vivienda_eb_ac, repel = FALSE, label = 'row')

# Valores propios
vivienda_eb_vp = vivienda_eb_ac$eig
vivienda_eb_vp
##       eigenvalue percentage of variance cumulative percentage of variance
## dim 1  0.8223533               45.81376                          45.81376
## dim 2  0.6863211               38.23533                          84.04909
## dim 3  0.2863175               15.95091                         100.00000
#  Gráfico varianza
fviz_screeplot(vivienda_eb_ac, addlabels = TRUE) + 
  ggtitle('') +
  ylab('Porcentaje de varianza explicado') + 
  xlab('Ejes')

Conclusiones y Recomendaciones

Con la base de datos de viviendas con la que cuenta la empresa inmobiliaria se realizó un análisis de variables del conjunto de datos y se encuentra lo siguiente:

  • En la base de datos se encuentran datos para 5 zonas, de los cuales el 56.8% de los datos / viviendas pertenecen a la Zona Sur (seguida por un 23.1% en la Zona Norte).
  • Todos los datos suministrados pertenecen a viviendas de estrato 3 al 6 (siendo el 5 el mayoritario con un 33%).
  • El rango de precios de las viviendas va desde los 58 millones hasta un máximo de 1999 millones de pesos.
  • El área construida mínima encontrada en los inmuebles analizados es de 30 m2 y la máxima de 1745 m2.
  • Aproximadamente el 61% de los datos son tipo apartamento y el restante 39% son casas.
  • El 75% de los precios de las viviendas analizadas es menor a 540 millones y menor a 229 m2.
  • Como era de esperarse las casas presentan las áreas y precios más altos en el conjunto de datos estudiados. Así mismo, parece haber una buena correlación entre el área construida y el precio de las viviendas estudiadas.
  • Los precios promedios más altos se encuentran en las zonas Oeste y Sur, los más bajos en la Oriente.
  • Los estratos más bajos se encuentran en las zonas Centro y Oriente, y acorde a lo anterior los estratos (y precios) más altos en las zonas Oeste y Sur.
  • El análisis de componentes principales (PCA) de las variables numéricas del conjunto de datos, arroja que el primer componente / dimensión principal PC1 resume 58.1% de la variabilidad de los datos, mientras que el segundo PC2 resume el 20.4%, es decir los dos primeros acumulan el 78.5% de la varianza (86.7% con PC3). Las variables con mayor contribución a PC1 son el precio, número de baños y el área construida y número de parqueaderos; mientas que a PC2 la principales contribuciones provienen del número de habitaciones y el estrato se realizó para la zona / precio, el estrato / precio y zona / estrato. Debido a lo más de 8 mil datos analizados, los gráficos de puntos no fueron del todo claros a la hora del análisis, pero las siluetas promedios calculados obtenidas fueron de 0.58 para zona / precio y 0.51 para estrato / precio, mientras que para zona / estrato aumenta el promedio a 0.65.
  • El análisis de conglomerados.
  • El análisis de correspondencia aplicado a las variables categóricas analizadas, nos permiten evidenciar inicialmente que el estrato 6 se encuentra en la zona Oeste de ahí los precios más altos de las viviendas analizadas en dicha zona. Los estratos 4 y 5 corresponden a las zonas Sur y Norte (que siguen en el orden en precios más altos), mientras que el estrato 3 se encuentra asociado a las zonas Centro y Oriente (la de precios más bajos). Los dos primeros componentes / ejes del análisis zona / estrato resumen un 97.6% de los datos. Para el análisis de correspondencia zona / barrio, las 4 dimensiones / componentes presentan un porcentaje similar de varianza entre el 21 al 27%. Por último se analizó la correspondencia entre el estrato / barrio y este caso los dos primeros ejes / dimensiones resumen el 84% de los datos.
  • Respecto al material de estudio, se recomienda revisar ortografía, funcionalidad de los ejemplos y la ampliación de los mismos.

Referencias

Díaz Monroy, Luis Guillermo. 2007. “Estadística Multivariada: Inferencia y Métodos.” https://repositorio.unal.edu.co/handle/unal/79907.
Díaz Monroy, Luis Guillermo, and Mario Alfonso Morales Rivera. 2012. “Análisis Estadístico de Datos Multivariados.” https://repositorio.unal.edu.co/handle/unal/79916.
Holtz, Yan. n.d. “The R Graph Gallery – Help and Inspiration for R´ Charts.” The R Graph Gallery. Accessed August 11, 2023. https://r-graph-gallery.com/.
Kassambara, Alboukadel. n.d. “Factoextra R Package: Easy Multivariate Data Analyses and Elegant Visualization.” Accessed August 13, 2023. http://www.sthda.com/english/wiki/factoextra-r-package-easy-multivariate-data-analyses-and-elegant-visualization.
Pardo, Campo Elías. 2020. “Estadística Descriptiva Multivariada.” https://repositorio.unal.edu.co/handle/unal/79914.
Soage, José Carlos. n.d. R-Charts.com. Accessed August 12, 2023. https://r-charts.com/.
Stack Exchange, Inc. n.d. Stack Overflow. Accessed August 13, 2023. https://stackoverflow.com/.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2023. R Markdown: The Definitive Guide. https://bookdown.org/yihui/rmarkdown/.