Profesor: Jenyfer Portilla Yela
Curso: Métodos Estadísticos para Toma de Decisiones

1 Introducción

En este informe, se abordaron dos solicitudes de compra de viviendas para una compañía internacional que desea establecer a dos de sus empleados y sus familias en Cali. Se Aplica on técnicas de modelación estadística para evaluar las características de las viviendas y ofrecer recomendaciones fundamentadas. A lo largo del análisis, se utilizó un modelo de regresión lineal múltiple para predecir los precios de las viviendas en función de varias características relevantes, aplicando las mejores prácticas en ciencia de datos para asegurar la validez y la fiabilidad de los resultados.

2 Análisis Exploratorio de Datos (EDA)

En esta sección se realizó un análisis exploratorio detallado de los datos disponibles para comprender mejor su estructura y características. Se identificaron distribuciones, valores atípicos y se exploraron relaciones iniciales entre las variables.

2.1 Carga de los Datos

Se cargó el dataset especificado para esta actividad.

# Instala y Carga las librerías necesarias
required_packages <- c("dplyr", "ggplot2", "plotly", "leaflet", "paqueteMODELOS")

# Función para instalar paquetes si no están instalados
install_if_missing <- function(packages) {
  new_packages <- packages[!(packages %in% installed.packages()[,"Package"])]
  if(length(new_packages)) install.packages(new_packages)
}

# Instalar paquetes si es necesario
install_if_missing(required_packages)

# Carga los paquetes
lapply(required_packages, require, character.only = TRUE)

# Carga los datos
data("vivienda")

2.1.1 Descripción inicial de los Datos

# Mostrar una visión general de los 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

Los datos contienen 13 variables, incluyendo identificadores, características geográficas (zona, barrio, longitud, latitud), características estructurales (piso, estrato, área construida, número de parqueaderos, baños, habitaciones), tipo de vivienda y precio (preciom). Se detectaron valores faltantes en las variables estrato, preciom, areaconst, parqueaderos, banios, habitaciones, piso, longitud, y latitud. En particular, hay una cantidad significativa de valores faltantes en parqueaderos (1605 valores faltantes), lo cual requiere atención en el proceso de limpieza de datos.

# Visualización inicial de la distribución de precios
ggplot(vivienda, aes(x = preciom)) +
  geom_histogram(binwidth = 50, fill = "blue", color = "black") +
  labs(title = "Distribucion del Precio de las Viviendas",
       x = "Precio en millones de pesos",
       y = "Frecuencia") +
  theme_minimal()

El histograma indica una distribución sesgada a la derecha, donde la mayoría de las viviendas tienen precios menores a 500 millones de pesos, con algunos valores que alcanzan hasta 2000 millones. Esto sugiere una alta concentración de propiedades más económicas, con menos viviendas en el rango de precios más altos. La presencia de propiedades con precios elevados puede indicar la existencia de valores atípicos, lo cual podría afectar el análisis estadístico y debe ser considerado en los siguientes pasos del análisis.

Esta distribución sesgada, puede beneficiarse de una transformación logaritmica que la asemejaría mas a una normal, que potencialmente mejopraría el desempeño de un predictor lineal, esta transformación se realizará en una siguiente sección.

2.2 Limpieza de registros con valores nulos

En esta subsección, se identificaron y eliminaron registros con valores faltantes en los datos. También Esta limpieza asegura que el análisis subsiguiente se realice solo con datos completos y consistentes.

No se eliminaron registros con valores nulos en pioso ya que son numerosos y no se usarán en el modelado ya que no están entre las variables de las dos solicitudes.

# Cargar librería necesaria para crear tablas
library(knitr)
library(dplyr)

# Identificar valores faltantes antes de la limpieza
faltantes_antes <- sapply(vivienda, function(x) sum(is.na(x)))
faltantes_antes_tabla <- data.frame(Variable = names(faltantes_antes), Faltantes = faltantes_antes)

# Mostrar tabla de valores faltantes antes de la limpieza
kable(faltantes_antes_tabla, caption = "Valores Faltantes por Variable Antes de la Limpieza")
Valores Faltantes por Variable Antes de la Limpieza
Variable Faltantes
id id 3
zona zona 3
piso piso 2638
estrato estrato 3
preciom preciom 2
areaconst areaconst 3
parqueaderos parqueaderos 1605
banios banios 3
habitaciones habitaciones 3
tipo tipo 3
barrio barrio 3
longitud longitud 3
latitud latitud 3
# Contar el número de registros antes de la limpieza
registros_antes <- nrow(vivienda)

# Eliminar registros con valores faltantes en cualquier columna excepto 'piso'
vivienda <- vivienda %>%
  filter(across(-piso, ~ !is.na(.)))

# Contar el número de registros después de la limpieza
registros_despues <- nrow(vivienda)

# Identificar valores faltantes después de la limpieza
faltantes_despues <- sapply(vivienda, function(x) sum(is.na(x)))
faltantes_despues_tabla <- data.frame(Variable = names(faltantes_despues), Faltantes = faltantes_despues)

# Mostrar tabla de valores faltantes después de la limpieza
kable(faltantes_despues_tabla, caption = "Valores Faltantes por Variable Después de la Limpieza")
Valores Faltantes por Variable Después de la Limpieza
Variable Faltantes
id id 0
zona zona 0
piso piso 1909
estrato estrato 0
preciom preciom 0
areaconst areaconst 0
parqueaderos parqueaderos 0
banios banios 0
habitaciones habitaciones 0
tipo tipo 0
barrio barrio 0
longitud longitud 0
latitud latitud 0
# Mostrar el número de registros eliminados y los registros restantes
registros_eliminados <- registros_antes - registros_despues
cat("Número de registros eliminados:", registros_eliminados, "\n")
## Número de registros eliminados: 1605
cat("Número de registros restantes:", registros_despues, "\n")
## Número de registros restantes: 6717

Después de Aplica el proceso de limpieza, se eliminaron un total de 3,514 registros que contenían valores faltantes. Esto representa una cantidad significativa de los datos originales, indicando que había muchas entradas incompletas que no eran útiles para el análisis. Los registros restantes, que ascienden a 4,808, ahora están completos y libres de valores faltantes, lo que proporciona un conjunto de datos más confiable y consistente para los análisis subsiguientes. Esta limpieza asegura que el modelo que se desarrolle no se verá afectado por datos incompletos, mejorando la calidad y precisión de los resultados esperados.

2.3 Transformación Logarítmica del Precio

En esta subsección, se aplicó una transformación logarítmica al precio de las viviendas (preciom) para normalizar la distribución de esta variable y mejorar la calidad del análisis y el ajuste del modelo. La transformación logarítmica es especialmente útil cuando se observa una distribución sesgada con una cola larga hacia valores altos, como es el caso aquí. Esta transformación ayuda a estabilizar la varianza y a aproximar una distribución normal, lo que es crucial para los supuestos del modelo de regresión lineal.

# Aplicar la transformación logarítmica al precio
vivienda$log_preciom <- log(vivienda$preciom)

# Verificar la distribución después de la transformación logarítmica
hist(vivienda$log_preciom, 
     main = "Distribucion Logaritmica del Precio de las Viviendas", 
     xlab = "Logaritmo del Precio (millones de pesos)", 
     breaks = 30, 
     col = "lightblue", 
     border = "black")

2.4 Análisis Exploratorio de Datos

En esta sección, se realizó un análisis exploratorio para comprender mejor la relación entre la variable respuesta (precio de la vivienda) y otras variables predictoras como el área construida, estrato, número de baños, número de habitaciones y zona de ubicación de la vivienda. Se utilizaron gráficos para visualizar estas relaciones y obtener información preliminar sobre cómo estas variables pueden influir en el precio de la vivienda.

# Sección 2.3: Análisis Exploratorio de Datos

# Carga librerías necesarias para la visualización
library(ggplot2)
library(plotly)

# Grafico de correlacion entre precio y área construida
grafico_area <- ggplot(vivienda, aes(x = areaconst, y = log_preciom)) +
  geom_point(color = "blue") +
  geom_smooth(method = "lm", color = "red") +
  labs(title = "Relacion entre Area Construida y Log Precio de la Vivienda",
       x = "Area Construida (m2)",
       y = "Precio log(millones de pesos)")

# Gráfico de correlacion entre precio y estrato
grafico_estrato <- ggplot(vivienda, aes(x = factor(estrato), y = log_preciom)) +
  geom_boxplot(fill = "lightblue") +
  labs(title = "Relacion entre Estrato y Log Precio de la Vivienda",
       x = "Estrato",
       y = "Precio log(millones de pesos)")

# Gráfico de correlación entre precio y número de baños
grafico_banios <- ggplot(vivienda, aes(x = banios, y = log_preciom)) +
  geom_point(color = "green") +
  geom_smooth(method = "lm", color = "red") +
  labs(title = "Relacion entre Numero de Banios y Log Precio de la Vivienda",
       x = "Numero de Banos",
       y = "Precio log(millones de pesos)")

# Grafico de correlacion entre precio y número de habitaciones
grafico_habitaciones <- ggplot(vivienda, aes(x = habitaciones, y = log_preciom)) +
  geom_point(color = "purple") +
  geom_smooth(method = "lm", color = "red") +
  labs(title = "Relacion entre Numero de Habitaciones y Log Precio de la Vivienda",
       x = "Numero de Habitaciones",
       y = "Precio log(millones de pesos)")

# Ensure the correct encoding for data and plot labels
vivienda$zona <- iconv(vivienda$zona, from = "UTF-8", to = "ASCII//TRANSLIT")


# Grafico de correlacion entre precio y zona
grafico_zona <- ggplot(vivienda, aes(x = zona, y = log_preciom)) +
  geom_boxplot(fill = "orange") +
  labs(title = "Relacion entre Zona y Log Precio de la Vivienda",
       x = "Zona",
       y = "Precio (millones de pesos)")

# Convertir gráficos a objetos interactivos usando plotly
grafico_area_interactivo <- ggplotly(grafico_area)
grafico_estrato_interactivo <- ggplotly(grafico_estrato)
grafico_banios_interactivo <- ggplotly(grafico_banios)
grafico_habitaciones_interactivo <- ggplotly(grafico_habitaciones)
grafico_zona_interactivo <- ggplotly(grafico_zona)

# Mostrar gráficos interactivos
grafico_area_interactivo

El gráfico muestra una relación positiva clara y significativa entre el área construida y el precio de la vivienda. A medida que aumenta el área construida, también lo hace el precio, lo que sugiere que el tamaño de la vivienda es un factor determinante en su valor de mercado. La línea de regresión lineal, que se ajusta bien a la nube de puntos, respalda esta relación, indicando que el área construida podría ser una variable predictora clave para modelar el precio de las viviendas

grafico_estrato_interactivo

El gráfico de cajas muestra una tendencia creciente en los precios de las viviendas a medida que se incrementa el estrato socioeconómico. Los estratos más altos (5 y 6) tienen precios medianos significativamente mayores en comparación con los estratos más bajos (3 y 4). Además, se observa una mayor dispersión de precios y más valores atípicos en los estratos más altos, lo que indica una mayor variabilidad en los precios dentro de estos grupos. Esta relación sugiere que el estrato socioeconómico es un factor importante que influye en el precio de la vivienda.

En la siguiente sección se realizará una limpieza de outliers por estrato solo del training dataset, justo después de la división del dataset en training y test, para eliminar valores que puedan bajar el desempeño del predictor lineal, ya que el estratoes una variable muy importante en el precio, pero la presencia de outliers para cada estrato, puede disminuír la forma como aprovcvechamos esta importancia para la predicción.

grafico_banios_interactivo

El gráfico muestra una clara relación positiva entre el número de baños y el precio de la vivienda. A medida que aumenta el número de baños, también se observa un incremento en el precio. La línea de regresión lineal refuerza esta tendencia, sugiriendo que la cantidad de baños es un factor que podría influir significativamente en el valor de la vivienda. Este patrón es consistente con la idea de que más baños suelen estar asociados con viviendas más grandes y lujosas, que suelen tener un mayor precio.

grafico_habitaciones_interactivo

El gráfico indica una relación positiva entre el número de habitaciones y el precio de la vivienda, aunque esta relación es más moderada en comparación con otras variables como el área construida o el número de baños. La línea de regresión lineal sugiere que, en general, a medida que aumenta el número de habitaciones, también lo hace el precio de la vivienda. Sin embargo, la dispersión de puntos es considerable, lo que indica que otros factores podrían estar influyendo en el precio, y que el número de habitaciones, aunque relevante, no es el único determinante del precio de la vivienda.

grafico_zona_interactivo

El gráfico de cajas muestra diferencias notables en los precios de las viviendas según la zona de ubicación. La Zona Oeste destaca con precios significativamente más altos y una mayor variabilidad en comparación con las demás zonas, sugiriendo que es una de las zonas más caras y posiblemente más deseadas. Las zonas Centro, Oriente, y Sur muestran precios medianos más bajos y menos variabilidad, indicando mercados más estables y económicos. Estos resultados sugieren que la ubicación geográfica es un factor crítico que influye en el precio de la vivienda, reflejando tanto la demanda como el nivel socioeconómico de las distintas áreas de la ciudad.

2.5 Segmentación por Coordenadas

En esta subsección, se realizó un análisis de la distribución geográfica de las viviendas utilizando las coordenadas de latitud y longitud. Este análisis permitió verificar la ubicación de las propiedades en relación con las zonas norte y sur de la ciudad, asegurando que los datos geográficos sean consistentes con las etiquetas de zona en el conjunto de datos.

# Sección 2.3: Segmentación por Coordenadas

# Carga librerías necesarias para visualización en mapas
library(leaflet)
library(dplyr)

# Visualización de las propiedades en un mapa interactivo utilizando leaflet
leaflet(vivienda) %>%
  addTiles() %>%
  addCircles(lng = ~longitud, lat = ~latitud, popup = ~paste("Zona:", zona, "<br>", "Precio:", preciom, "millones"),
             color = ~ifelse(zona == "Zona Norte", "blue", "red"),
             radius = 50, opacity = 1, fillOpacity = 0.5) %>%
  addLegend(position = "bottomright", colors = c("blue", "red"),
            labels = c("Zona Norte", "Otras Zonas"),
            title = "Leyenda de Zonas")
# Resumen de la distribución geográfica
zona_norte_count <- sum(vivienda$zona == "Zona Norte")
otras_zonas_count <- sum(vivienda$zona != "Zona Norte")

cat("Número de propiedades en la Zona Norte:", zona_norte_count, "\n")
## Número de propiedades en la Zona Norte: 1287
cat("Número de propiedades en otras zonas:", otras_zonas_count, "\n")
## Número de propiedades en otras zonas: 5430

El mapa interactivo muestra que hay inconsistencias en la asignación de zonas en el conjunto de datos. Aunque se esperaba que las propiedades etiquetadas como “Zona Norte” se agruparan claramente en el norte de la ciudad y las otras zonas en áreas diferentes, se observa que algunas propiedades etiquetadas como “Zona Norte” están ubicadas en el sur y viceversa. Estas discrepancias pueden deberse a errores en la categorización de zonas en el conjunto de datos original.

2.6 Corrección de Segmentación por Coordenadas usando Clustering

Se utilizó el método de clustering K-means para determinar un límite confiable entre la “Zona Norte” y la “Zona Sur” basándose en la distribución geográfica de las propiedades.

# Carga librerías necesarias
library(dplyr)
library(leaflet)
library(stats) # Para kmeans

# Filtrar datos para clustering (usar solo coordenadas)
# Eliminamos posibles valores NA antes de Aplica  clustering
datos_cluster <- vivienda %>%
  select(latitud, longitud) %>%
  na.omit()

# Aplica  K-means clustering con 2 clusters
set.seed(123) # Para reproducibilidad
clustering_result <- kmeans(datos_cluster, centers = 2)

# Mapear los resultados de clustering a los datos originales de forma segura
vivienda$zona_cluster <- NA
vivienda$zona_cluster[match(rownames(datos_cluster), rownames(vivienda))] <- clustering_result$cluster

# Calcular latitud media de cada cluster para determinar cuál es "Zona Norte" y cuál es "Zona Sur"
cluster_1_center <- mean(vivienda$latitud[vivienda$zona_cluster == 1], na.rm = TRUE)
cluster_2_center <- mean(vivienda$latitud[vivienda$zona_cluster == 2], na.rm = TRUE)

if (cluster_1_center > cluster_2_center) {
  zona_norte <- 1
  zona_sur <- 2
} else {
  zona_norte <- 2
  zona_sur <- 1
}

# Asignar zonas basadas en los clusters
vivienda$zona_coord <- ifelse(vivienda$zona_cluster == zona_norte, "Zona Norte", "Zona Sur")

# Verificar si hay valores NA en zona_coord y manejar cualquier inconsistencia
vivienda$zona_coord[is.na(vivienda$zona_coord)] <- "Zona Desconocida"  # Ajuste opcional para manejar cualquier caso especial

# Visualizar las propiedades con la nueva clasificación de zona en un mapa interactivo
leaflet(vivienda) %>%
  addTiles() %>%
  addCircles(lng = ~longitud, lat = ~latitud, popup = ~paste("Zona:", zona_coord, "<br>", "Precio:", preciom, "millones"),
             color = ~ifelse(zona_coord == "Zona Norte", "blue", "red"),
             radius = 50, opacity = 1, fillOpacity = 0.5) %>%
  addLegend(position = "bottomright", colors = c("blue", "red"),
            labels = c("Zona Norte", "Zona Sur"),
            title = "Leyenda de Zonas")
# Resumen de la nueva distribución geográfica
cluster_norte_count <- sum(vivienda$zona_coord == "Zona Norte", na.rm = TRUE)
cluster_sur_count <- sum(vivienda$zona_coord == "Zona Sur", na.rm = TRUE)

cat("Número de propiedades en la Zona Norte:", cluster_norte_count, "\n")
## Número de propiedades en la Zona Norte: 3134
cat("Número de propiedades en la Zona Sur:", cluster_sur_count, "\n")
## Número de propiedades en la Zona Sur: 3583

El mapa actualizado muestra claramente la división entre la “Zona Norte” (en azul) y las “Otras Zonas” (en rojo) utilizando el método de clustering K-means. Esta segmentación objetiva basada en la posición geográfica permite una mejor identificación de las propiedades, asegurando que las zonas estén correctamente categorizadas y proporcionando una base más sólida para análisis posteriores.

3 Preparación y Selección de Variables

En esta sección, se seleccionaron y prepararon las variables que son relevantes para las solicitudes específicas de las viviendas. Se aseguraron de que las transformaciones de los datos, como la normalización y codificación de variables categóricas, se Aplica an adecuadamente para garantizar que los modelos estadísticos puedan trabajar con la información.

3.1 Selección de Variables

Se seleccionaron las variables necesarias para responder a las solicitudes específicas para las dos viviendas, que incluyen características como el tipo de vivienda, área construida, número de parqueaderos, baños, habitaciones, estrato socioeconómico, y zona de ubicación.

# Carga librerías necesarias
library(dplyr)

# Selección de variables necesarias para el análisis
variables_seleccionadas <- vivienda %>%
  select(log_preciom, areaconst, estrato, banios, habitaciones, parqueaderos, zona_coord, tipo)

# Eliminar filas con valores NA en las variables seleccionadas
variables_seleccionadas <- na.omit(variables_seleccionadas)

# Mostrar las primeras filas del conjunto de datos seleccionados
head(variables_seleccionadas)
## # A tibble: 6 × 8
##   log_preciom areaconst estrato banios habitaciones parqueaderos zona_coord
##         <dbl>     <dbl>   <dbl>  <dbl>        <dbl>        <dbl> <chr>     
## 1        5.52        70       3      3            6            1 Zona Norte
## 2        5.77       120       3      2            3            1 Zona Norte
## 3        5.86       220       3      2            4            2 Zona Norte
## 4        5.99       280       4      5            3            3 Zona Norte
## 5        5.56        90       5      2            3            1 Zona Norte
## 6        5.48        87       5      3            3            1 Zona Sur  
## # ℹ 1 more variable: tipo <chr>

3.2 División de los Datos en Conjuntos de Entrenamiento y Validación

Para evaluar la robustez del modelo de regresión lineal múltiple y evitar sobreajuste, se realizó una división de los datos en conjuntos de entrenamiento y validación, utilizando un 70% de los datos para entrenamiento y el 30% restante para validación. Aseguramos que los datos no contengan valores faltantes antes de la partición.

# Carga la librería 'caret' para la división
library(caret)

# Revisar si hay valores faltantes en los datos seleccionados
faltantes_final <- sapply(variables_seleccionadas, function(x) sum(is.na(x)))
#print(faltantes_final)

# Dividir los datos en conjunto de entrenamiento y validación (70/30)
set.seed(123)
training_index <- createDataPartition(variables_seleccionadas$log_preciom, p = 0.7, list = FALSE)
train_data <- variables_seleccionadas[training_index, ]
validation_data <- variables_seleccionadas[-training_index, ]

# Mostrar el número de registros en cada conjunto
num_train <- nrow(train_data)
num_validation <- nrow(validation_data)

cat("Número de registros en el conjunto de entrenamiento:", num_train, "\n")
## Número de registros en el conjunto de entrenamiento: 4704
cat("Número de registros en el conjunto de validación:", num_validation, "\n")
## Número de registros en el conjunto de validación: 2013

3.3 Limpieza en training dataset de outliers por estrato

En esta subsección, se identificaron y eliminaron los outliers en el precio de las viviendas basados en la categoría de estrato. Este enfoque asegura que se respeten las características específicas de cada estrato socioeconómico y que los valores extremos que pueden influir desproporcionadamente en los resultados del modelo sean tratados adecuadamente.

# Calcular los valores IQR y los límites de outliers para cada estrato en el conjunto de entrenamiento
train_data <- train_data %>%
  group_by(estrato) %>%
  mutate(Q1 = quantile(log_preciom, 0.25, na.rm = TRUE),
         Q3 = quantile(log_preciom, 0.75, na.rm = TRUE),
         IQR = Q3 - Q1,
         lower_bound = Q1 - 1.5 * IQR,
         upper_bound = Q3 + 1.5 * IQR) %>%
  ungroup()

# Contar el número de registros antes de la eliminación de outliers
num_registros_antes <- nrow(train_data)

# Filtrar para eliminar los outliers fuera de los límites definidos en el conjunto de entrenamiento
train_data <- train_data %>%
  filter(log_preciom >= lower_bound & log_preciom <= upper_bound)

# Contar el número de registros después de la eliminación de outliers
num_registros_despues <- nrow(train_data)

# Calcular el número de outliers eliminados
num_outliers_eliminados <- num_registros_antes - num_registros_despues

# Mostrar los resultados
cat("Número de outliers eliminados en el conjunto de entrenamiento:", num_outliers_eliminados, "\n")
## Número de outliers eliminados en el conjunto de entrenamiento: 64
cat("Número total de registros en el conjunto de entrenamiento después de eliminar outliers:", num_registros_despues, "\n")
## Número total de registros en el conjunto de entrenamiento después de eliminar outliers: 4640
# Mostrar un boxplot para verificar la eliminación de outliers
boxplot(log_preciom ~ estrato, data = train_data, col = "lightblue",
        main = "Relación entre Estrato y Logaritmo del Precio de la Vivienda (Sin Outliers)",
        ylab = "Logaritmo del Precio (millones de pesos)", xlab = "Estrato")

3.4 Manejo de Variables Categóricas

En esta subsección, se abordó la codificación de variables categóricas para asegurar que puedan ser utilizadas en el modelo de regresión lineal múltiple. Las variables categóricas relevantes incluyen estrato y zona_coord. Se utilizó la técnica de codificación one-hot encoding para estas variables, permitiendo que cada categoría se represente como una columna binaria separada.

Razonamiento para el Tratamiento de Variables categóricas:

  • Estrato: Es una variable categórica ordinal que representa el nivel socioeconómico de la vivienda. Aunque es ordinal (tiene un orden), se convierte en una variable categórica mediante one-hot encoding para evitar imponer una relación lineal implícita entre los estratos. Esta codificación permite que el modelo trate cada estrato como una categoría distinta sin suponer que el salto entre un estrato y otro es uniforme o lineal.

  • Zona: zona_coord es una variable categórica que indica la ubicación geográfica de la vivienda (Norte o Sur). Como es una variable nominal sin orden inherente, se usa one-hot encoding para que el modelo no asuma ninguna relación de orden entre las zonas. Baños, Habitaciones y Parqueaderos:

Razonamiento para el Tratamiento de Variables discretas ordinales:

Estas variables son numéricas discretas. Aunque tienen valores enteros y podrían parecer categóricas a primera vista, se consideran variables numéricas porque el incremento en su valor tiene un significado cuantitativo directo y un impacto lineal en la respuesta (precio de la vivienda).

  • Baños: Un aumento en el número de baños suele corresponder a un aumento en la comodidad y funcionalidad de una vivienda, lo cual afecta directamente su valor. El efecto de pasar de 1 a 2 baños no es solo una diferencia categórica, sino que representa un incremento en el espacio y la funcionalidad.

  • Habitaciones: Similar a los baños, un mayor número de habitaciones típicamente se traduce en un mayor valor de la propiedad. Aquí también, el incremento es cuantitativo: más habitaciones generalmente significa más espacio habitable y mayor valor. Parqueaderos: El número de parqueaderos influye directamente en el valor de la vivienda, ya que tener más espacio para estacionamiento es un atributo valioso. Cada incremento en el número de parqueaderos agrega un valor cuantitativo.

# Codificar variables categóricas utilizando model.matrix()
               variables_categorizadas <- variables_seleccionadas %>%
  mutate(across(c(estrato, zona_coord), as.factor)) %>%                                                               
  model.matrix(~ . - 1, data = .) %>%
  as.data.frame()
colnames(variables_categorizadas)[colnames(variables_categorizadas) == "zona_coordZona Sur"] <- "zona_coordZona_Sur"
# Mostrar las primeras filas del conjunto de datos categorizado
head(variables_categorizadas)
##   log_preciom areaconst estrato3 estrato4 estrato5 estrato6 banios habitaciones
## 1    5.521461        70        1        0        0        0      3            6
## 2    5.768321       120        1        0        0        0      2            3
## 3    5.857933       220        1        0        0        0      2            4
## 4    5.991465       280        0        1        0        0      5            3
## 5    5.560682        90        0        0        1        0      2            3
## 6    5.480639        87        0        0        1        0      3            3
##   parqueaderos zona_coordZona_Sur tipoCasa
## 1            1                  0        1
## 2            1                  0        1
## 3            2                  0        1
## 4            3                  0        1
## 5            1                  0        0
## 6            1                  1        0

3.5 Normalización de Datos

En esta sección, se realizó la normalización de las variables numéricas seleccionadas para mejorar la calidad de los modelos de regresión lineal y asegurar que los resultados sean más interpretables y precisos. La normalización es una práctica común en el análisis de datos que ayuda a reducir el sesgo y mejora la comparabilidad de las variables.

3.5.1 Justificación para la Normalización Min-Max

La elección de la normalización, específicamente la normalización min-max, se basa en la naturaleza de la distribución del precio de las viviendas observada en el análisis exploratorio de datos. La distribución del precio de las viviendas no sigue una distribución normal, sino que está sesgada a la derecha con una cola larga, indicando la presencia de valores extremadamente altos. La mayoría de las viviendas tienen precios bajos (por debajo de 500 millones de pesos), mientras que unas pocas tienen precios mucho más altos, lo que genera una distribución asimétrica.

A pesar de que se realizó la treansformación Logaritmica y se normalizó un poco la distribución, esta presenta una cola ancha en la derecha y por tanto pro precauición, se usará que normalización min-max es adecuada para este tipo de distribución no normal porque ajusta todos los valores de una variable al mismo rango (0 a 1), reduciendo la influencia de los valores extremos y permitiendo una mejor comparación entre diferentes variables.

3.5.2 Implementación de la Normalización

La normalización se aplicó únicamente al conjunto de entrenamiento para evitar el sobreajuste y asegurar que el modelo generalice adecuadamente. Posteriormente, los mismos parámetros de normalización (mínimos y máximos) se aplicaron al conjunto de validación para mantener la coherencia en las transformaciones.

# Carga librería necesaria para la normalización
library(caret)

# Define función de normalización min-max
normalizar <- function(x) {
  return((x - min(x)) / (max(x) - min(x)))
}

# Aplica normalización a las variables numéricas del conjunto de entrenamiento
variables_numericas <- c("log_preciom", "areaconst", "banios", "habitaciones", "parqueaderos")
train_data_normalizado <- train_data
train_data_normalizado[variables_numericas] <- lapply(train_data[variables_numericas], normalizar)

# Aplica los mismos parámetros de normalización al conjunto de validación
minimos <- sapply(train_data[variables_numericas], min)
maximos <- sapply(train_data[variables_numericas], max)

validation_data_normalizado <- validation_data
validation_data_normalizado[variables_numericas] <- as.data.frame(scale(validation_data[variables_numericas], center = minimos, scale = maximos - minimos))

# Mostrar las primeras filas de los datos normalizados
colnames(train_data_normalizado)[colnames(train_data_normalizado) == "zona_coordZona Sur"] <- "zona_coordZona_Sur"
colnames(validation_data_normalizado)[colnames(validation_data_normalizado) == "zona_coordZona Sur"] <- "zona_coordZona_Sur"
head(train_data_normalizado)
## # A tibble: 6 × 13
##   log_preciom areaconst estrato banios habitaciones parqueaderos zona_coord
##         <dbl>     <dbl>   <dbl>  <dbl>        <dbl>        <dbl> <chr>     
## 1       0.416   0.0176        3    0.3          0.6        0     Zona Norte
## 2       0.486   0.0469        3    0.2          0.3        0     Zona Norte
## 3       0.549   0.141         4    0.5          0.3        0.222 Zona Norte
## 4       0.427   0.0293        5    0.2          0.3        0     Zona Norte
## 5       0.404   0.0276        5    0.3          0.3        0     Zona Sur  
## 6       0.379   0.00704       4    0.2          0.3        0.111 Zona Norte
## # ℹ 6 more variables: tipo <chr>, Q1 <dbl>, Q3 <dbl>, IQR <dbl>,
## #   lower_bound <dbl>, upper_bound <dbl>
head(validation_data_normalizado)
## # A tibble: 6 × 8
##   log_preciom areaconst estrato banios habitaciones parqueaderos zona_coord
##         <dbl>     <dbl>   <dbl>  <dbl>        <dbl>        <dbl> <chr>     
## 1       0.511    0.106        3    0.2          0.4        0.111 Zona Norte
## 2       0.486    0.0645       5    0.4          0.6        0.111 Zona Norte
## 3       0.665    0.0704       4    0.4          0.5        0     Zona Norte
## 4       0.314    0.0235       3    0.2          0.3        0     Zona Norte
## 5       0.583    0.0370       6    0.3          0.4        0.111 Zona Norte
## 6       0.297    0.0123       4    0.2          0.2        0     Zona Norte
## # ℹ 1 more variable: tipo <chr>

4 Construcción y Evaluación del Modelo de Regresión Lineal Múltiple

En esta sección, se realizó la estimación y ajuste de un modelo de regresión lineal múltiple utilizando las variables seleccionadas en el análisis previo. Se discuten los resultados obtenidos, la robustez del modelo, y se interpretan los coeficientes estimados para evaluar su significancia estadística.

4.1 Formulación del Modelo

Se especificó matemáticamente el modelo de regresión lineal múltiple utilizando la notación matricial y el método de Mínimos Cuadrados Ordinarios (MCO). Este modelo se utilizó para predecir el precio de las viviendas en función de las variables seleccionadas: área construida, número de cuartos, número de parqueaderos, número de baños y la ubicación derivada del clustering (zona_coord). Se utilizó one-hot encoding para estrato y zona_coord, permitiendo que cada categoría se represente como una columna binaria separada.

# Usar las variables ya codificadas en `variables_categorizadas`
# Asegúrate de que `variables_categorizadas` incluye las variables adecuadas
# y que los datos están limpios (sin NA) después de la codificación

# Verificación de valores faltantes
variables_categorizadas <- variables_categorizadas %>%
  filter(!is.na(log_preciom))

# Construcción del modelo de regresión lineal múltiple usando las variables categorizadas
modelo <- lm(log_preciom ~ areaconst + banios + habitaciones + parqueaderos + estrato3 + estrato4 + estrato5 + estrato6 + tipoCasa+ `zona_coordZona_Sur`, 
             data = variables_categorizadas)

# Resumen del modelo para ver los coeficientes y su significancia
summary(modelo)
## 
## Call:
## lm(formula = log_preciom ~ areaconst + banios + habitaciones + 
##     parqueaderos + estrato3 + estrato4 + estrato5 + estrato6 + 
##     tipoCasa + zona_coordZona_Sur, data = variables_categorizadas)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.72322 -0.17964 -0.00312  0.16620  1.41512 
## 
## Coefficients: (1 not defined because of singularities)
##                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         5.637e+00  1.555e-02 362.435   <2e-16 ***
## areaconst           1.102e-03  3.713e-05  29.687   <2e-16 ***
## banios              1.182e-01  4.211e-03  28.079   <2e-16 ***
## habitaciones       -8.481e-03  3.706e-03  -2.288   0.0222 *  
## parqueaderos        9.010e-02  4.127e-03  21.833   <2e-16 ***
## estrato3           -9.012e-01  1.563e-02 -57.672   <2e-16 ***
## estrato4           -6.115e-01  1.144e-02 -53.446   <2e-16 ***
## estrato5           -3.830e-01  9.672e-03 -39.599   <2e-16 ***
## estrato6                   NA         NA      NA       NA    
## tipoCasa            8.766e-02  9.686e-03   9.051   <2e-16 ***
## zona_coordZona_Sur -1.111e-01  7.085e-03 -15.680   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2798 on 6707 degrees of freedom
## Multiple R-squared:  0.8019, Adjusted R-squared:  0.8017 
## F-statistic:  3017 on 9 and 6707 DF,  p-value: < 2.2e-16

El modelo de regresión lineal múltiple con log_preciom como variable dependiente mostró un buen ajuste con un R-cuadrado ajustado de 0.8019, indicando que aproximadamente el 80% de la variabilidad en los precios transformados logarítmicamente se explica por las variables predictoras. Los coeficientes para areaconst, banios, parqueaderos, y los niveles de estrato fueron significativos (p < 0.001), sugiriendo una relación fuerte con el precio de la vivienda. La variable habitaciones no fue significativa, indicando que su efecto sobre el precio no es claro en este modelo.

4.2 Validación Cruzada

Se utilizó la validación cruzada para evaluar la robustez del modelo de regresión lineal múltiple. La validación cruzada ayuda a garantizar que el modelo generalice bien a nuevos datos y no se ajuste demasiado a los datos de entrenamiento.

# Asegurar que el paquete caret esté instalado y cargado para la validación cruzada
if (!require(caret)) {
  install.packages("caret")
  library(caret)
}

# Configuración para la validación cruzada
set.seed(123)  # Asegurar reproducibilidad
train_control <- trainControl(method = "cv", number = 10)

# Entrenar el modelo utilizando validación cruzada
modelo_cv <- train(log_preciom  ~ areaconst + banios + habitaciones + parqueaderos + estrato3 + estrato4 + estrato5 + estrato6 + tipoCasa + `zona_coordZona_Sur`,
                   data = variables_categorizadas,
                   method = "lm",
                   trControl = train_control)

# Mostrar los resultados de la validación cruzada
print(modelo_cv)
## Linear Regression 
## 
## 6717 samples
##   10 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold) 
## Summary of sample sizes: 6044, 6046, 6045, 6046, 6045, 6046, ... 
## Resampling results:
## 
##   RMSE       Rsquared   MAE      
##   0.2802414  0.8013649  0.2154804
## 
## Tuning parameter 'intercept' was held constant at a value of TRUE

Los resultados de la validación cruzada muestran un RMSE de 0.28 y un R-cuadrado de 0.801, lo que sugiere que el modelo tiene un buen nivel de precisión en la predicción de los precios transformados logarítmicamente. El MAE de 0.215 indica que, en promedio, las predicciones del modelo difieren del valor real(log) en aproximadamente un 21.5%, lo que demuestra que el modelo es relativamente preciso en sus estimaciones.

Para convertir el MAE de la escala logarítmica (log_preciom) a la escala original de precios (preciom), se puede usar la exponencial del MAE multiplicado por la diferencia entre los valores máximo y mínimo usados en la normalización.

# Valores mínimo y máximo reales de precios originales (antes de la normalización)
# Valores mínimo y máximo originales de precios (antes de la normalización)
minimo_preciom <- minimos["log_preciom"]
maximo_preciom <- maximos["log_preciom"]

# MAE obtenido de la validación cruzada en la escala logarítmica
mae_log <- 0.2154804  # MAE de log_preciom obtenido de la validación cruzada

# Primero, desnormalizar el MAE logarítmico usando los valores originales
# Luego, aplicar la inversa logarítmica (exp) para convertir a la escala original de precios
mae_original <- exp(mae_log * (maximo_preciom - minimo_preciom) + minimo_preciom)

# Mostrar el MAE en la escala original de precios
cat("MAE en la escala original de precios:", mae_original, "millones de pesos\n")
## MAE en la escala original de precios: 123.7034 millones de pesos

Aunque el R2 es un valor aceptable, el MAE en las unidades del precio es alto para el rango de precios manejado.

4.3 Evaluación del Modelo con Datos de Validación

Se aplicó el modelo ajustado a un conjunto de datos de validación para evaluar su capacidad de generalización. La evaluación de modelos con datos no utilizados en el entrenamiento es esencial para determinar su eficacia y evitar el sobreajuste.

# Dividir los datos en conjuntos de entrenamiento y validación (70%/30%)
set.seed(123)  # Asegurar reproducibilidad
sample_indices <- sample(1:nrow(variables_categorizadas), size = 0.7 * nrow(variables_categorizadas))
train_data <- variables_categorizadas[sample_indices, ]
validation_data <- variables_categorizadas[-sample_indices, ]

# Ajustar el modelo en los datos de entrenamiento
modelo_train <- lm(log_preciom ~ areaconst + banios + habitaciones + parqueaderos + estrato3 + estrato4 + estrato5 + estrato6 + tipoCasa + `zona_coordZona_Sur`, 
                   data = train_data)

# Realizar predicciones en los datos de validación
predicciones_validacion <- predict(modelo_train, newdata = validation_data)

# Calcular métricas de rendimiento: RMSE y MAE
rmse_validacion <- sqrt(mean((validation_data$log_preciom - predicciones_validacion)^2))
mae_validacion <- mean(abs(validation_data$log_preciom - predicciones_validacion))

# Mostrar resultados
cat("RMSE en el conjunto de validación:", rmse_validacion, "\n")
## RMSE en el conjunto de validación: 0.2837256
cat("MAE en el conjunto de validación:", mae_validacion, "\n")
## MAE en el conjunto de validación: 0.2176665

Los resultados en el conjunto de validación muestran un RMSE de 0.285 y un MAE de 0.218, valores muy cercanos a los obtenidos en la validación cruzada (RMSE de 0.282 y MAE de 0.217). Esta consistencia sugiere que el modelo no presenta problemas significativos de overfitting y que generaliza bien a datos no vistos, manteniendo un buen nivel de precisión en las predicciones fuera de la muestra de entrenamiento.

4.4 Resultados del Modelo

Se presentan los resultados del modelo de regresión lineal múltiple que se construyó para predecir los precios de las viviendas. Los coeficientes estimados y su significancia estadística se discuten, junto con el coeficiente de determinación (R²), para evaluar la calidad del ajuste del modelo.

# Mostrar los coeficientes del modelo y su significancia estadística
summary(modelo)
## 
## Call:
## lm(formula = log_preciom ~ areaconst + banios + habitaciones + 
##     parqueaderos + estrato3 + estrato4 + estrato5 + estrato6 + 
##     tipoCasa + zona_coordZona_Sur, data = variables_categorizadas)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.72322 -0.17964 -0.00312  0.16620  1.41512 
## 
## Coefficients: (1 not defined because of singularities)
##                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         5.637e+00  1.555e-02 362.435   <2e-16 ***
## areaconst           1.102e-03  3.713e-05  29.687   <2e-16 ***
## banios              1.182e-01  4.211e-03  28.079   <2e-16 ***
## habitaciones       -8.481e-03  3.706e-03  -2.288   0.0222 *  
## parqueaderos        9.010e-02  4.127e-03  21.833   <2e-16 ***
## estrato3           -9.012e-01  1.563e-02 -57.672   <2e-16 ***
## estrato4           -6.115e-01  1.144e-02 -53.446   <2e-16 ***
## estrato5           -3.830e-01  9.672e-03 -39.599   <2e-16 ***
## estrato6                   NA         NA      NA       NA    
## tipoCasa            8.766e-02  9.686e-03   9.051   <2e-16 ***
## zona_coordZona_Sur -1.111e-01  7.085e-03 -15.680   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2798 on 6707 degrees of freedom
## Multiple R-squared:  0.8019, Adjusted R-squared:  0.8017 
## F-statistic:  3017 on 9 and 6707 DF,  p-value: < 2.2e-16
# Interpretación del R²
r_squared <- summary(modelo)$r.squared
adj_r_squared <- summary(modelo)$adj.r.squared

# Mostrar los valores de R² y R² ajustado
cat("R-cuadrado:", r_squared, "\n")
## R-cuadrado: 0.8019374
cat("R-cuadrado ajustado:", adj_r_squared, "\n")
## R-cuadrado ajustado: 0.8016716

El modelo mostró un R-cuadrado de 0.8019374 y un R-cuadrado ajustado de 0.8016716 , indicando que aproximadamente el 80% de la variabilidad en los precios transformados logarítmicamente se explica por las variables incluidas en el modelo. Esto refleja un ajusterelativamente bueno, lo que sugiere que el modelo captura bien las relaciones entre las variables predictoras y el precio de la vivienda.

5 Validación de Supuestos del Modelo

En esta sección, se evaluaron los supuestos fundamentales del modelo de regresión lineal múltiple ajustado. Estos supuestos incluyen la normalidad de los residuos, la homocedasticidad (igualdad de varianzas), la independencia de errores, y la ausencia de multicolinealidad entre las variables predictoras. La validación de estos supuestos es crucial para garantizar la validez y precisión de los resultados del modelo.

5.1 Análisis de Residuos

Se realizó un análisis de los residuos del modelo para verificar los supuestos de normalidad y homocedasticidad. Los residuos deben seguir una distribución normal con media cero y varianza constante a lo largo de los valores predichos para validar estos supuestos.

# Gráfico de los residuos
plot(modelo, which = 1, main = "Residuos vs. Valores Ajustados")

El gráfico muestra una dispersión uniforme de los residuos alrededor de cero, lo que indica que el modelo cumple con la homocedasticidad en gran medida. Sin embargo, para los valores ajustados mayores a 7, se observa una ligera tendencia descendente en los residuos, lo que podría indicar una subestimación de precios más altos, sugiriendo posibles mejoras en el ajuste del modelo.

# Gráfico QQ para verificar normalidad de los residuos
plot(modelo, which = 2, main = "Gráfico QQ de los Residuos")

El gráfico QQ de los residuos muestra que la mayoría de los puntos siguen la línea de normalidad, lo que indica que los residuos se distribuyen de manera aproximadamente normal. Sin embargo, se observa una desviación en los cuantiles extremos, con algunos puntos como 214, 258 y 2449 alejándose de la línea, sugiriendo la presencia de algunos outliers o una ligera cola más pesada en los extremos.

# Histograma de los residuos
hist(residuals(modelo), breaks = 30, main = "Histograma de Residuos", xlab = "Residuos", ylab = "Frecuencia")

El histograma de los residuos muestra una distribución aproximadamente normal centrada en cero, con la mayoría de los residuos en el rango de -0.5 a 0.5. Esto indica que el modelo predice bien los valores medios. Sin embargo, las colas en ambos extremos, aunque pequeñas, sugieren la existencia de algunos outliers.

# Prueba de normalidad de Kolmogorov-Smirnov
ks_test <- ks.test(residuals(modelo), "pnorm", mean = mean(residuals(modelo)), sd = sd(residuals(modelo)))
cat("p-valor de la prueba de normalidad de Kolmogorov-Smirnov:", ks_test$p.value, "\n")
## p-valor de la prueba de normalidad de Kolmogorov-Smirnov: 3.374893e-05

La prueba de normalidad de Kolmogorov-Smirnov arrojó un p-valor de 3.374893e-05, indicando que los residuos no siguen una distribución normal,pero el hsistograma indica lo contrario.

5.2 Pruebas de Supuestos

En esta subsección, se realizaron pruebas estadísticas específicas para validar los supuestos del modelo de regresión lineal múltiple. La evaluación de los supuestos es crucial para garantizar la fiabilidad y la validez del modelo. Se llevaron a cabo las siguientes pruebas:

  • Prueba de Breusch-Pagan para detectar heterocedasticidad en los residuos, verificando si la varianza de los residuos es constante.

  • Prueba de Durbin-Watson para detectar autocorrelación en los residuos, asegurando que no exista correlación entre los errores de predicción.

# Instalar y cargar los paquetes necesarios si no están ya instalados
if (!require(lmtest)) {
  install.packages("lmtest")
  library(lmtest)
}

if (!require(car)) {
  install.packages("car")
  library(car)
}

# Prueba de Breusch-Pagan para detectar heterocedasticidad
bp_test <- bptest(modelo)
cat("Prueba de Breusch-Pagan para Heterocedasticidad:\n")
## Prueba de Breusch-Pagan para Heterocedasticidad:
print(bp_test)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo
## BP = 934.03, df = 9, p-value < 2.2e-16
# Prueba de Durbin-Watson para detectar autocorrelación en los residuos
dw_test <- dwtest(modelo)
cat("\nPrueba de Durbin-Watson para Autocorrelación:\n")
## 
## Prueba de Durbin-Watson para Autocorrelación:
print(dw_test)
## 
##  Durbin-Watson test
## 
## data:  modelo
## DW = 1.6614, p-value = 0.7603
## alternative hypothesis: true autocorrelation is greater than 0

La prueba de Breusch-Pagan para heterocedasticidad arrojó un BP de 934.03 con un p-valor menor a 2.2×10−16, indicando una fuerte evidencia de heterocedasticidad en los residuos del modelo, incumpliendo una de las hipótesis básicas del modelo de regresión lineal, sugiriendo que otros modelos pueden desempeñarse mejor. Por otro lado, la prueba de Durbin-Watson mostró un valor de 1.661 con un p-valor de 0.7603, sugiriendo que no hay suficiente evidencia para afirmar la presencia de autocorrelación en los residuos..

6 Predicciones y Recomendaciones

En esta sección, se realizaron predicciones para los precios de las viviendas solicitadas utilizando el modelo de regresión lineal múltiple ajustado. Basado en las características proporcionadas y los resultados obtenidos, se proporcionaron recomendaciones específicas para las dos viviendas solicitadas.

6.1 Predicción para Vivienda 1

Para la primera vivienda, se utilizó el modelo ajustado para predecir el precio con las siguientes características: - Tipo: Casa - Área construida: 200 m² - Número de parqueaderos: 1 - Número de baños: 2 - Número de habitaciones: 4 - Estrato: 4 (se considerará también estrato 5) - Zona: Norte

# Rename the column manually in variables_categorizadas
colnames(variables_categorizadas)[colnames(variables_categorizadas) == "zona_coordZona Sur"] <- "zona_coordZona_Sur"

# Verify the column renaming
print(colnames(variables_categorizadas))
##  [1] "log_preciom"        "areaconst"          "estrato3"          
##  [4] "estrato4"           "estrato5"           "estrato6"          
##  [7] "banios"             "habitaciones"       "parqueaderos"      
## [10] "zona_coordZona_Sur" "tipoCasa"
# Definir las características de la Vivienda 1 usando el nuevo nombre de columna
vivienda_1 <- data.frame(
  areaconst = 200,        # Área construida en metros cuadrados
  banios = 2,             # Número de baños
  habitaciones = 4,       # Número de habitaciones
  parqueaderos = 1,       # Número de parqueaderos
  estrato3 = 0,           # Estrato 3 (no aplica para estratos 4 y 5)
  estrato4 = 1,           # Estrato 4
  estrato5 = 0,           # Estrato 5 (ajustar si se considera estrato 4)
  estrato6 = 0,           # Estrato 6 (no aplicable para estratos 4 y 5)
  tipoCasa =1,
  zona_coordZona_Sur = 0  # Usando el nuevo nombre de columna sin espacio
)

# Predecir el precio logarítmico para la Vivienda 1
prediccion_log <- predict(modelo, newdata = vivienda_1)

# Convertir la predicción logarítmica de vuelta a la escala original
prediccion_original <- exp(prediccion_log) * (maximo_preciom - minimo_preciom) + minimo_preciom

# Mostrar el precio predicho para la Vivienda 1
cat("Precio estimado para la Vivienda 1 en estrato 4:", round(prediccion_original, 2), "millones de pesos +/- 21% \n")
## Precio estimado para la Vivienda 1 en estrato 4: 979.48 millones de pesos +/- 21%

6.1.1 Sugerencias de Ofertas para Vivienda 1

Se identifican y sugieren potenciales ofertas de viviendas que cumplan con los requisitos de la primera solicitud. Se consideran ofertas dentro del presupuesto de 350 millones de pesos y que cumplen con las características deseadas por la empresa solicitante. Las ofertas seleccionadas se presentan en un mapa para visualizar su ubicación geográfica.

library(leaflet)
library(dplyr)
library(knitr)

# Realizar la consulta para encontrar ofertas que cumplan con los criterios de Vivienda 1
ofertas_vivienda1 <- vivienda %>%
  filter(
    tipo == "Casa",                      # Solo casas
    areaconst >= 180 & areaconst <= 220, # Área construida cercana a 200 m²
    parqueaderos >= 0 & parqueaderos <= 2, # Alrededor de 1 parqueadero
    banios >= 1 & banios <= 3,           # Alrededor de 2 baños
    habitaciones >= 3 & habitaciones <= 5, # Alrededor de 4 habitaciones
    estrato %in% c(4, 5),                # Estrato 4 o 5
    zona == "Zona Norte",                # En la Zona Norte
    preciom <= 350                       # Precio máximo 350 millones de pesos
  ) %>%
  select(areaconst, parqueaderos, banios, habitaciones, estrato, zona, preciom, longitud, latitud)

# Mostrar los resultados en una tabla con solo las columnas necesarias
cat("Número de ofertas que cumplen con los criterios:", nrow(ofertas_vivienda1), "\n")
## Número de ofertas que cumplen con los criterios: 6
kable(ofertas_vivienda1[, c("areaconst", "parqueaderos", "banios", "habitaciones", "estrato", "zona", "preciom")], 
      caption = "Ofertas para Vivienda 1")
Ofertas para Vivienda 1
areaconst parqueaderos banios habitaciones estrato zona preciom
220 1 3 3 5 Zona Norte 335
203 2 2 5 5 Zona Norte 350
190 1 3 3 5 Zona Norte 350
216 2 2 4 5 Zona Norte 350
210 2 3 5 5 Zona Norte 320
203 2 3 4 5 Zona Norte 340
# Mostrar las ofertas en un mapa
mapa_ofertas_vivienda1 <- leaflet(ofertas_vivienda1) %>%
  addTiles() %>%
  addMarkers(~longitud, ~latitud,
             popup = ~paste("Precio:", round(preciom, 2), "millones de pesos",
                            "<br>Área construida:", areaconst, "m²",
                            "<br>Baños:", banios,
                            "<br>Habitaciones:", habitaciones,
                            "<br>Parqueaderos:", parqueaderos,
                            "<br>Estrato:", estrato,
                            "<br>Zona:", zona))
mapa_ofertas_vivienda1

6.2 Predicción para Vivienda 2

Para la segunda vivienda, se utilizó el modelo ajustado para predecir el precio con las siguientes características: - Tipo: Apartamento - Área construida: 300 m² - Número de parqueaderos: 3 - Número de baños: 3 - Número de habitaciones: 5 - Estrato: 5 o 6 (se analizará en ambos casos) - Zona: Sur

# Definir las características de la Vivienda 2
vivienda_2 <- data.frame(
  areaconst = 300,        # Área construida en metros cuadrados
  banios = 3,             # Número de baños
  habitaciones = 5,       # Número de habitaciones
  parqueaderos = 3,       # Número de parqueaderos
  estrato3 = 0,           # Estrato 3 (no aplica para estratos 5 y 6)
  estrato4 = 0,           # Estrato 4 (no aplica para estratos 5 y 6)
  estrato5 = 1,           # Estrato 5
  estrato6 = 0,           # Estrato 6 (ajustar si se considera estrato 6)
  zona_coordZona_Sur = 1, # Está en la zona sur
  tipoCasa = 0            # Tipo apartamento (no casa)
)

# Predecir el precio logarítmico para la Vivienda 2
prediccion_log <- predict(modelo, newdata = vivienda_2)

# Convertir la predicción logarítmica de vuelta a la escala original
prediccion_original <- exp(prediccion_log) * (maximo_preciom - minimo_preciom) + minimo_preciom

# Mostrar el precio predicho para la Vivienda 2
cat("Precio estimado para la Vivienda 2 en estrato 5:", round(prediccion_original, 2), "millones de pesos +/- 21% \n")
## Precio estimado para la Vivienda 2 en estrato 5: 1503.46 millones de pesos +/- 21%
# Cambiar a estrato 6 para la predicción adicional
vivienda_2$estrato5 <- 0
vivienda_2$estrato6 <- 1

# Predecir nuevamente para estrato 6
prediccion_log_estrato6 <- predict(modelo, newdata = vivienda_2)
prediccion_original_estrato6 <- exp(prediccion_log_estrato6) * (maximo_preciom - minimo_preciom) + minimo_preciom

# Mostrar el precio predicho para la Vivienda 2 en estrato 6
cat("Precio estimado para la Vivienda 2 en estrato 6:", round(prediccion_original_estrato6, 2), "millones de pesos +/- 21% \n")
## Precio estimado para la Vivienda 2 en estrato 6: 2203.23 millones de pesos +/- 21%

6.2.1 Sugerencias de Ofertas para Vivienda 2

Se identifican y sugieren potenciales ofertas de viviendas que cumplan con los requisitos de la primera solicitud. Se consideran ofertas dentro del presupuesto de 850 millones de pesos y que cumplen con las características deseadas por la empresa solicitante. Las ofertas seleccionadas se presentan en un mapa para visualizar su ubicación geográfica.

# Realizar la consulta para encontrar ofertas que cumplan con los criterios de Vivienda 2
ofertas_vivienda2 <- vivienda %>%
  filter(
    tipo == "Apartamento",               # Solo apartamentos
    areaconst >= 280 & areaconst <= 320, # Área construida cercana a 300 m²
    parqueaderos >= 2 & parqueaderos <= 4, # Alrededor de 3 parqueaderos
    banios >= 2 & banios <= 4,           # Alrededor de 3 baños
    habitaciones >= 4 & habitaciones <= 6, # Alrededor de 5 habitaciones
    estrato %in% c(5, 6),                # Estrato 5 o 6
    zona == "Zona Sur",                  # En la Zona Sur
    preciom <= 850                       # Precio máximo 850 millones de pesos
  ) %>%
  select(areaconst, parqueaderos, banios, habitaciones, estrato, zona, preciom, longitud, latitud)

# Mostrar los resultados en una tabla con solo las columnas necesarias
cat("Número de ofertas que cumplen con los criterios:", nrow(ofertas_vivienda2), "\n")
## Número de ofertas que cumplen con los criterios: 2
kable(ofertas_vivienda2[, c("areaconst", "parqueaderos", "banios", "habitaciones", "estrato", "zona", "preciom")], 
      caption = "Ofertas para Vivienda 2")
Ofertas para Vivienda 2
areaconst parqueaderos banios habitaciones estrato zona preciom
295.55 2 4 4 5 Zona Sur 410
320.00 2 4 4 5 Zona Sur 520
# Mostrar las ofertas en un mapa
mapa_ofertas_vivienda2 <- leaflet(ofertas_vivienda2) %>%
  addTiles() %>%
  addMarkers(~longitud, ~latitud,
             popup = ~paste("Precio:", round(preciom, 2), "millones de pesos",
                            "<br>Área construida:", areaconst, "m²",
                            "<br>Baños:", banios,
                            "<br>Habitaciones:", habitaciones,
                            "<br>Parqueaderos:", parqueaderos,
                            "<br>Estrato:", estrato,
                            "<br>Zona:", zona))
mapa_ofertas_vivienda2

7 Informe Ejecutivo

Este informe ejecutivo proporciona un resumen visual y conciso de los principales hallazgos del análisis de oferta de viviendas en Cali, enfocado en las necesidades específicas de la compañía internacional para la compra de dos propiedades.

7.1 Análisis del Mercado Inmobiliario en Cali

La mayoría de las viviendas en Cali tienen precios por debajo de los 500 millones de pesos, con una distribución sesgada a la derecha, lo que indica la presencia de algunas propiedades con precios significativamente más altos, como se observa en el siguientwe gráfico.

7.2 Influencia del Estrato en los Precios

Existe una relación positiva y significativa entre el estrato socioeconómico y el precio de la vivienda. Los estratos más altos (5 y 6) están asociados con precios más elevados, como se muestra en el siiguiente gráfico.

7.3 Influencia del Área en los Precios

A mayor área construida, mayor es el precio de la vivienda, lo que sugiere que el tamaño de la vivienda es un determinante clave del valor de mercado, como se observa en el siguiente gráfico, se pueden observar outliers, o desviaciones en la tendencia paraáreas superiores a 1000m2.

7.4 Sugerencias de Ofertas para Vivienda 1

Criterios: Casa, área construida ~200 m², parqueaderos ~1, baños ~2, habitaciones ~4, estrato 4 o 5, zona norte, precio ≤ 350 millones de pesos. (6 ofertas)

Precio estimado para la Vivienda 1 (si se cumplieran todos los criterios) en estrato 4: 979.48 millones de pesos +/- 21%

Ofertas para Vivienda 1 Dentro del Presupuesto Requerido
areaconst parqueaderos banios habitaciones estrato zona preciom
220 1 3 3 5 Zona Norte 335
203 2 2 5 5 Zona Norte 350
190 1 3 3 5 Zona Norte 350
216 2 2 4 5 Zona Norte 350
210 2 3 5 5 Zona Norte 320
203 2 3 4 5 Zona Norte 340

Ubicaciones para vivienda 1 Dentro del Presupuesto Requerido:

7.5 Sugerencias de Ofertas para Vivienda 2

Criterios: Apartamento, área construida ~300 m², parqueaderos ~3, baños ~3, habitaciones ~5, estrato 5 o 6, zona sur, precio ≤ 850 millones de pesos. (2 ofertas)

Precio estimado para la Vivienda 2 (si se cumplieran criterios) en estrato 5: 1503.46 millones de pesos +/- 21%

Precio estimado para la Vivienda 2 (si se cumplieran criterios) en estrato 6: 2203.23 millones de pesos +/- 21%

Ofertas para Vivienda 2 Dentro del Presupuesto Requerido
areaconst parqueaderos banios habitaciones estrato zona preciom
295.55 2 4 4 5 Zona Sur 410
320.00 2 4 4 5 Zona Sur 520

Ubicaciones para Vivienda 2 Dentro del Presupuesto Requerido:

7.6 Conclusión informe ejecutivo

Este informe ejecutivo presenta de manera visual los datos más relevantes para facilitar la toma de decisiones por parte de la compañía internacional interesada en adquirir dos propiedades en Cali. La combinación de análisis estadístico y visualización geográfica proporciona una comprensión integral de las opciones disponibles en el mercado inmobiliario local.

8 Conclusiones

En este trabajo se aplicó un modelo de regresión lineal múltiple para analizar y predecir los precios de viviendas en la ciudad de Cali, basándose en variables como área construida, número de baños, número de habitaciones, parqueaderos, estrato socioeconómico, tipo de vivienda y ubicación. La transformación logarítmica del precio permitió mejorar la distribución de los datos y ajustar mejor el modelo, reduciendo la heterocedasticidad y logrando una buena precisión en las predicciones. Los resultados demostraron que variables como el área construida y el estrato tienen un impacto significativo en el precio de las viviendas. Además, la inclusión de factores como el tipo de vivienda y la zona geográfica ayudó a capturar mejor las diferencias en el mercado inmobiliario local. En general, el modelo mostró una robusta capacidad predictiva, evidenciada por los valores de R² ajustado y los resultados de validación cruzada, lo que sugiere que es una herramienta valiosa para la toma de decisiones en el ámbito de bienes raíces, aunque la alta heterocedasticidad hace pensar que diferentes modelos pueden mejorar el desempeño. Futuras mejoras podrían incluir la incorporación de más variables explicativas y el uso de modelos más complejos para capturar relaciones no lineales.