Análisis del mercado inmobiliario en Cali

1. Introducción

El mercado de viviendas urbanas es un sector complejo y dinámico que se encuentra en constante evolución. Para tener éxito en este mercado, las empresas inmobiliarias necesitan comprender en profundidad las tendencias del mercado, las necesidades de los clientes y la competencia.

En este informe, se presenta un análisis del mercado de viviendas urbanas en Cali. El análisis se basa en información detallada sobre diversas propiedades residenciales disponibles en el mercado de la ciudad de Cali.

2. Objetivos

  • Objetivo 1: Proporcionar información del precio de las viviendas en diferentes zonas de Cali.
  • Objetivo 2: Identificar tipo de viviendas más ofertadas en Cali.
  • Objetivo 3: Dar a conocer las características más relevantes de la oferta de vivienda en Cali.

3. Métodos

Se realiza un primer análisis exploratorio de la base de datos. Este análisis se estructurará en la identificación de las columnas y dimensiones de la tabla, lo segundo será identificar los tipos de datos de las columnas y seleccionar cuáles serán relevantes para el análisis. Lo tercero será realizar la identificación de valores perdidos dentro de las columnas seleccionadas para el análisis y brindar posibles propuestas para poder solucionar los datos faltantes. Con la realización de estos pasos se puede determinar la relación de algunas variables con respecto a los objetivos del presente informe.

3.1 Cargue de base de datos

data(vivienda_faltantes)
head(vivienda_faltantes)
## # A tibble: 6 × 13
##      id zona        piso estrato preciom areaconst parquea banios habitac tipo  
##   <dbl> <chr>      <dbl>   <dbl>   <dbl>     <dbl>   <dbl>  <dbl>   <dbl> <chr> 
## 1  8312 Zona Oeste     4       6    1300       318       2      4       2 Apart…
## 2  8311 Zona Oeste     1       6     480       300       1      4       4 Casa  
## 3  8307 Zona Oeste    NA       5    1200       800       4      7       5 Casa  
## 4  8296 Zona Sur       2       3     220       150       1      2       4 Casa  
## 5  8297 Zona Oeste    NA       5     330       112       2      4       3 Casa  
## 6  8298 Zona Sur      NA       5    1350       390       8     10      10 Casa  
## # ℹ 3 more variables: barrio <chr>, longitud <dbl>, latitud <dbl>
cat("Cantidad columnas: ", ncol(vivienda_faltantes), "Cantidad filas: ", nrow(vivienda_faltantes))
## Cantidad columnas:  13 Cantidad filas:  8330

3.2 Selección de datos relevantes

Según los objetivos del estudio, se identifican como variables relevantes zona, barrio, tipo como variables categóricas. Para análisis de variables numéricas se selecciona principalmente la variable preciom, como variables para análisis de caraterísticas se seleccionan piso, estrato, areaconst, banios, habitac. A continuación se realiza una verificación de datos categóricos relevantes:

unique_values <- unique(vivienda_faltantes$zona)
print(paste0("Valores únicos para zona: ", paste0(unique_values, collapse = ", ")))
## [1] "Valores únicos para zona: Zona Oeste, Zona Sur, Zona Norte, Zona Oriente, Zona Centro, NA"
unique_values <- unique(vivienda_faltantes$tipo)
print(paste0("Valores únicos para tipo: ", paste0(unique_values, collapse = ", ")))
## [1] "Valores únicos para tipo: Apartamento, Casa, APARTAMENTO, casa, CASA, apto, NA"
# Generando vector para resumir las columnas seleccionadas
specific_columns <- c("preciom", "piso", "estrato", "areaconst", "banios", "habitac")
summary(vivienda_faltantes[, specific_columns])
##     preciom            piso           estrato        areaconst   
##  Min.   :  58.0   Min.   : 1.000   Min.   :3.000   Min.   :  30  
##  1st Qu.: 220.0   1st Qu.: 2.000   1st Qu.:4.000   1st Qu.:  80  
##  Median : 330.0   Median : 3.000   Median :5.000   Median : 123  
##  Mean   : 434.2   Mean   : 3.772   Mean   :4.634   Mean   : 175  
##  3rd Qu.: 540.0   3rd Qu.: 5.000   3rd Qu.:5.000   3rd Qu.: 229  
##  Max.   :1999.0   Max.   :12.000   Max.   :6.000   Max.   :1745  
##  NA's   :2        NA's   :2641     NA's   :3       NA's   :3     
##      banios          habitac      
##  Min.   : 0.000   Min.   : 0.000  
##  1st Qu.: 2.000   1st Qu.: 3.000  
##  Median : 3.000   Median : 3.000  
##  Mean   : 3.112   Mean   : 3.605  
##  3rd Qu.: 4.000   3rd Qu.: 4.000  
##  Max.   :10.000   Max.   :10.000  
##  NA's   :3        NA's   :3

3.3 Limpieza de datos

Se evidencia que vienen valores de id con vacíos, para lo cual es necesario quitarlos de la base de datos:

faltantes_id = sum(is.na(vivienda_faltantes$id))
cat("Cantidad de id faltantes:", faltantes_id)
## Cantidad de id faltantes: 3
## Se remueven los id vacios de la tabla:
vivienda_faltantes = subset(vivienda_faltantes, !is.na(id))
cat("Nueva cantidad filas: ", nrow(vivienda_faltantes))
## Nueva cantidad filas:  8327

También se realiza la verificación de datos duplicados dentro de la tabla provista:

duplicates <- duplicated(vivienda_faltantes)
n_duplicates <- sum(duplicates)
cat("Cantidad de filas duplicadas: ", n_duplicates)
## Cantidad de filas duplicadas:  8
## Se remueven los duplicados encontrados:
vivienda_faltantes <- unique(vivienda_faltantes)
cat("Nueva cantidad filas: ", nrow(vivienda_faltantes))
## Nueva cantidad filas:  8319

Con lo identificado en la selección de variables se realiza la limpieza de las columnas de tipo, zona y barrio. Adicionalmente, al haber identificado un valor de “APTO” en la columna zona, esta se unifica con “APARTAMENTO” para normalizar los datos.

vivienda_faltantes$zona <- toupper(vivienda_faltantes$zona)
vivienda_faltantes$barrio <- toupper(vivienda_faltantes$barrio)
vivienda_faltantes$tipo <- toupper(vivienda_faltantes$tipo)
vivienda_faltantes$tipo <- ifelse(vivienda_faltantes$tipo=='CASA','CASA','APARTAMENTO')
unique_values <- unique(vivienda_faltantes$zona)
print(paste0("Valores únicos para zona: ", paste0(unique_values, collapse = ", ")))
## [1] "Valores únicos para zona: ZONA OESTE, ZONA SUR, ZONA NORTE, ZONA ORIENTE, ZONA CENTRO"
unique_values <- unique(vivienda_faltantes$tipo)
print(paste0("Valores únicos para tipo: ", paste0(unique_values, collapse = ", ")))
## [1] "Valores únicos para tipo: APARTAMENTO, CASA"

3.4 Identificación de faltantes

## uses visdat
vis_miss(vivienda_faltantes)

Haciendo uso de la librería visdat se logra identificar que dentro de la tabla dispuesta, después de la limpieza se tiene 3.9 % de datos faltantes. Todos distribuidos en las columnas parqueaderos y piso.

## uses visdat
md.pattern(vivienda_faltantes, rotate.names = TRUE)

##      id zona estrato preciom areaconst banios habitac tipo barrio longitud
## 4808  1    1       1       1         1      1       1    1      1        1
## 1909  1    1       1       1         1      1       1    1      1        1
## 876   1    1       1       1         1      1       1    1      1        1
## 726   1    1       1       1         1      1       1    1      1        1
##       0    0       0       0         0      0       0    0      0        0
##      latitud parquea piso     
## 4808       1       1    1    0
## 1909       1       1    0    1
## 876        1       0    1    1
## 726        1       0    0    2
##            0    1602 2635 4237

Asi mismo, utilizando la librería mice se logra distinguir en qué categorías se encuentran mezclados los datos perdidos. Para el total de filas (8.319 filas) después de limpieza, se logra identificar que hay 1.602 (19,25 %) datos perdidos para la variable parqueaderos. Mientras que para la variable piso existen un total de 2.635 (31,67 %) filas sin datos.

En cuanto a la combinación de datos perdidos entre las dos variables identificadas, se resalta que hay 1.909 (22,94 %) filas con datos perdidos únicamente para la variable piso, hay 876 (10,53%) filas con datos perdidos únicamente para parqueaderos y 726 (8,72 %) filas que no tienen datos para ninguna de las dos columnas.

3.5 Posibles estrategías para mitigar datos faltantes

La primera posible solución para poder trabajar con los datos de la forma más completa posible puede ser precindir de usar las variables parqueaderos y piso. Esta estrategia tiene como ventaja que puede ser de las más rápidas de implementar, así como reducir la dimensionalidad de los datos, con lo que aplicar algunos algoritmos puede llegar a ser más eficiente. Así mismo, la reducción de información dentro de la tabla puede generar eliminación de información importante, lo que puede conllevar a presentar sesgo en el resultado.

vivienda_faltantes <- vivienda_faltantes[, -c("parqueaderos", "piso")]

La segunda solución puede ser implementar una imputación por alguna medida de tendencia central. Esta también es una medida simple de implementar y puede ayudar a conservar la dimensionalidad del conjunto de datos. Como contra puede que si los valores faltantes no son aleatorios o dependen de alguna categorización puede guiar a tener sesgo en los resultados.

median_value <- median(vivienda_faltantes$piso) Se calcula la mediana y se imputa vivienda_faltantes$piso[is.na(vivienda_faltantes$piso)] <- median_value

También se puede intentar implementar una imputación por regresión. Esta técnica puede llegar a ser más sofisticada ya que tiene en cuenta la interacción entre variables. Sin embargo, este tipo de técnicas puede llegar a ser menos eficiente (tomar más tiempo de ejecución) que la imputación por medidas de tendencia central para conjuntos de datos grandes.

4. Resultados

4.1 Precio de las viviendas en diferentes zonas de Cali

Después de realizar la limpieza de los datos se procede a analizar los puntos propuestos dentro de los objetivos del escrito. Entre ellos, se puede realizar la verificación de los precios en general para las viviendas de cali. Lo primero será realizar un box plot por zona y precio en millones de pesos.

ggplot(vivienda_faltantes, aes(x = preciom, y = zona)) +
  geom_boxplot() + labs(title = "Precio en millones según zona",
                        x = "Precio (millones de pesos)",
                        y = "Zona") +
  theme_bw()

Antes de sacar conclusiones del gráfico, también puede ser útil realizar la visualización de la cantidad de propiedades por zona que están ofertadas en la base de datos:

ggplot(vivienda_faltantes, aes(x = zona)) +
  geom_bar() +
  labs(title = "Cantidad de viviendas por zona",
       x = "Zona",
       y = "Cantidad ofertada")

Como se puede observar en la gráfica, la zona sur es la zona que más viviendas tiene en oferta, seguida por la zona norte y la zona oeste. Sin embargo, la zona sur presenta una asimetría a la derecha desde la media con respecto a sus precios, aunque se encuentran más concentrados con respecto a la mediana que en la zona oeste. También es importante resaltar que sólo en la zona oeste la mediana de precios se encuentra después de los 500 millones de pesos, esta zona posee gran variabilidad en la columna de precio, el resto de zonas tiene su mediana rondando por los 250 millones de pesos.

Aquí también surge la necesidad de realizar un análisis de precio por metro cuadrado. Para articular este ejercicio se declara la variable preciom2 que va a ser el resultado de la división de preciom por areaconst. La variable se declara de la siguiente manera:

vivienda_faltantes$preciom2 <- vivienda_faltantes$preciom / vivienda_faltantes$areaconst
summary(vivienda_faltantes$preciom2)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.1461  1.9167  2.6400  2.7222  3.3795  9.4681

Y se realiza la correspondiente gráfica por zona nuevamente para poder identificar precios anómalos dentro de la base de datos:

ggplot(vivienda_faltantes, aes(x = preciom2, y = zona)) +
  geom_boxplot() + labs(title = "Precio x m2 en millones según zona",
                        x = "Precio x m2 (millones de pesos)",
                        y = "Zona") +
  theme_bw()

Llama la atención un precio de 9.46 millones de pesos por metro cuadrado en la zona norte, que se encuentra además muy alejado de los demás datos dentro de la distribución.

4.2 Tipo de viviendas más ofertadas en Cali

En la base de datos usada, luego de limpieza, sólo se tienen dos tipos de viviendas: apartamentos y casas. La distribución de las cantidades ofertadas se analiza a continuación en el gráfico de barras:

ggplot(vivienda_faltantes, aes(x = tipo, fill = tipo)) +
  geom_bar() +
  labs(title = "Tipo de viviendas más ofertadas",
       x = "Tipo de viviendas",
       y = "Cantidad ofertada")

Allí se puede evidenciar que se ofertan más apartamentos (más de 5.000 unidades) con respecto a casas (más de 3.000 unidades) en la data prevista para Cali. Así mismo, para complementar el análisis de precio, se presenta un análisis de cambios de precio con respecto al tipo en el siguiente gráfico de bigotes y cajas:

ggplot(vivienda_faltantes, aes(x = preciom, y = tipo)) +
  geom_boxplot() + labs(title = "Precio en millones según tipo de vivienda",
                        x = "Precio (millones de pesos)",
                        y = "Tipo de vivienda") +
  theme_bw()

En el anterior gráfico se puede observar que se tienen outliers en precio que van desde los 1.250 millones de pesos hasta casi 2.000 millones de pesos para el caso de las casas y desde aproximadamente los 800 millones de pesos hasta los 2.000 millones de pesos también para los apartamentos.

ggplot(vivienda_faltantes, aes(x = preciom2, y = tipo)) +
  geom_boxplot() + labs(title = "Precio x m2 en millones según tipo de vivienda",
                        x = "Precio x m2 (millones de pesos)",
                        y = "Tipo de vivienda") +
  theme_bw()

Como principal hallazgo destacado, se encuentra en este gráfico que las casas tienen un menor precio por metro cuadrado que los apartamentos, encontrandose su mediana por debajo de los 2,5 millones de pesos x m2, mientras que los apartamentos tienen una mediana por encima de los 2,5 millones de pesos.

4.3 Características más relevantes de la oferta de vivienda en Cali

Este apartado pretende mostrar las características principales de las viviendas en Cali, así como su correlación con el precio para oferta. De lo encontrado en la base de datos, se realizará una tabla dinámica que contiene la información agrupada en promedios de preciom, preciom2, banios y areaconst como variables numéricas relevantes para el análisis de las características de las viviendas en oferta.

vivienda_faltantes %>%
  group_by(zona, tipo) %>%
  summarize(
    preciom_mean = mean(preciom),
    preciom2_mean = mean(preciom2),
    banios_mean = mean(banios),
    areaconst_mean = mean(areaconst)
  )
## `summarise()` has grouped output by 'zona'. You can override using the
## `.groups` argument.
## # A tibble: 10 × 6
## # Groups:   zona [5]
##    zona         tipo       preciom_mean preciom2_mean banios_mean areaconst_mean
##    <chr>        <chr>             <dbl>         <dbl>       <dbl>          <dbl>
##  1 ZONA CENTRO  APARTAMEN…         187.          1.95        2.12           95.1
##  2 ZONA CENTRO  CASA               339.          1.70        3.01          218. 
##  3 ZONA NORTE   APARTAMEN…         285.          2.81        2.31           98.6
##  4 ZONA NORTE   CASA               446.          1.85        3.56          265. 
##  5 ZONA OESTE   APARTAMEN…         668.          3.85        3.39          172. 
##  6 ZONA OESTE   CASA               736.          2.39        4.26          343. 
##  7 ZONA ORIENTE APARTAMEN…         153.          1.70        1.73           94.2
##  8 ZONA ORIENTE CASA               245.          1.39        2.97          213. 
##  9 ZONA SUR     APARTAMEN…         297.          2.99        2.49           97.5
## 10 ZONA SUR     CASA               612.          2.34        4.17          282.

También se permite realizar un análisis por estrato, dado que se entiende el estrato como una variable que puede afectar directamente la valoración de una vivienda. En este caso se toman las variables de zona y tipo como índice, la variable estrato como columna, y como variable objetivo se toma el precio x m2, agregado en promedios.

dcast(vivienda_faltantes, zona + tipo ~ estrato, value.var = "preciom2", fun.aggregate = mean)
##            zona        tipo        3        4         5        6
## 1   ZONA CENTRO APARTAMENTO 1.687162 2.196739 2.5970172      NaN
## 2   ZONA CENTRO        CASA 1.618190 2.129628 5.0387597 2.500000
## 3    ZONA NORTE APARTAMENTO 1.982170 2.619976 3.2505142 3.732418
## 4    ZONA NORTE        CASA 1.741728 1.832592 1.8555119 2.284297
## 5    ZONA OESTE APARTAMENTO 2.166269 2.741639 3.5526116 4.106758
## 6    ZONA OESTE        CASA 2.217560 2.171362 2.0538018 2.885407
## 7  ZONA ORIENTE APARTAMENTO 1.568097 3.011905 1.7500000 6.367925
## 8  ZONA ORIENTE        CASA 1.383509 1.702931 0.9866667      NaN
## 9      ZONA SUR APARTAMENTO 2.088322 2.711098 3.0142868 3.977286
## 10     ZONA SUR        CASA 1.644637 2.018603 2.2415438 2.942569

5. Discusión

En esta sección se van a explorar los hallazgos más relevantes del trabajo expuesto en los resultados. Los mayores puntos y más relevantes se encuentran enfocados a las características de las viviendas que se trataron en el punto 4.3 de este reporte.

5.1 Puntos relevantes encontrados dentro de los resultados

  • En la mayoría de las zonas el área construida de las casas tiende a ser el doble o hasta el triple del área construida de los apartamentos.
  • Las casas tienen hasta un baño más en promedio que los apartamentos. De resaltar que en la zona sur y en la zona oeste las casas tienen aproximadamente 4.2 baños en promedio.
  • Los precios de las casas son del doble en promedio por zona con respecto a los apartamentos. Sin embargo, viendo los precios por metro cuadrado, resulta se que las casas poseen una mayor área construida y que si bien los precios llegan a ser de hasta el doble, los apartamentos tienen, en todas las zonas sin excepción, mayores precios por metro cuadrado.
  • Realizando un análisis de precio x m2 promedio por estrato, se encuentra que, independientemente de la zona y el tipo de vivienda, en los estratos 3 y 4, los valores se comportan muy similar.
  • Mientras que para los estratos 5 y 6 se comienzan a encontrar datos curisioso, entre ellos que en la zona oriente el precio x m2 de una casa estrato 5 es menor que para los estratos 3 y 4. Además, para esta misma zona se puede evidenciar que el precio x m2 de los apartamentos de estrato 6 son los más altos en promedio de todas las categorizaciones usadas.

6. Conclusiones

El análisis de viviendas en Cali revela una serie de hallazgos importantes. En cuanto a la oferta, se observa que hay una mayor cantidad de apartamentos disponibles en el mercado que de casas. Sin embargo, las casas tienen un precio por metro cuadrado menor que los apartamentos, con una mediana inferior a 2,5 millones de pesos frente a una superior a 2,5 millones de pesos para los apartamentos.

En cuanto a las características, las casas tienden a tener un área construida mayor que los apartamentos, llegando a ser hasta el doble o triple en algunas zonas. Además, las casas tienen un promedio de baños superior al de los apartamentos, con valores que alcanzan los 4,2 baños en las zonas sur y oeste.

En términos de precios por zona, las casas son más costosas que los apartamentos, con un promedio del doble. Sin embargo, al analizar los precios por metro cuadrado, se observa que los apartamentos tienen un valor superior en todas las zonas, lo que indica que la mayor área construida de las casas compensa en parte su precio más elevado.

Al analizar el comportamiento del precio por metro cuadrado en diferentes estratos, se observa que en los estratos 3 y 4, los valores son similares para casas y apartamentos, independientemente de la zona. Sin embargo, en los estratos 5 y 6 se encuentran algunos datos curiosos. Por ejemplo, en la zona oriente, el precio por metro cuadrado de una casa estrato 5 es menor que el de los estratos 3 y 4. Además, en la misma zona, los apartamentos de estrato 6 tienen el precio por metro cuadrado más alto de todas las categorías.

6.1 Recomendaciones:

  • Es fundamental evaluar el precio por metro cuadrado para comparar precios de forma más precisa.
  • Se recomienda prestar atención al comportamiento del precio por metro cuadrado en diferentes estratos y zonas.

6.2 Limitaciones:

  • Es importante tener en cuenta que algunos puntos de este análisis se podrían ampliar si hubiese una mayor completitud de los datos estudiados.

6.3 Posibles próximos pasos:

  • Sería útil estudiar la evolución del precio de las viviendas en el tiempo.
  • Se podría llegar a encontrar relación entre el precio de las viviendas y otros factores ampliando la base de datos.