María, una agente inmobiliaria con una década de experiencia, fundó su propia agencia, C&A (Casas y Apartamentos), en Cali, tras haber trabajado en otras ciudades de Colombia. A pesar de que el mercado inmobiliario en Cali ha experimentado una desaceleración significativa en lo corrido del año, María ha recibido recientemente una solicitud de asesoría por parte de una compañía internacional. Esta empresa desea adquirir dos viviendas en Cali para ubicar a dos de sus empleados, cada una con características específicas en cuanto a tipo de inmueble, área construida, número de parqueaderos, baños, habitaciones, estrato y zona de la ciudad.
El objetivo de este informe es proporcionar a la compañía internacional una recomendación precisa y fundamentada sobre las mejores opciones de compra en el mercado actual de Cali, utilizando técnicas de modelación estadística. Se busca no solo identificar las propiedades que cumplen con los requisitos establecidos, sino también predecir su precio utilizando modelos de regresión lineal múltiple y recomendar las opciones más viables dentro del presupuesto preaprobado por la empresa.
-Filtrar las propiedades del mercado inmobiliario de Cali para seleccionar únicamente aquellas que cumplen con las especificaciones de tipo (casa y apartamento) y zona (Norte y Sur) solicitadas por la compañía internacional.
-Realizar un análisis exploratorio de datos centrado en la relación entre el precio de las viviendas y las variables clave: área construida, estrato, número de baños, número de habitaciones y número de parqueaderos, utilizando gráficos interactivos para una mejor visualización y comprensión.
-Desarrollar modelos de regresión lineal múltiple para predecir el precio de las viviendas en función de las características especificadas, y evaluar la significancia estadística de los coeficientes para asegurar la precisión de las predicciones.
-Validar los supuestos del modelo de regresión para asegurar la robustez del modelo predictivo, analizando la homocedasticidad, normalidad de los residuos y posibles multicolinealidades.
-Predecir el precio de las viviendas que se ajustan a las características solicitadas por la compañía, utilizando los modelos desarrollados, y verificar que estas predicciones se alineen con los créditos preaprobados (350 millones para la vivienda 1 y 850 millones para la vivienda 2).
-Recomendar al menos cinco opciones de compra para cada vivienda solicitada, asegurando que estas opciones cumplan con las condiciones requeridas y presentarlas en un mapa interactivo para facilitar la toma de decisiones por parte de la compañía internacional.
El análisis se realizó utilizando un conjunto de datos proporcionado
por el paquete paqueteMODELOS, que contiene información
detallada sobre propiedades residenciales en Cali, Colombia. Los datos
fueron filtrados para enfocarse en las zonas Norte y Sur de la ciudad, y
se incluyeron solo aquellos registros que correspondían a viviendas tipo
casa en la Zona Norte y apartamentos en la Zona Sur.
Inicialmente, se filtraron los datos para incluir únicamente las propiedades de interés en cada zona. Este proceso incluyó la exclusión de propiedades con ubicaciones ambiguas o no correspondientes a las zonas de estudio. Los barrios que no pertenecen a la zona específica fueron eliminados para asegurar la precisión en el análisis.
# Cargar el paquete y los datos
library(tidyverse)
library(htmlwidgets)
library(broom)
library(paqueteMODELOS)
library(tidyverse)
library(broom)
data("vivienda")
library(stringi)
library(ggplot2)
# Filtrar los datos para incluir solo casas en la zona norte
vivienda_norte_casas <- subset(vivienda, zona == "Zona Norte" & tipo == "Casa")
# Mostrar los primeros 3 registros de la base de datos filtrada
print(head(vivienda_norte_casas, 3))## # A tibble: 3 × 13
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1209 Zona N… 02 5 320 150 2 4 6
## 2 1592 Zona N… 02 5 780 380 2 3 3
## 3 4057 Zona N… 02 6 750 445 NA 7 6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
En este proceso, se abordó la normalización de los nombres de barrios para garantizar la consistencia de los datos en la zona norte. Se realizaron las siguientes etapas clave:
Filtrado Inicial: Se seleccionaron solo las casas de la zona norte para focalizar el análisis.
Eliminación de Acentos: Se eliminaron acentos de los nombres utilizando la función iconv, unificando variantes como “santa mónica” y “santa monica” en “santa monica”.
Sustitución de Nombres: Se realizaron sustituciones específicas para asegurar que todas las variantes de un mismo barrio se normalizaran bajo un nombre único.
Depuración de Datos: Se eliminaron barrios genéricos y no pertinentes, como “Cali” y “santa mónica residencial”, para asegurar la relevancia del conjunto de datos.
Verificación y Visualización: Se comprobó la correcta actualización y eliminación de los barrios normalizados y se visualizó el resultado en un mapa interactivo para validar la consistencia del proceso.
# Cargar y filtrar los datos
vivienda_norte_casas <- subset(vivienda, zona == "Zona Norte" & tipo == "Casa")
# Eliminar acentos de los nombres de los barrios
vivienda_norte_casas$barrio_normalizado <- tolower(trimws(vivienda_norte_casas$barrio))
vivienda_norte_casas$barrio_normalizado <- iconv(vivienda_norte_casas$barrio_normalizado, from = "UTF-8", to = "ASCII//TRANSLIT")
# Realizar las sustituciones necesarias sin imprimir resultados
vivienda_norte_casas$barrio_normalizado <- gsub("santa monica|santa monica", "santa monica", vivienda_norte_casas$barrio_normalizado)
vivienda_norte_casas$barrio_normalizado <- gsub("la flora|la.flora", "la flora", vivienda_norte_casas$barrio_normalizado)
vivienda_norte_casas$barrio_normalizado <- gsub("santa monica residencial|santa monica residencial", "santa monica residencial", vivienda_norte_casas$barrio_normalizado)
vivienda_norte_casas$barrio_normalizado <- gsub("villa del prado|villa del prado", "villa del prado", vivienda_norte_casas$barrio_normalizado)
vivienda_norte_casas$barrio_normalizado <- gsub("villas de veracruz|villas de veracruz", "villas de veracruz", vivienda_norte_casas$barrio_normalizado)
# Eliminar los barrios genéricos
vivienda_norte_casas <- subset(vivienda_norte_casas, !barrio_normalizado %in% c("zona norte", "zona oriente"))
# Actualizar el campo 'zona' para los barrios que están en la lista
barrios_a_actualizar <- data.frame(
barrio_normalizado = c("valle del lili", "las granjas", "las ceibas", "el trebol", "las americas",
"evaristo garcia", "chapinero", "la base", "urbanizacion la nueva",
"cristales", "tejares de san", "occidente", "poblado campestre",
"las delicias", "el sena", "brisas del guabito", "el guabito"),
nueva_zona = c("Zona Sur", "Zona Sur", "Zona Sur", "Zona Sur", "Zona Sur",
"Zona Sur", "Zona Sur", "Zona Centro-Sur", "Zona Sur",
"Zona Oeste", "Zona Sur", "Zona Sur", "Zona Sur",
"Zona Sur", "Zona Centro-Sur", "Zona Sur", "Zona Sur")
)
for (i in 1:nrow(barrios_a_actualizar)) {
vivienda_norte_casas$zona[vivienda_norte_casas$barrio_normalizado == barrios_a_actualizar$barrio_normalizado[i]] <- barrios_a_actualizar$nueva_zona[i]
}
# Eliminar los registros donde el barrio es "Cali" y "santa monica residencial"
vivienda_norte_casas <- subset(vivienda_norte_casas, barrio_normalizado != "cali")
vivienda_norte_casas <- subset(vivienda_norte_casas, !grepl("santa monica residencial", vivienda_norte_casas$barrio_normalizado, ignore.case = TRUE))
# Preparar el mapa
if(!require(leaflet)) install.packages("leaflet")
library(leaflet)
mapa <- leaflet(vivienda_norte_casas) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
radius = 5,
color = "blue",
fill = TRUE,
fillOpacity = 0.7,
popup = ~paste("Barrio:", barrio_normalizado),
label = ~paste("Barrio:", barrio_normalizado)
) %>%
setView(lng = mean(vivienda_norte_casas$longitud, na.rm = TRUE),
lat = mean(vivienda_norte_casas$latitud, na.rm = TRUE),
zoom = 13)
# Mostrar el mapa
mapaLa gráfica de correlación presentada ofrece una visión integral de cómo diferentes características de las viviendas en la zona norte están relacionadas entre sí, especialmente en lo que respecta a su influencia en el precio. A continuación, se detalla un análisis más humanizado sobre los hallazgos principales de la gráfica:
-1. Precio y Área Construida: Correlación de 0.731: Esta es la relación más fuerte observada en la gráfica. Esto significa que, a medida que aumenta el área construida de una vivienda, también lo hace su precio. Es un hallazgo esperado, dado que más espacio generalmente se traduce en un mayor valor. Esto sugiere que el tamaño es un factor crítico en la valoración de las casas en la zona norte.
-2. Precio y Estrato: Correlación de 0.612: Existe una relación significativa entre el estrato de una vivienda y su precio. Los estratos más altos, que suelen ofrecer mejor infraestructura, servicios y prestigio, están asociados con precios más elevados. Esto es clave al considerar viviendas en diferentes estratos, ya que la ubicación y el nivel socioeconómico del área impactan considerablemente en el valor de la propiedad.
-3. Precio y Número de Baños: Correlación de 0.523: El número de baños también tiene una relación positiva con el precio, aunque no tan fuerte como la del área construida o el estrato. Sin embargo, es un factor importante, ya que más baños suelen indicar mayor comodidad y funcionalidad en la vivienda.
-4. Precio y Número de Habitaciones: Correlación de 0.375: La relación entre el precio y el número de habitaciones es más débil en comparación con otras variables. Aunque sigue siendo relevante, su impacto en el precio es menor. Esto podría sugerir que, para los compradores en esta zona, otras características como el espacio general y la calidad del entorno (estrato) son más decisivas.
-5. Otras Relaciones: Área Construida y Estrato (Correlación de 0.457): A medida que se aumenta el estrato, las viviendas tienden a ser más grandes, lo que refuerza la importancia del estrato en la determinación del valor de la propiedad. Número de Baños y Habitaciones (Correlación de 0.576): Es lógico que un mayor número de habitaciones implique un mayor número de baños, lo cual es un factor de confort y funcionalidad en la vivienda.
library(GGally)
library(plotly)
# Selección de variables para el análisis
variables_seleccionadas <- vivienda_norte_casas[, c("preciom", "areaconst", "estrato", "banios", "habitaciones")]
# Generar el gráfico de pares (ggpairs) para las variables seleccionadas
ggpairs_plot <- ggpairs(variables_seleccionadas,
title = "Correlación entre Precio y Variables Seleccionadas")
# Convertir el gráfico de ggpairs a un objeto plotly para interactividad
plotly_ggpairs <- ggplotly(ggpairs_plot)
# Mostrar el gráfico interactivo
plotly_ggpairsPara asegurar la integridad del análisis de datos de vivienda_norte_casas, se realizó un tratamiento cuidadoso de los valores faltantes, sin intervenir en los valores atípicos, ya que estos reflejan fielmente la diversidad del mercado inmobiliario en las zonas norte y sur de Cali.
Tratamiento de Valores Faltantes Identificación de valores faltantes: Se detectaron valores ausentes en las variables clave (areaconst, estrato, habitaciones, parqueaderos, banios).
Imputación por moda: Los valores faltantes en la variable parqueaderos se imputaron utilizando la moda por barrio, asegurando que los datos fueran representativos de las características locales.
Conversión de variables: La variable estrato fue convertida a factor para facilitar un análisis categórico más adecuado.
Exclusión del Tratamiento de Outliers No se realizó tratamiento de outliers en este análisis, ya que los valores extremos son indicativos de la variabilidad natural entre las zonas norte y sur de Cali. Estos outliers proporcionan información valiosa sobre las diferencias en el mercado inmobiliario y reflejan las características únicas de cada área, las cuales son esenciales para un análisis integral del mercado.
# 1. Identificación y Tratamiento de Valores Faltantes
# Ver cuántos valores NA hay en cada columna relevante
print(sapply(vivienda_norte_casas[, c("areaconst", "estrato", "habitaciones",
"parqueaderos", "banios")],
function(x) sum(is.na(x))))## areaconst estrato habitaciones parqueaderos banios
## 0 0 0 262 0
# Función para calcular la moda
get_moda <- function(x) {
uniq_x <- unique(x)
uniq_x[which.max(tabulate(match(x, uniq_x)))]
}
# Calcular la moda de parqueaderos por barrio
moda_parqueaderos <- aggregate(parqueaderos ~ barrio_normalizado, data = vivienda_norte_casas, FUN = get_moda)
# Imputar los valores faltantes con la moda correspondiente al barrio
vivienda_norte_casas <- merge(vivienda_norte_casas, moda_parqueaderos, by = "barrio_normalizado", suffixes = c("", "_moda"))
# Reemplazar los NA en parqueaderos con la moda del barrio
vivienda_norte_casas$parqueaderos[is.na(vivienda_norte_casas$parqueaderos)] <- vivienda_norte_casas$parqueaderos_moda
# Eliminar la columna temporal de moda
vivienda_norte_casas$parqueaderos_moda <- NULL
# Verificar si se han imputado los valores faltantes
print(sapply(vivienda_norte_casas[, c("areaconst", "estrato", "habitaciones",
"parqueaderos", "banios")], function(x) sum(is.na(x))))## areaconst estrato habitaciones parqueaderos banios
## 0 0 0 0 0
# Convertir la variable 'estrato' a factor
vivienda_norte_casas$estrato <- as.factor(vivienda_norte_casas$estrato)
# Verificar la conversión
print(str(vivienda_norte_casas$estrato))## Factor w/ 4 levels "3","4","5","6": 2 2 1 2 4 2 3 3 3 1 ...
## NULL
El modelo de regresión lineal múltiple incluye las siguientes variables predictoras: área construida (areaconst), estrato socioeconómico (estrato), número de habitaciones, número de parqueaderos y número de baños.
-Coeficiente de Determinación (R²): El valor de R² es 0.6433, lo que indica que aproximadamente el 64.33% de la variabilidad en el precio por metro cuadrado de las viviendas puede ser explicada por las variables incluidas en el modelo. Este es un indicador positivo que sugiere que el modelo tiene un buen ajuste.
-R² ajustado: El valor ajustado de R² es 0.6393, lo que ajusta el valor de R² considerando el número de variables en el modelo y confirma la solidez del ajuste del modelo. Interpretación de los Coeficientes Área construida (areaconst): Este es el factor más influyente en el precio por metro cuadrado, con un coeficiente de 0.8123. Esto significa que, manteniendo todo lo demás constante, cada metro cuadrado adicional de área construida incrementa el precio por metro cuadrado en 0.81 unidades. Este resultado es altamente significativo (p < 2e-16).
Estrato socioeconómico (estrato): Los coeficientes para los diferentes niveles de estrato (4, 5, y 6) son todos positivos y altamente significativos, lo que indica que el precio por metro cuadrado aumenta con el estrato. En particular, el estrato 6 tiene el mayor impacto, elevando el precio en 273.14 unidades, lo cual es esperado, ya que las propiedades en estratos más altos suelen estar ubicadas en zonas más exclusivas con mejores servicios.
-Número de parqueaderos y baños: Ambas variables tienen un impacto positivo y significativo en el precio por metro cuadrado. Cada parqueadero adicional incrementa el precio en 13.03 unidades, mientras que cada baño adicional lo incrementa en 23.36 unidades. Estos resultados reflejan la preferencia del mercado por viviendas con más comodidades.
-Número de habitaciones: Aunque el número de habitaciones tiene un coeficiente positivo (6.28), su efecto no es estadísticamente significativo (p = 0.1456), lo que sugiere que este factor no tiene un impacto considerable en el precio por metro cuadrado, al menos no en el contexto de este modelo.
# Instalar los paquetes necesarios
install.packages("tidyverse")
install.packages("broom")
# Estimación del modelo de regresión lineal múltiple con el nombre correcto de la variable precio
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = vivienda_norte_casas)
# Resumen del modelo: Coeficientes y su significancia
modelo_summary <- summary(modelo)
print(modelo_summary)##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = vivienda_norte_casas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -965.66 -76.23 -16.16 44.64 1067.47
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.30996 19.65277 -0.168 0.8663
## areaconst 0.81229 0.04504 18.036 < 2e-16 ***
## estrato4 86.06374 18.44351 4.666 3.76e-06 ***
## estrato5 135.58043 17.35394 7.813 2.39e-14 ***
## estrato6 273.14127 30.77988 8.874 < 2e-16 ***
## habitaciones 6.28022 4.31037 1.457 0.1456
## parqueaderos 13.02796 5.55580 2.345 0.0193 *
## banios 23.36200 5.73910 4.071 5.29e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 156.4 on 622 degrees of freedom
## Multiple R-squared: 0.6433, Adjusted R-squared: 0.6393
## F-statistic: 160.3 on 7 and 622 DF, p-value: < 2.2e-16
# Resumen del modelo en un formato más ordenado usando broom
modelo_tidy <- tidy(modelo)
print(modelo_tidy)## # A tibble: 8 × 5
## term estimate std.error statistic p.value
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -3.31 19.7 -0.168 8.66e- 1
## 2 areaconst 0.812 0.0450 18.0 8.27e-59
## 3 estrato4 86.1 18.4 4.67 3.76e- 6
## 4 estrato5 136. 17.4 7.81 2.39e-14
## 5 estrato6 273. 30.8 8.87 7.47e-18
## 6 habitaciones 6.28 4.31 1.46 1.46e- 1
## 7 parqueaderos 13.0 5.56 2.34 1.93e- 2
## 8 banios 23.4 5.74 4.07 5.29e- 5
# Interpretación del coeficiente R2
r2_value <- modelo_summary$r.squared
adjusted_r2_value <- modelo_summary$adj.r.squared
cat("El valor de R² es:", r2_value, "\n")## El valor de R² es: 0.6433091
## El valor de R² ajustado es: 0.6392949
-Q-Q Plot: Este gráfico evalúa la normalidad de los residuos. En el Q-Q plot (segundo gráfico, arriba a la derecha), se observa que los puntos se desvían de la línea diagonal en los extremos, lo que indica que los residuos no siguen perfectamente una distribución normal.
-Interpretación: La desviación de la normalidad podría afectar la validez de las inferencias estadísticas (como las pruebas t y F). Aunque el modelo podría seguir siendo útil, se debería considerar la posibilidad de aplicar una transformación a la variable dependiente para mejorar la normalidad, o utilizar métodos robustos a la no normalidad.
Residuals vs Fitted Plot: El primer gráfico en la parte superior izquierda muestra los residuos en función de los valores ajustados. Se espera que los residuos se dispersen aleatoriamente alrededor de la línea horizontal (residuo = 0). Sin embargo, en este caso, parece haber una ligera dispersión creciente conforme aumentan los valores ajustados, lo que podría indicar heteroscedasticidad (varianza no constante).
Scale-Location Plot: En el tercer gráfico (abajo a la izquierda), los residuos estándar se distribuyen de manera similar, mostrando un ligero patrón creciente, lo que confirma la sospecha de heteroscedasticidad. Interpretación: La presencia de heteroscedasticidad sugiere que las estimaciones del modelo podrían ser ineficientes. Como corrección, se podría considerar la aplicación de una transformación a la variable dependiente, o utilizar errores estándar robustos.
Residuals vs Fitted Plot: Este gráfico también se utiliza para evaluar la linealidad. La ausencia de un patrón claro indica que la relación entre las variables independientes y dependiente es razonablemente lineal. Sin embargo, la presencia de puntos alejados sugiere que algunas relaciones podrían no ser perfectamente lineales. Interpretación: Aunque no parece haber una fuerte violación de la linealidad, la inclusión de términos polinomiales o la transformación de algunas variables independientes podría mejorar el ajuste del modelo.
El gráfico de residuos vs leverage (cuarto gráfico, abajo a la derecha) no proporciona directamente información sobre la autocorrelación, pero puede sugerir la presencia de puntos de alta influencia (outliers) que podrían afectar la independencia de los errores. Interpretación: Se recomienda realizar la prueba de Durbin-Watson para evaluar la autocorrelación de los residuos. Si se detecta autocorrelación, sería necesario ajustar el modelo utilizando técnicas que manejen la dependencia temporal o espacial.
Residuals vs Leverage Plot: Este gráfico ayuda a identificar observaciones con alta influencia sobre el modelo (outliers). Algunos puntos están claramente identificados (por ejemplo, 1890, 4610) como posibles outliers con alto leverage. Interpretación: Los outliers podrían estar sesgando las estimaciones del modelo. Es recomendable analizar estos puntos para decidir si deben ser eliminados, transformados o si se debe utilizar un modelo robusto que minimice
División del Conjunto de Datos: Se comenzó fijando una semilla con el propósito de garantizar la reproducibilidad del análisis. Luego, se creó un índice aleatorio que selecciona el 70% de los datos originales para conformar el conjunto de entrenamiento (train_set), mientras que el 30% restante se destinó al conjunto de prueba (test_set). Esta partición es fundamental para validar la capacidad predictiva del modelo, permitiendo una evaluación más precisa de su rendimiento.
Estimación del Modelo con el Conjunto de Entrenamiento: Utilizando los datos del conjunto de entrenamiento, se ajustó un modelo de regresión lineal múltiple para predecir el precio por metro cuadrado (preciom). Las variables predictoras incluidas fueron: área construida (areaconst), estrato socioeconómico (estrato), número de habitaciones, número de parqueaderos y número de baños. Este modelo se construyó para identificar las relaciones entre estas características de las viviendas y su precio por metro cuadrado.
Resumen del Modelo:
-Coeficiente de Determinación (R²): El valor de R² fue de 0.6612, lo que sugiere que el 66.12% de la variabilidad en el precio por metro cuadrado de las viviendas puede explicarse por las variables incluidas en el modelo. Este es un buen nivel de ajuste, que indica que el modelo capta gran parte de las tendencias presentes en los datos.
-R² Ajustado: El valor ajustado de R², que toma en cuenta el número de variables en el modelo, fue de 0.6557. Esto confirma que el modelo sigue siendo sólido incluso después de ajustar por el número de predictores.
-Área construida (areaconst): Con un coeficiente de 0.74236 y un valor p < 2e-16, esta variable es altamente significativa, indicando que a medida que aumenta el área construida, también lo hace el precio por metro cuadrado.
-Estrato (estrato4, estrato5, estrato6): Los estratos socioeconómicos superiores (4, 5, 6) muestran coeficientes positivos y altamente significativos, especialmente el estrato 6, que tiene un impacto considerable en el aumento del precio por metro cuadrado.
-Habitaciones: Con un coeficiente de 10.50957 y un valor p de 0.02844, el número de habitaciones muestra una relación significativa con el precio, aunque su impacto es menor en comparación con otras variables.
-Parqueaderos: Aunque el coeficiente es positivo (8.67287), esta variable no es estadísticamente significativa (p = 0.15965), sugiriendo que su influencia en el precio es limitada.
-Baños: Los baños tienen un impacto significativo en el precio, con un coeficiente de 20.51619 y un valor p de 0.00161.
#Particionar los Datos
set.seed(123) # Fijar la semilla para la reproducibilidad
# Crear un índice aleatorio para seleccionar el 70% de los datos para el conjunto de entrenamiento
train_index <- sample(seq_len(nrow(vivienda_norte_casas)), size = 0.7 * nrow(vivienda_norte_casas))
# Crear los sets de entrenamiento y prueba
train_set <- vivienda_norte_casas[train_index, ]
test_set <- vivienda_norte_casas[-train_index, ]
#Estimar el Modelo Usando el Conjunto de Entrenamiento
# Estimar el modelo con el conjunto de entrenamiento
modelo_train <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = train_set)
# Mostrar un resumen del modelo
summary(modelo_train)##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = train_set)
##
## Residuals:
## Min 1Q Median 3Q Max
## -897.98 -74.12 -13.34 43.96 1067.01
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.14188 22.63552 0.139 0.88967
## areaconst 0.74236 0.04897 15.161 < 2e-16 ***
## estrato4 104.41562 21.65062 4.823 1.96e-06 ***
## estrato5 139.59024 19.64300 7.106 4.94e-12 ***
## estrato6 294.80028 34.11765 8.641 < 2e-16 ***
## habitaciones 10.50957 4.78041 2.198 0.02844 *
## parqueaderos 8.67287 6.15673 1.409 0.15965
## banios 20.51619 6.46171 3.175 0.00161 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 148.6 on 433 degrees of freedom
## Multiple R-squared: 0.6612, Adjusted R-squared: 0.6557
## F-statistic: 120.7 on 7 and 433 DF, p-value: < 2.2e-16
El gráfico compara las predicciones del modelo con los valores reales de los precios de las viviendas. Cada punto azul en el gráfico representa una observación, es decir, una vivienda en particular, donde la posición en el eje horizontal indica el precio real y la posición en el eje vertical indica el precio predicho por el modelo.
Observaciones Clave
La mayoría de los puntos se encuentran bastante cerca de la línea roja discontinua, que representa una predicción perfecta (donde el precio predicho sería exactamente igual al precio real). Esto sugiere que, en general, el modelo tiene un buen rendimiento, capturando la tendencia general de los precios de las viviendas en función de las variables consideradas (área construida, estrato, número de habitaciones, parqueaderos y baños).
Sin embargo, se observan algunos puntos alejados de la línea roja, lo que indica que en estos casos el modelo no fue capaz de predecir con precisión el precio real de la vivienda. Por ejemplo, en una vivienda con un precio real de 600 unidades, el modelo predijo un valor significativamente menor, de aproximadamente 350.6 unidades. Este tipo de divergencias sugiere que podría haber otros factores, no considerados en el modelo, que afectan el precio de las viviendas.
El modelo parece ser más preciso para las viviendas con precios en el rango medio, donde la mayoría de los puntos están concentrados cerca de la línea de referencia. Esto puede indicar que el modelo es adecuado para predecir precios de viviendas típicas en la zona norte, pero podría ser menos confiable para viviendas con precios extremadamente altos o bajos.
library(ggplot2)
# Paso 1: Realizar predicciones sobre el conjunto de prueba
predicciones <- predict(modelo, newdata = test_set)
# Paso 2: Combinar las predicciones con los valores reales
resultados <- data.frame(
Real = test_set$preciom,
Prediccion = predicciones
)
# Mostrar las primeras filas de las predicciones
print(head(resultados))## Real Prediccion
## 1 600 350.5968
## 2 320 291.1494
## 3 500 371.1797
## 9 800 707.2022
## 15 650 529.5133
## 17 625 558.4108
# Paso 3: Visualización de las predicciones vs los valores reales
library(ggplot2)
ggplot(resultados, aes(x = Real, y = Prediccion)) +
geom_point(color = "blue") +
geom_abline(intercept = 0, slope = 1, color = "red", linetype = "dashed") +
labs(title = "Predicciones vs Valores Reales",
x = "Valor Real",
y = "Predicción") +
theme_minimal()El Error Cuadrático Medio (MSE) mide el promedio de los errores al cuadrado entre los valores predichos por el modelo y los valores reales. En este caso, un MSE de 29,346.97 indica que, en promedio, las predicciones del modelo se desvían de los valores reales por una cantidad considerable. Este valor sugiere que hay una cantidad significativa de variabilidad en las predicciones que el modelo no ha capturado de manera efectiva.
Un MSE alto puede ser un indicador de que existen outliers o valores atípicos que están influyendo en el rendimiento del modelo. Estos valores podrían ser propiedades con características extremas o no comunes, lo que podría llevar a errores de predicción mayores.
Error Absoluto Medio (MAE): 100.3844 El Error Absoluto Medio (MAE) nos proporciona una medida de la magnitud promedio de los errores de predicción, pero sin considerar la dirección del error (es decir, si la predicción es más alta o más baja que el valor real). Un MAE de 100.3844 significa que, en promedio, las predicciones del modelo difieren de los valores reales en aproximadamente 100 unidades.
Este valor nos da una idea más tangible del error típico que podemos esperar del modelo, y en este caso, sugiere que las predicciones pueden estar razonablemente cerca del valor real, pero aún existen diferencias notables. Comparado con el MSE, el MAE es más intuitivo ya que está en las mismas unidades que los precios de las viviendas.
Coeficiente de Determinación (R²): 0.6275624 El Coeficiente de Determinación (R²) es un indicador de la proporción de la varianza en la variable dependiente (el precio de las viviendas) que es explicada por el modelo. Un R² de 0.6275624 indica que el 62.76% de la variabilidad en los precios de las viviendas es capturada por el modelo.
En términos prácticos, esto significa que el modelo es bastante efectivo en capturar las relaciones entre las variables explicativas (como el área construida, el estrato, el número de habitaciones, parqueaderos, y baños) y el precio de las viviendas. Sin embargo, hay un 37.24% de la variabilidad que no está siendo explicada por este modelo, lo que sugiere que hay otros factores importantes que no se han incluido y que podrían mejorar las predicciones si se consideran.
# Calcular el Error Cuadrático Medio (MSE)
mse <- mean((test_set$preciom - predicciones)^2)
# Calcular el Error Absoluto Medio (MAE)
mae <- mean(abs(test_set$preciom - predicciones))
# Calcular el R2
r2 <- cor(test_set$preciom, predicciones)^2
# Mostrar los resultados
cat("Error Cuadrático Medio (MSE):", mse, "\n")## Error Cuadrático Medio (MSE): 29346.97
## Error Absoluto Medio (MAE): 100.3844
## Coeficiente de Determinación (R2): 0.6275624
El proceso de selección de las propiedades para la Vivienda 1 se basó en una evaluación rigurosa que comparó las características deseadas con las ofertas disponibles en la Zona Norte. A continuación, se detallan las razones por las cuales se eligieron las cinco propiedades finales:
-Filtración por Precio y Estrato: Precio: Las propiedades seleccionadas no exceden el crédito preaprobado de 350 millones de pesos. Esto garantiza que todas las opciones sean financieramente viables, lo que es esencial para asegurar una compra exitosa dentro del presupuesto establecido.
-Estrato: Se consideraron propiedades en estratos 4 y 5, que corresponden al estándar de vida esperado para la Vivienda 1. Estos estratos aseguran una calidad de vida acorde a las expectativas del comprador, incluyendo servicios públicos de calidad y un entorno comunitario adecuado.
-Comparación con los Valores Objetivo: Área Construida: El valor objetivo de 200 m² se tomó como referencia para seleccionar propiedades con áreas construidas que oscilan entre 180 y 220 m². Esto asegura que la vivienda proporcione suficiente espacio para la comodidad familiar sin ser excesivamente grande.
-Parqueaderos: Dado que la Vivienda 1 requiere 1 parqueadero, todas las propiedades seleccionadas cumplen con este requisito, lo que asegura la conveniencia diaria para los propietarios.
-Baños y Habitaciones: Se priorizó la selección de viviendas con al menos 3 baños y 3 a 4 habitaciones, asegurando que se cumplan las necesidades de una familia que busca comodidad y espacio suficiente para todos sus miembros.
-Cálculo del Puntaje (Score): Se calculó un puntaje basado en la diferencia entre las características de cada propiedad y los valores objetivo mencionados. Las propiedades con el menor puntaje fueron seleccionadas, ya que son las que más se acercan a cumplir con todas las especificaciones. Este método cuantitativo asegura que las propiedades elegidas se alineen lo más posible con las expectativas del comprador.
-Selección Final: De las propiedades disponibles, se seleccionaron las cinco con el puntaje más bajo. Estas propiedades no solo cumplen con los requisitos de espacio, comodidad, y ubicación, sino que también se encuentran dentro del rango presupuestal. Esto garantiza que las opciones elegidas ofrezcan el mejor equilibrio entre todas las características deseadas, justificando su selección como las mejores opciones para la Vivienda 1.
library(leaflet)
library(dplyr)
# Definir los valores objetivo de la vivienda 1
area_objetivo <- 200
parqueaderos_objetivo <- 1
banios_objetivo <- 2
habitaciones_objetivo <- 4
estrato_objetivo <- c(4, 5)
precio_maximo <- 350 # Crédito preaprobado en millones
# Filtrar por precio, estrato y calcular la diferencia con los valores objetivo
ofertas_cercanas <- test_set %>%
filter(preciom <= precio_maximo & estrato %in% estrato_objetivo) %>%
mutate(
score = abs(areaconst - area_objetivo) +
abs(parqueaderos - parqueaderos_objetivo) +
abs(banios - banios_objetivo) +
abs(habitaciones - habitaciones_objetivo)
) %>%
arrange(score) %>%
head(5) # Seleccionar las 5 ofertas más cercanas
# Verificar si hay propiedades que cumplan con los criterios
if (nrow(ofertas_cercanas) == 0) {
cat("No se encontraron propiedades que cumplan con los criterios de la vivienda 1.\n")
} else {
# Crear el mapa interactivo con las 5 ofertas seleccionadas
mapa_ofertas_norte <- leaflet(ofertas_cercanas) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
radius = 8,
color = "blue",
fill = TRUE,
fillOpacity = 0.6,
popup = ~paste(
"Barrio:", barrio, "<br>",
"Precio Estimado: $", round(preciom, 2), "millones<br>",
"Área Construida:", areaconst, "m2<br>",
"Estrato:", estrato, "<br>",
"Habitaciones:", habitaciones, "<br>",
"Parqueaderos:", parqueaderos, "<br>",
"Baños:", banios
),
label = ~paste("Precio: $", round(preciom, 2), "millones")
) %>%
setView(lng = mean(ofertas_cercanas$longitud, na.rm = TRUE),
lat = mean(ofertas_cercanas$latitud, na.rm = TRUE),
zoom = 13)
# Mostrar el mapa
print(mapa_ofertas_norte)
# Generar la tabla con las características de las casas seleccionadas
tabla_ofertas <- ofertas_cercanas %>%
select(areaconst, parqueaderos, banios, habitaciones, estrato, zona, barrio, preciom)
# Mostrar la tabla
print(tabla_ofertas)
}## areaconst parqueaderos banios habitaciones estrato zona barrio
## 1 207 1 4 4 4 Zona Norte el bosque
## 2 208 1 6 4 5 Zona Norte el bosque
## 3 190 1 3 3 5 Zona Norte la flora
## 4 180 1 3 4 4 Zona Norte los andes
## 5 220 1 3 3 5 Zona Norte el bosque
## preciom
## 1 340
## 2 340
## 3 350
## 4 280
## 5 335
El análisis de los datos de las viviendas revela una variabilidad significativa en varias de las características clave:
Precio (preciom): Los precios de las viviendas oscilan entre 75 y 1750 millones, con un promedio de 297.3 millones y una mediana de 245 millones. Esto sugiere que la mayoría de las viviendas están en un rango de precios accesible, pero hay algunas propiedades de alto valor que elevan el promedio.
Área Construida (areaconst): El tamaño de las viviendas varía considerablemente, desde 40 m² hasta 932 m², con un tamaño promedio de 97.47 m² y una mediana de 85 m². Esto indica que la mayoría de las viviendas son relativamente compactas, aunque existen opciones más grandes disponibles.
Parqueaderos (parqueaderos): La mayoría de las viviendas cuentan con un solo parqueadero, aunque hay propiedades con hasta 10 espacios. Sin embargo, es notable que hay 406 registros sin información sobre parqueaderos, lo que podría afectar el análisis si no se maneja adecuadamente.
Baños (banios) y Habitaciones (habitaciones): La mayoría de las viviendas tiene entre 2 y 3 baños y alrededor de 3 habitaciones. Estas cifras son consistentes con lo que se esperaría en un mercado de viviendas estándar.
# Filtrar los datos para incluir solo apartamentos en la zona sur
vivienda_sur_aptos <- subset(vivienda, zona == "Zona Sur" & tipo == "Apartamento")
# Resumen de la base de datos filtrada
print(summary(vivienda_sur_aptos))## id zona piso estrato
## Min. : 3 Length:2787 Length:2787 Min. :3.00
## 1st Qu.:2292 Class :character Class :character 1st Qu.:4.00
## Median :4004 Mode :character Mode :character Median :5.00
## Mean :4131 Mean :4.63
## 3rd Qu.:5876 3rd Qu.:5.00
## Max. :8302 Max. :6.00
##
## preciom areaconst parqueaderos banios
## Min. : 75.0 Min. : 40.00 Min. : 1.000 Min. :0.000
## 1st Qu.: 175.0 1st Qu.: 65.00 1st Qu.: 1.000 1st Qu.:2.000
## Median : 245.0 Median : 85.00 Median : 1.000 Median :2.000
## Mean : 297.3 Mean : 97.47 Mean : 1.415 Mean :2.488
## 3rd Qu.: 335.0 3rd Qu.:110.00 3rd Qu.: 2.000 3rd Qu.:3.000
## Max. :1750.0 Max. :932.00 Max. :10.000 Max. :8.000
## NA's :406
## habitaciones tipo barrio longitud
## Min. :0.000 Length:2787 Length:2787 Min. :-76.57
## 1st Qu.:3.000 Class :character Class :character 1st Qu.:-76.54
## Median :3.000 Mode :character Mode :character Median :-76.53
## Mean :2.966 Mean :-76.53
## 3rd Qu.:3.000 3rd Qu.:-76.52
## Max. :6.000 Max. :-76.46
##
## latitud
## Min. :3.334
## 1st Qu.:3.370
## Median :3.383
## Mean :3.390
## 3rd Qu.:3.406
## Max. :3.497
##
El proceso de normalización de los nombres de barrios en la zona sur de Cali es esencial para garantizar la coherencia y la precisión en el análisis de los datos. Dado que los nombres de los barrios pueden estar escritos de diferentes maneras, se implementó un enfoque sistemático para unificarlos.
Primero, se utilizó la función mutate de dplyr junto con case_when para estandarizar los nombres de los barrios comunes que aparecen con variaciones. Por ejemplo, todos los registros de “Valle Del Lili”, “valle del lili” y “valle de lili” se normalizaron bajo el nombre unificado “Valle del Lili”. De manera similar, otros barrios como “Meléndez”, “El Ingenio” y “Ciudad Jardín” también fueron unificados para evitar discrepancias.
Una vez que los nombres fueron normalizados, la columna que contenía estos nombres fue integrada a la columna original de barrios y luego se eliminó la columna auxiliar que se utilizó para el proceso de normalización, ya que no era necesaria para los análisis posteriores.
Posteriormente, se realizó un filtrado adicional para eliminar barrios que no eran de interés en el análisis de la zona sur, como “Zona Sur”, “Cali” y otros barrios que no se alinean con los objetivos del estudio. Este paso permitió refinar aún más los datos y enfocarse solo en los barrios relevantes.
Finalmente, se creó un mapa interactivo que visualiza las ubicaciones de los apartamentos en la zona sur después de aplicar todos los filtros. Este mapa permite explorar de manera dinámica los barrios normalizados y analizar la distribución de precios de las propiedades en esta zona específica, ofreciendo una herramienta visual poderosa para la toma de decisiones.
# Normalizar los nombres de los barrios
vivienda_sur_aptos <- vivienda_sur_aptos %>%
mutate(barrio_normalizado = case_when(
barrio %in% c("Valle Del Lili", "valle del lili", "valle de lili") ~ "Valle del Lili",
barrio %in% c("Melendez", "melendez", "meléndez", "mel√©ndez") ~ "Meléndez",
barrio %in% c("Ingenio", "El Ingenio", "ingenio", "ingenio ii", "El Ingenio II", "ingenio 2") ~ "El Ingenio",
barrio %in% c("Gran Limonar", "El Gran Limonar", "gran limonar", "el gran limonar") ~ "El Gran Limonar",
barrio %in% c("Ciudad Melendez", "ciudad melendez", "Ciudad Mel√©ndez", "Ciudad Meléndez") ~ "Ciudad Meléndez",
barrio %in% c("Ciudad Jardín", "ciudad jardin", "Ciudad Jardin", "Ciudad Jardín Pance", "ciudad jardín") ~ "Ciudad Jardín",
barrio %in% c("Alferez Real", "alferez real", "alf√©rez real") ~ "Alférez Real",
barrio == "Cali" ~ "Cali",
TRUE ~ barrio # Mantener el nombre original si no coincide con ninguna de las condiciones anteriores
))
# Integrar la columna normalizada a la columna original de barrios
vivienda_sur_aptos <- vivienda_sur_aptos %>%
mutate(barrio = barrio_normalizado) %>%
select(-barrio_normalizado) # Eliminar la columna barrio_normalizado si ya no es necesaria
library(dplyr)
# Listado de barrios a retirar
barrios_retirar <- c("Zona Sur", "Cali", "Belisario Caicedo", "Cataya Real", "Fuentes de la",
"Pampa linda", "La Cascada", "San Fernando", "Alameda", "Colseguros",
"Colseguros Andes", "Cuarto de Legua", "El Lido", "Panamericano",
"San Bosco", "San Fernando Nuevo", "San Fernando Viejo", "Acopi",
"La Flora", "Versalles", "Vipasa", "Aguablanca", "Buenos Aires",
"Caldas", "Aguacatal", "Alto Jordán", "Altos de Guadalupe",
"Arboleda", "Bella Suiza", "Cerro Cristales", "Cristales",
"Los Farallones", "Miraflores", "Normandía", "Santa Teresita",
"Sector Aguacatal", "Seminario")
# Filtrar los datos para excluir los barrios en la lista de retiro
vivienda_sur_aptos_filtrados <- vivienda_sur_aptos %>%
filter(!barrio %in% barrios_retirar)
# Crear el mapa con las ubicaciones originales de los apartamentos en la zona sur después del filtrado
mapa_filtrado <- leaflet(vivienda_sur_aptos_filtrados) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
radius = 5,
color = "blue",
fill = TRUE,
fillOpacity = 0.7,
popup = ~paste("Barrio:", barrio, "<br>Precio: $", round(preciom, 2)),
label = ~paste("Barrio:", barrio)
) %>%
setView(lng = mean(vivienda_sur_aptos_filtrados$longitud, na.rm = TRUE),
lat = mean(vivienda_sur_aptos_filtrados$latitud, na.rm = TRUE),
zoom = 13)
# Mostrar el mapa
mapa_filtradoEl gráfico presenta un análisis de correlación entre el precio de los apartamentos en la zona sur de Cali y varias variables clave, tales como área construida, estrato, número de baños y número de habitaciones.
Área Construida: Existe una fuerte correlación positiva (0.759) con el precio, indicando que a mayor área construida, el precio del apartamento tiende a aumentar significativamente.
Estrato: La correlación con el estrato es de 0.673, lo que sugiere que los apartamentos en estratos más altos tienen precios más elevados, reflejando la influencia del nivel socioeconómico en el valor de las viviendas.
Baños y Habitaciones: Aunque con correlaciones más bajas, tanto el número de baños (0.661) como el de habitaciones (0.514) también muestran una asociación positiva con el precio, indicando que más baños y habitaciones suelen coincidir con precios más altos.
library(GGally)
library(plotly)
# Selección de variables para el análisis en la zona sur
variables_seleccionadas_sur <- vivienda_sur_aptos_filtrados[, c("preciom", "areaconst", "estrato", "banios", "habitaciones")]
# Generar el gráfico de pares (ggpairs) para las variables seleccionadas
ggpairs_plot_sur <- ggpairs(variables_seleccionadas_sur,
title = "Correlación entre Precio y Variables Seleccionadas - Zona Sur")
# Convertir el gráfico de ggpairs a un objeto plotly para interactividad
plotly_ggpairs_sur <- ggplotly(ggpairs_plot_sur)
# Mostrar el gráfico interactivo
plotly_ggpairs_surnicialmente, se identifican los valores faltantes en variables clave como área construida, estrato, habitaciones, parqueaderos y baños, encontrando que la mayoría de los valores faltantes se encuentran en la variable de parqueaderos (405 valores faltantes).
Para imputar estos valores, se calcula la moda de parqueaderos por barrio y se utilizan estos valores para rellenar los nulos. Luego de la imputación, se verifica que ya no quedan valores faltantes en ninguna de las variables.
Posteriormente, se realiza la detección de outliers utilizando el método del rango intercuartílico (IQR). Se identifican 176 outliers en área construida, 875 en número de habitaciones, 33 en parqueaderos, y 141 en baños. Estos outliers son casos que se encuentran fuera de los límites esperados. Sin embargo, debido a las características particulares del mercado inmobiliario en la zona sur de Cali, donde las propiedades pueden variar considerablemente en tamaño y características, se decide mantener estos outliers en el análisis. Esta decisión se toma para reflejar con mayor precisión la realidad del mercado y evitar la eliminación de propiedades que, aunque atípicas, son representativas de la diversidad de la zona.
Finalmente, se convierte la variable ‘estrato’ en un factor para facilitar su manejo en análisis posteriores, confirmando que la conversión se realizó correctamente. Este proceso asegura que los datos estén limpios y preparados para análisis más profundos, manteniendo la integridad y representatividad de la información sobre los apartamentos en la zona sur.
# Identificación y Tratamiento de Valores Faltantes
# Ver cuántos valores NA hay en cada columna relevante en la zona sur
na_counts_sur <- sapply(vivienda_sur_aptos_filtrados[, c("areaconst", "estrato", "habitaciones",
"parqueaderos", "banios")],
function(x) sum(is.na(x)))
# Mostrar la cantidad de valores NA en cada columna
print(na_counts_sur)## areaconst estrato habitaciones parqueaderos banios
## 0 0 0 405 0
# Asegurarse de que la columna barrio_normalizado no se elimina antes de realizar la imputación
vivienda_sur_aptos_filtrados <- vivienda_sur_aptos %>%
filter(!barrio %in% barrios_retirar)
# Función para calcular la moda
get_moda <- function(x) {
uniq_x <- unique(x)
uniq_x[which.max(tabulate(match(x, uniq_x)))]
}
# Calcular la moda de parqueaderos por barrio en la zona sur
moda_parqueaderos_sur <- aggregate(parqueaderos ~ barrio, data = vivienda_sur_aptos_filtrados, FUN = get_moda)
# Imputar los valores faltantes con la moda correspondiente al barrio
vivienda_sur_aptos_filtrados <- merge(vivienda_sur_aptos_filtrados, moda_parqueaderos_sur, by = "barrio", suffixes = c("", "_moda"))
# Reemplazar los NA en parqueaderos con la moda del barrio
vivienda_sur_aptos_filtrados$parqueaderos[is.na(vivienda_sur_aptos_filtrados$parqueaderos)] <- vivienda_sur_aptos_filtrados$parqueaderos_moda
# Eliminar la columna temporal de moda
vivienda_sur_aptos_filtrados$parqueaderos_moda <- NULL
# Verificar si se han imputado los valores faltantes
na_counts_sur_updated <- sapply(vivienda_sur_aptos_filtrados[, c("areaconst", "estrato", "habitaciones",
"parqueaderos", "banios")],
function(x) sum(is.na(x)))
print(na_counts_sur_updated)## areaconst estrato habitaciones parqueaderos banios
## 0 0 0 0 0
# Función para detectar outliers usando el método IQR
detect_outliers <- function(x) {
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
return(x < lower_bound | x > upper_bound)
}
# Identificación de outliers para cada variable en la zona sur
vivienda_sur_aptos_filtrados$outlier_areaconst <- detect_outliers(vivienda_sur_aptos_filtrados$areaconst)
vivienda_sur_aptos_filtrados$outlier_habitaciones <- detect_outliers(vivienda_sur_aptos_filtrados$habitaciones)
vivienda_sur_aptos_filtrados$outlier_parqueaderos <- detect_outliers(vivienda_sur_aptos_filtrados$parqueaderos)
vivienda_sur_aptos_filtrados$outlier_banios <- detect_outliers(vivienda_sur_aptos_filtrados$banios)
# Verificación del número de outliers detectados en cada variable
print(sapply(vivienda_sur_aptos_filtrados[, grep("outlier", colnames(vivienda_sur_aptos_filtrados))], sum))## outlier_areaconst outlier_habitaciones outlier_parqueaderos
## 176 875 33
## outlier_banios
## 141
# Convertir la variable 'estrato' a factor
vivienda_sur_aptos_filtrados$estrato <- as.factor(vivienda_sur_aptos_filtrados$estrato)
# Verificar la conversión
print(str(vivienda_sur_aptos_filtrados$estrato))## Factor w/ 4 levels "3","4","5","6": 2 1 4 2 2 1 1 1 1 3 ...
## NULL
El análisis de la regresión lineal aplicada a los datos de apartamentos en la zona sur de Cali nos proporciona una visión detallada de cómo diversas variables explicativas influyen en el precio estimado de las propiedades.
Interpretación de los Coeficientes Intercepto (-43.69): El valor negativo del intercepto sugiere que, cuando todas las variables predictoras son iguales a cero, el precio estimado es negativo, lo cual carece de interpretación práctica en este contexto. Sin embargo, este valor sirve principalmente como un ajuste en el modelo y no se debe interpretar de manera literal.
Área Construida (1.39): Este coeficiente indica que, por cada metro cuadrado adicional de área construida, el precio estimado de la propiedad aumenta en aproximadamente 1.39 millones de pesos. Este efecto es altamente significativo con un valor p menor a 2e-16, reflejando una fuerte relación positiva entre el tamaño del apartamento y su precio.
Estrato (4, 5 y 6): Los coeficientes para los estratos sugieren que a medida que aumenta el estrato, el precio también aumenta. Por ejemplo, estar en estrato 6 incrementa el precio en aproximadamente 214.8 millones de pesos comparado con el estrato base (presumiblemente estrato 3). Esta tendencia es consistente y significativa, lo que refleja la importancia del nivel socioeconómico en la determinación del precio.
Habitaciones (-11.19): Curiosamente, el coeficiente para el número de habitaciones es negativo, indicando que, al aumentar una habitación, el precio podría disminuir en unos 11.19 millones de pesos. Aunque significativo, este resultado puede sugerir que otras variables, como el área construida o el estrato, podrían estar capturando mejor el valor de la propiedad, y las habitaciones podrían estar correlacionadas de manera negativa en este modelo específico.
Parqueaderos (51.61): Este coeficiente muestra que por cada parqueadero adicional, el precio estimado de la propiedad aumenta en 51.61 millones de pesos, lo cual es altamente significativo. Esto subraya la importancia de los espacios de estacionamiento como un factor valioso en la determinación del precio de una vivienda en la zona sur.
Baños (39.97): Similar al número de parqueaderos, un baño adicional incrementa el precio en aproximadamente 40 millones de pesos. La significancia estadística alta también respalda la importancia de esta variable.
Calidad del Modelo R² (0.787) y R² ajustado (0.786): Estos valores indican que alrededor del 79% de la variabilidad en los precios de los apartamentos puede explicarse mediante las variables incluidas en el modelo. Esto sugiere un buen ajuste del modelo, aunque hay un 21% de la variabilidad que podría explicarse por otros factores no considerados en este análisis. Residuos Distribución de Residuos: La distribución de los residuos muestra una variabilidad considerable, con un rango que va desde -1147 hasta 895 millones de pesos. La mediana cercana a cero sugiere que el modelo no presenta sesgos sistemáticos, aunque los valores extremos indican que existen algunas observaciones con diferencias notables entre el precio real y el predicho.
# Estimación del modelo de regresión lineal múltiple
modelo_sur <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = vivienda_sur_aptos_filtrados)
# Resumen del modelo: Coeficientes y su significancia
modelo_sur_summary <- summary(modelo_sur)
print(modelo_sur_summary)##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = vivienda_sur_aptos_filtrados)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1147.00 -38.57 -0.09 36.28 894.82
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -43.6860 10.5261 -4.150 3.42e-05 ***
## areaconst 1.3894 0.0459 30.268 < 2e-16 ***
## estrato4 27.4344 7.1512 3.836 0.000128 ***
## estrato5 56.8540 7.3661 7.718 1.64e-14 ***
## estrato6 214.7995 9.1175 23.559 < 2e-16 ***
## habitaciones -11.1927 3.2186 -3.477 0.000514 ***
## parqueaderos 51.6129 3.2984 15.648 < 2e-16 ***
## banios 39.9746 2.8847 13.857 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 88.64 on 2760 degrees of freedom
## Multiple R-squared: 0.7868, Adjusted R-squared: 0.7863
## F-statistic: 1455 on 7 and 2760 DF, p-value: < 2.2e-16
# Resumen del modelo en un formato más ordenado usando broom
modelo_sur_tidy <- tidy(modelo_sur)
print(modelo_sur_tidy)## # A tibble: 8 × 5
## term estimate std.error statistic p.value
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -43.7 10.5 -4.15 3.42e- 5
## 2 areaconst 1.39 0.0459 30.3 4.91e-174
## 3 estrato4 27.4 7.15 3.84 1.28e- 4
## 4 estrato5 56.9 7.37 7.72 1.64e- 14
## 5 estrato6 215. 9.12 23.6 5.64e-112
## 6 habitaciones -11.2 3.22 -3.48 5.14e- 4
## 7 parqueaderos 51.6 3.30 15.6 6.04e- 53
## 8 banios 40.0 2.88 13.9 2.89e- 42
# Interpretación del coeficiente R²
r2_value_sur <- modelo_sur_summary$r.squared
adjusted_r2_value_sur <- modelo_sur_summary$adj.r.squared
cat("El valor de R² es:", r2_value_sur, "\n")## El valor de R² es: 0.7867942
## El valor de R² ajustado es: 0.7862534
Al analizar los gráficos de diagnóstico desde la perspectiva de los supuestos básicos de la regresión lineal múltiple, podemos observar lo siguiente:
Supuesto: La relación entre las variables independientes y la variable dependiente debe ser lineal. Observación: En el gráfico de “Residuals vs Fitted”, la mayoría de los residuos se distribuyen de manera aleatoria alrededor de la línea horizontal. Esto sugiere que el supuesto de linealidad se cumple en gran medida, aunque algunos outliers podrían estar afectando esta linealidad en los extremos.
Supuesto: Los residuos deben ser independientes entre sí. Observación: No se observan patrones claros en la dispersión de los residuos, lo que sugiere que los errores son independientes. No hay evidencia de autocorrelación, aunque esto se debería confirmar con un test específico como el de Durbin-Watson. Normalidad de los errores (Q-Q Residuals):
Supuesto: Los residuos deben seguir una distribución normal. Observación: El gráfico Q-Q muestra que los residuos siguen la línea diagonal en gran medida, lo que indica que los errores se aproximan a una distribución normal. Sin embargo, las desviaciones en los extremos sugieren que hay algunos outliers que podrían violar este supuesto.
Supuesto: La varianza de los errores debe ser constante a lo largo de los valores predichos. Observación: El gráfico “Scale-Location” muestra que la dispersión de los residuos estandarizados es relativamente uniforme, aunque existe una ligera tendencia en los valores altos de los ajustados. Esto sugiere una posible heterocedasticidad, pero no parece ser grave.
Supuesto: Las variables independientes no deben estar altamente correlacionadas entre sí. Observación: Este supuesto no se verifica directamente en los gráficos presentados. La multicolinealidad se examina típicamente mediante el VIF (Variance Inflation Factor), pero no hay indicios directos en estos gráficos que sugieran un problema grave de multicolinealidad.
Supuesto: No debe haber observaciones con un alto apalancamiento que influyan desproporcionadamente en el modelo. Observación: El gráfico de “Residuals vs Leverage” muestra algunos puntos con alto apalancamiento y residuos grandes, lo que indica que estos puntos son outliers influyentes. Esto podría afectar la estabilidad del modelo, y se recomienda un análisis más detallado para decidir si estos puntos deben ser eliminados o si se debe ajustar el modelo para manejar su influencia.
## Compresión del Modelo Proceso de Particionamiento de los Datos:
Fijación de la semilla:
Se utiliza set.seed(123) para asegurar que el proceso de muestreo sea reproducible. Esto garantiza que, al ejecutar el código en diferentes momentos o sistemas, se obtendrán los mismos conjuntos de entrenamiento y prueba. Particionamiento de los datos:
El código selecciona aleatoriamente el 70% de las observaciones para formar el conjunto de entrenamiento (train_set_sur). El 30% restante de los datos se reserva para el conjunto de prueba (test_set_sur). Esto es esencial para evaluar el rendimiento del modelo en datos que no se utilizaron para entrenarlo. La función sample() genera un índice aleatorio que indica qué observaciones del conjunto de datos original se asignan al entrenamiento. Estimación del modelo:
El modelo de regresión lineal múltiple se ajusta utilizando el conjunto de entrenamiento (train_set_sur). El modelo predice el precio de la vivienda (preciom) en función de cinco variables independientes: areaconst (área construida), estrato, habitaciones, parqueaderos y baños. Resumen del modelo (resultados):
Los residuales (errores) muestran una distribución cercana a cero en la mediana, lo que sugiere que no hay un sesgo claro en el modelo. El Intercepto tiene un valor negativo (-31.067), lo que implica que si todas las variables predictoras tuvieran valor cero, el precio estimado sería negativo. Esto no tiene una interpretación realista, pero es una característica común en modelos con múltiples variables, especialmente en contextos donde no todas las variables pueden realmente ser cero al mismo tiempo. Todas las variables predictoras son estadísticamente significativas al nivel del 0.01% (Pr(>|t|) muy pequeño), indicando que tienen un efecto considerable sobre el precio de la vivienda: Área construida (areaconst) tiene una relación positiva y muy fuerte con el precio, con un coeficiente de 1.44, lo que indica que por cada metro cuadrado adicional de área construida, el precio aumenta en aproximadamente 1.44 millones de pesos. Estrato 4, 5 y 6 también tienen efectos positivos sobre el precio, lo que sugiere que a medida que el estrato aumenta, el precio de la vivienda también lo hace de manera significativa. Habitaciones tiene un coeficiente negativo (-11.27), lo que indica que el aumento en el número de habitaciones se asocia con una ligera disminución en el precio, lo cual podría parecer contraintuitivo pero podría reflejar características particulares de los apartamentos en la zona sur. Parqueaderos y baños también tienen efectos significativos y positivos sobre el precio, lo que refleja que la disponibilidad de más parqueaderos y baños incrementa el valor de la vivienda. Ajuste del modelo:
El R² múltiple es de 0.7952, lo que significa que el 79.52% de la variabilidad en el precio de las viviendas es explicada por las variables predictoras en el modelo. Esto indica un buen ajuste del modelo. El R² ajustado es de 0.7945, lo que tiene en cuenta el número de variables en el modelo, mostrando que el ajuste sigue siendo fuerte incluso cuando se ajusta por el número de predictores.
# Punto 5: Particionar los Datos
set.seed(123) # Fijar la semilla para la reproducibilidad
# Crear un índice aleatorio para seleccionar el 70% de los datos para el conjunto de entrenamiento
train_index_sur <- sample(seq_len(nrow(vivienda_sur_aptos_filtrados)), size = 0.7 * nrow(vivienda_sur_aptos_filtrados))
# Crear los sets de entrenamiento y prueba
train_set_sur <- vivienda_sur_aptos_filtrados[train_index_sur, ]
test_set_sur <- vivienda_sur_aptos_filtrados[-train_index_sur, ]
# Estimar el Modelo Usando el Conjunto de Entrenamiento
# Estimar el modelo con el conjunto de entrenamiento
modelo_train_sur <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = train_set_sur)
# Mostrar un resumen del modelo
summary(modelo_train_sur)##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = train_set_sur)
##
## Residuals:
## Min 1Q Median 3Q Max
## -821.88 -37.10 -1.54 36.13 906.86
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -31.06728 11.54387 -2.691 0.00718 **
## areaconst 1.44005 0.05381 26.762 < 2e-16 ***
## estrato4 32.78701 7.80672 4.200 2.79e-05 ***
## estrato5 61.97749 8.07487 7.675 2.60e-14 ***
## estrato6 220.46949 10.14257 21.737 < 2e-16 ***
## habitaciones -11.26545 3.58796 -3.140 0.00172 **
## parqueaderos 45.38054 3.59660 12.618 < 2e-16 ***
## banios 33.44356 3.28147 10.192 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 83.36 on 1929 degrees of freedom
## Multiple R-squared: 0.7952, Adjusted R-squared: 0.7945
## F-statistic: 1070 on 7 and 1929 DF, p-value: < 2.2e-16
Se realiza una evaluación de las predicciones del modelo de regresión lineal múltiple aplicadas a los datos de prueba de la zona sur.
Paso 1: Realizar predicciones sobre el conjunto de prueba Utilizando el modelo previamente entrenado (modelo_train_sur), se generan predicciones para el conjunto de prueba (test_set_sur). Esto nos permite comparar el rendimiento del modelo sobre datos no utilizados en su entrenamiento.
Paso 2: Combinar las predicciones con los valores reales Se crea un DataFrame llamado resultados_sur que contiene dos columnas:
Real: los valores reales del precio de las viviendas en la zona sur. Prediccion: los valores predichos por el modelo. Paso 3: Visualización de las predicciones vs los valores reales Se genera un gráfico de dispersión con ggplot2 donde:
El eje x muestra los valores reales de los precios (Real). El eje y muestra las predicciones del modelo (Prediccion). La línea roja discontinua representa la línea ideal donde las predicciones coinciden exactamente con los valores reales (es decir, una pendiente de 1). Análisis de los Resultados Al observar el gráfico:
La mayoría de los puntos se concentran cerca de la línea roja, lo que indica que el modelo predice de manera precisa los precios para la mayoría de las viviendas. Sin embargo, existen algunas desviaciones, especialmente en los valores más altos, lo que sugiere que el modelo tiende a subestimar o sobreestimar algunos precios, en particular aquellos con precios más elevados.
# Paso 1: Realizar predicciones sobre el conjunto de prueba
predicciones_sur <- predict(modelo_train_sur, newdata = test_set_sur)
# Paso 2: Combinar las predicciones con los valores reales
resultados_sur <- data.frame(
Real = test_set_sur$preciom,
Prediccion = predicciones_sur
)
# Mostrar las primeras filas de las predicciones
print(head(resultados_sur))## Real Prediccion
## 3 875 692.9542
## 6 115 142.1923
## 15 175 212.8101
## 19 175 176.4194
## 21 175 179.5544
## 22 170 211.9745
# Paso 3: Visualización de las predicciones vs los valores reales
library(ggplot2)
ggplot(resultados_sur, aes(x = Real, y = Prediccion)) +
geom_point(color = "blue") +
geom_abline(intercept = 0, slope = 1, color = "red", linetype = "dashed") +
labs(title = "Predicciones vs Valores Reales - Zona Sur",
x = "Valor Real",
y = "Predicción") +
theme_minimal()Los resultados del modelo de predicción para la zona sur muestran un desempeño bastante sólido.
Error Cuadrático Medio (MSE): El valor de 10,155.47 indica que, en promedio, las predicciones del precio se desvían en esa cantidad de millones de pesos cuando se consideran los errores al cuadrado. Aunque parece alto, es razonable dado el rango de precios en la zona.
Error Absoluto Medio (MAE): El MAE de 55.77 significa que, en promedio, el modelo se equivoca por aproximadamente 55.77 millones de pesos al predecir el precio de un inmueble. Este valor nos da una idea más clara del margen de error esperado.
Coeficiente de Determinación (R²): El R² de 0.774 indica que el 77.4% de la variabilidad en los precios de los inmuebles se explica por el modelo. Esto sugiere que el modelo tiene un buen nivel de precisión, aunque hay espacio para mejorar en la predicción de algunos casos.
mse_sur <- mean((test_set_sur$preciom - predicciones_sur)^2)
# Calcular el Error Absoluto Medio (MAE)
mae_sur <- mean(abs(test_set_sur$preciom - predicciones_sur))
# Calcular el R2
r2_sur <- cor(test_set_sur$preciom, predicciones_sur)^2
# Mostrar los resultados
cat("Error Cuadrático Medio (MSE) - Zona Sur:", mse_sur, "\n")## Error Cuadrático Medio (MSE) - Zona Sur: 10155.47
## Error Absoluto Medio (MAE) - Zona Sur: 55.77361
## Coeficiente de Determinación (R2) - Zona Sur: 0.7743081
El proceso de selección de las propiedades se basó en una comparación detallada entre las características objetivo de la vivienda 2 y las ofertas disponibles en la zona sur. A continuación, se presentan las razones específicas por las cuales se seleccionaron las cinco propiedades finales:
Filtración por Precio y Estrato:
-Precio: Se filtraron las propiedades que no exceden el crédito preaprobado de 850 millones. Esto asegura que todas las opciones sean económicamente viables.
-Estrato: Solo se consideraron propiedades en estratos 5 y 6, que corresponden al estándar de vida esperado para la vivienda 2. Comparación con los Valores Objetivo:
-Área Construida: Se utilizó un valor objetivo de 300 m², lo que es representativo de un apartamento espacioso en la zona sur. Las propiedades seleccionadas tienen áreas construidas cercanas a este valor.
-Parqueaderos: Se buscó que los apartamentos tuvieran 3 parqueaderos, que es una característica importante para la comodidad y conveniencia.
-Baños y Habitaciones: La vivienda objetivo tiene 3 baños y 5 habitaciones. Se priorizaron las propiedades que se acercan a estos valores. Cálculo del Puntaje (Score):
Se calculó un puntaje basado en la diferencia entre las características de cada propiedad y los valores objetivo mencionados. Las propiedades con el menor puntaje fueron seleccionadas, ya que son las que más se acercan a cumplir con todas las especificaciones.
Selección Final:
De las propiedades disponibles, las cinco con el puntaje más bajo fueron seleccionadas. Estas propiedades ofrecen el mejor equilibrio entre todas las características deseadas, lo que justifica su selección.
library(leaflet)
library(dplyr)
# Definir los valores objetivo de la vivienda 2
area_objetivo <- 300
parqueaderos_objetivo <- 3
banios_objetivo <- 3
habitaciones_objetivo <- 5
estrato_objetivo <- c(5, 6)
precio_maximo <- 850 # Crédito preaprobado en millones
# Filtrar por precio, estrato y calcular la diferencia con los valores objetivo
ofertas_cercanas <- test_set_sur %>%
filter(preciom <= precio_maximo & estrato %in% estrato_objetivo) %>%
mutate(
score = abs(areaconst - area_objetivo) +
abs(parqueaderos - parqueaderos_objetivo) +
abs(banios - banios_objetivo) +
abs(habitaciones - habitaciones_objetivo)
) %>%
arrange(score) %>%
head(5) # Seleccionar las 5 ofertas más cercanas
# Verificar si hay propiedades que cumplan con los criterios
if (nrow(ofertas_cercanas) == 0) {
cat("No se encontraron propiedades que cumplan con los criterios de la vivienda 2.\n")
} else {
# Crear el mapa interactivo con las 5 ofertas seleccionadas
mapa_ofertas_sur <- leaflet(ofertas_cercanas) %>%
addTiles() %>%
addCircleMarkers(
lng = ~longitud,
lat = ~latitud,
radius = 8,
color = "blue",
fill = TRUE,
fillOpacity = 0.6,
popup = ~paste(
"Barrio:", barrio, "<br>",
"Precio Estimado: $", round(preciom, 2), "millones<br>",
"Área Construida:", areaconst, "m2<br>",
"Estrato:", estrato, "<br>",
"Habitaciones:", habitaciones, "<br>",
"Parqueaderos:", parqueaderos, "<br>",
"Baños:", banios
),
label = ~paste("Precio: $", round(preciom, 2), "millones")
) %>%
setView(lng = mean(ofertas_cercanas$longitud, na.rm = TRUE),
lat = mean(ofertas_cercanas$latitud, na.rm = TRUE),
zoom = 13)
# Mostrar el mapa
print(mapa_ofertas_sur)
# Generar la tabla con las características de los apartamentos seleccionados
tabla_ofertas <- ofertas_cercanas %>%
select(areaconst, parqueaderos, banios, habitaciones, estrato, zona, barrio, preciom)
# Mostrar la tabla
print(tabla_ofertas)
}## areaconst parqueaderos banios habitaciones estrato zona
## 1 295.55 2 4 4 5 Zona Sur
## 2 275.00 2 5 5 5 Zona Sur
## 3 260.00 1 5 5 5 Zona Sur
## 4 257.00 2 4 3 5 Zona Sur
## 5 250.00 2 4 5 6 Zona Sur
## barrio preciom
## 1 cuarto de legua 410
## 2 ciudadela pasoancho 650
## 3 El Ingenio 480
## 4 el refugio 550
## 5 el ingenio 700
Priorizar el tamaño y la ubicación: El área construida y el estrato socioeconómico son los principales factores que influyen en el precio de las propiedades. Se recomienda enfocar las compras en viviendas amplias y en estratos altos (5 y 6), ya que estos ofrecen un mayor potencial de revalorización.
Ajuste al presupuesto: Para la vivienda en la zona norte, un presupuesto de hasta 350 millones es adecuado para encontrar opciones que satisfagan las necesidades de espacio y comodidad sin comprometer la viabilidad económica. En la zona sur, el presupuesto de 850 millones permite adquirir propiedades de alta calidad con características premium.
Selección estratégica: Las propiedades seleccionadas cumplen con los requisitos clave y ofrecen un buen equilibrio entre precio y características. Esto asegura que las inversiones sean sólidas y ajustadas a las expectativas de la empresa.
Monitoreo y precaución: Aunque el modelo predictivo es robusto, se recomienda estar atento a las fluctuaciones del mercado y realizar inspecciones detalladas de las propiedades para evitar sorpresas y maximizar el retorno de inversión.
Diversificación: La adquisición de propiedades en ambas zonas (norte y sur) permite diversificar la inversión, lo que puede proteger ante posibles variaciones en el mercado inmobiliario de Cali