Profesor: Jenyfer Portilla Yela
Curso: Métodos Estadísticos para Toma de Decisiones
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.
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.
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")## 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.
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")| 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")| 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
## 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.
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")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_interactivoEl 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
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.
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.
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.
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.
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
## 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.
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
## 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.
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.
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>
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
## Número de registros en el conjunto de validación: 2013
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")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
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.
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.
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>
## # 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>
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.
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.
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.
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
## 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.
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.
##
## 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
## 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.
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.
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.
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.
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:
##
## 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:
##
## 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..
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.
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%
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")| 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_vivienda1Para 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%
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")| 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_vivienda2Este 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.
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.
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.
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.
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%
| 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:
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%
| 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:
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.
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.