# 0. Preparación y carga de paquetes (Optimizado)
if(!require(devtools)) install.packages("devtools")## Loading required package: devtools
## Loading required package: usethis
## Loading required package: dplyr
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
## Loading required package: leaflet
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.6'
## (as 'lib' is unspecified)
## Warning: `install_github()` was deprecated in devtools 2.5.0.
## ℹ Please use pak::pak("user/repo") instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Downloading GitHub repo centromagis/paqueteMODELOS@HEAD
##
## ── R CMD build ─────────────────────────────────────────────────────────────────
## checking for file ‘/tmp/Rtmp11soB5/remotes224e4944c044/Centromagis-paqueteMODELOS-3b06257/DESCRIPTION’ ... ✔ checking for file ‘/tmp/Rtmp11soB5/remotes224e4944c044/Centromagis-paqueteMODELOS-3b06257/DESCRIPTION’ (597ms)
## ─ preparing ‘paqueteMODELOS’:
## checking DESCRIPTION meta-information ... ✔ checking DESCRIPTION meta-information
## ─ checking for LF line-endings in source and make files and shell scripts (561ms)
## ─ checking for empty or unneeded directories
## ─ building ‘paqueteMODELOS_0.1.0.tar.gz’
## Warning: invalid uid value replaced by that for user 'nobody'
##
##
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.6'
## (as 'lib' is unspecified)
## Loading required package: boot
## Loading required package: broom
## Loading required package: GGally
## Loading required package: ggplot2
## Loading required package: gridExtra
##
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
## Loading required package: knitr
## Loading required package: summarytools
## Warning in fun(libname, pkgname): couldn't connect to display ":0"
## system might not have X11 capabilities; in case of errors when using dfSummary(), set st_options(use.x11 = FALSE)
data("vivienda")
# Carga la librería de los datos
library(paqueteMODELOS)
library(dplyr)
library(leaflet)
# Cargamos la base completa
data("vivienda")
# 1. Filtrar la base de datos (base1: casas, zona norte)
# Usamos filter para limpiar datos vacíos en coordenadas y evitar errores en el mapa
base1 <- vivienda %>%
filter(tipo == "Casa", zona == "Zona Norte") %>%
filter(!is.na(longitud) & !is.na(latitud))
# 2. Presentar los primeros 3 registros
print("--- Primeros 3 registros de la base filtrada ---")## [1] "--- Primeros 3 registros de la base filtrada ---"
## [1] "--- Comprobación de Tipo de Vivienda ---"
##
## Casa
## 722
## [1] "--- Comprobación de Zona ---"
##
## Zona Norte
## 722
# 4. Creación del Mapa Optimizado
mapa_base1 <- leaflet(base1) %>%
addTiles() %>%
addMarkers(
lng = ~longitud,
lat = ~latitud,
# El popup mostrará el precio y el barrio al hacer clic
popup = ~paste("Barrio:", barrio, "<br>Precio:", preciom, "M"),
# clusterOptions es VITAL en Posit Cloud para no saturar la memoria de video/RAM
clusterOptions = markerClusterOptions()
)
# Mapa
mapa_base1Para responder a la primera solicitud, se realizó un filtro a la base de datos original aislando exclusivamente las ofertas correspondientes a Casas ubicadas en la Zona Norte de la ciudad[cite: 1]. Tras el filtro, se obtuvo un subconjunto de 722 registros.
Discusión sobre la ubicación geográfica (Análisis del Mapa): Al proyectar las coordenadas geográficas de esta base filtrada en el mapa interactivo, se identificó un comportamiento inusual: no todos los puntos se ubican geográficamente en la Zona Norte[cite: 1].
# ---------------------------------------------------------
# VALIDACIÓN DE VARIABLES
# ---------------------------------------------------------
# 1. Resumen estadístico: mostrará min, max, media y la cantidad de NAs de cada variable
print("--- Resumen Estadístico de las Variables ---")## [1] "--- Resumen Estadístico de las Variables ---"
## id zona piso estrato
## Min. : 58.0 Length :722 Length :722 Min. :3.000
## 1st Qu.: 766.2 N.unique : 1 N.unique : 5 1st Qu.:3.000
## Median :2257.0 N.blank : 0 N.blank : 0 Median :4.000
## Mean :2574.6 Min.nchar: 10 Min.nchar: 2 Mean :4.202
## 3rd Qu.:4225.0 Max.nchar: 10 Max.nchar: 2 3rd Qu.:5.000
## Max. :8319.0 NAs :372 Max. :6.000
##
## preciom areaconst parqueaderos banios
## Min. : 89.0 Min. : 30.0 Min. : 1.000 Min. : 0.000
## 1st Qu.: 261.2 1st Qu.: 140.0 1st Qu.: 1.000 1st Qu.: 2.000
## Median : 390.0 Median : 240.0 Median : 2.000 Median : 3.000
## Mean : 445.9 Mean : 264.9 Mean : 2.182 Mean : 3.555
## 3rd Qu.: 550.0 3rd Qu.: 336.8 3rd Qu.: 3.000 3rd Qu.: 4.000
## Max. :1940.0 Max. :1440.0 Max. :10.000 Max. :10.000
## NAs :287
## habitaciones tipo barrio longitud
## Min. : 0.000 Length :722 Length :722 Min. :-76.59
## 1st Qu.: 3.000 N.unique : 1 N.unique :103 1st Qu.:-76.53
## Median : 4.000 N.blank : 0 N.blank : 0 Median :-76.52
## Mean : 4.507 Min.nchar: 4 Min.nchar: 4 Mean :-76.52
## 3rd Qu.: 5.000 Max.nchar: 4 Max.nchar: 25 3rd Qu.:-76.50
## Max. :10.000 Max. :-76.47
##
## latitud
## Min. :3.333
## 1st Qu.:3.452
## Median :3.468
## Mean :3.460
## 3rd Qu.:3.482
## Max. :3.496
##
## [1] "--- Cantidad de NAs por columna ---"
## id zona piso estrato preciom areaconst
## 0 0 372 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 287 0 0 0 0 0
## latitud
## 0
# ---------------------------------------------------------
# IMPUTACIÓN DE DATOS NULOS
# ---------------------------------------------------------
# Imputamos los NAs de 'parqueaderos' usando la mediana de esa misma columna
base1 <- base1 %>%
mutate(
parqueaderos = ifelse(is.na(parqueaderos),
median(parqueaderos, na.rm = TRUE),
parqueaderos)
)
# Verificamos que ya no existan NAs en la columna parqueaderos
print("--- NAs restantes en parqueaderos tras la imputación ---")## [1] "--- NAs restantes en parqueaderos tras la imputación ---"
## [1] 0
# ---------------------------------------------------------
# PASO 2: ANÁLISIS EXPLORATORIO DE DATOS (Correlación)
# ---------------------------------------------------------
# Instalar y cargar plotly
if(!require(plotly)) install.packages("plotly")## Loading required package: plotly
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(plotly)
# Seleccionamos solo las variables numéricas solicitadas para correlacionar con el precio
# y usamos na.omit() para limpiar las filas incompletas momentáneamente
datos_correlacion <- base1 %>%
select(preciom, areaconst, estrato, banios, habitaciones) %>%
na.omit()
# Calculamos la matriz de correlación
matriz_cor <- cor(datos_correlacion)
# Generamos el gráfico de calor (Heatmap) interactivo con plotly
mapa_calor <- plot_ly(
z = matriz_cor,
x = colnames(matriz_cor),
y = colnames(matriz_cor),
type = "heatmap",
colorscale = "RdBu", # Rojo para correlación negativa, Azul para positiva
zmin = -1, zmax = 1
) %>%
layout(title = "Matriz de Correlación - Casas Zona Norte (Interactiva)")
# Mostrar el gráfico interactivo
mapa_calorAl analizar la relación de las variables independientes con la variable respuesta (preciom), observamos lo siguiente:
Mayor impacto en el precio: Las variables areaconst (área construida) y estrato muestran los tonos rojizos más intensos al cruzarse con el precio. Esto indica una fuerte correlación positiva. Tiene total lógica comercial: las casas más grandes y ubicadas en mejores estratos tienden a ser significativamente más costosas.
Impacto moderado: La variable banios (número de baños) presenta un tono salmón/naranja intermedio, lo que sugiere una correlación positiva moderada con el valor del inmueble.
Menor impacto (Dato curioso): La variable habitaciones muestra el tono más pálido (casi beige) frente al precio. Esto significa que la cantidad de cuartos tiene una correlación muy débil. Esto puede explicarse porque en la Zona Norte (estratos altos), una casa muy costosa no necesariamente tiene muchas habitaciones, sino que puede tener pocas habitaciones pero de gran tamaño y lujo.
# ---------------------------------------------------------
# PASO 3: MODELO DE REGRESIÓN LINEAL MÚLTIPLE
# ---------------------------------------------------------
# Estimamos el modelo con las variables solicitadas
modelo_norte <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base1)
# Generamos el resumen estadístico del modelo para ver los coeficientes y el R^2
print("--- Resumen del Modelo de Regresión (Zona Norte) ---")## [1] "--- Resumen del Modelo de Regresión (Zona Norte) ---"
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = base1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -924.94 -77.71 -17.66 45.90 1081.29
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -251.05177 30.11848 -8.335 3.94e-16 ***
## areaconst 0.81090 0.04352 18.634 < 2e-16 ***
## estrato 84.61108 7.17727 11.789 < 2e-16 ***
## habitaciones 0.95948 4.10569 0.234 0.81529
## parqueaderos 16.55976 5.70396 2.903 0.00381 **
## banios 24.57669 5.35583 4.589 5.26e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 158.2 on 716 degrees of freedom
## Multiple R-squared: 0.6548, Adjusted R-squared: 0.6524
## F-statistic: 271.6 on 5 and 716 DF, p-value: < 2.2e-16
1. Significancia de los Coeficientes y Lógica Comercial Al evaluar el modelo estimado para la Zona Norte, encontramos lo siguiente:
2. Ajuste del Modelo (\(R^2\)) e Implicaciones * Ajuste: El modelo presenta un \(R^2\) múltiple de 0.6548. Esto significa que las variables incluidas explican el 65.48% de la variabilidad de los precios de las casas en la Zona Norte. * Implicaciones: Es un ajuste aceptable, pero señala que casi un 34.5% de la variación del precio obedece a factores externos no contemplados. * Sugerencias de mejora: Para optimizar el modelo, se podrían incluir variables adicionales como la antigüedad del inmueble, la presencia de vigilancia privada o si está en conjunto cerrado. También se podría explorar una transformación logarítmica de la variable precio para suavizar posibles valores atípicos.
# ---------------------------------------------------------
# PASO 4: VALIDACIÓN DE SUPUESTOS DEL MODELO
# ---------------------------------------------------------
# Configuramos la ventana gráfica para ver 4 gráficos al mismo tiempo
par(mfrow = c(2, 2))
# Generamos los gráficos de diagnóstico del modelo
plot(modelo_norte)A partir del análisis gráfico de los residuos (errores del modelo), se identifican los siguientes comportamientos respecto a los supuestos teóricos:
Sugerencias de mejora (Qué se podría hacer): 1.
Transformación Logarítmica: Para corregir los problemas
de normalidad y heterocedasticidad, la solución estadística más común y
recomendada es aplicar el logaritmo natural a la variable dependiente
(precio). Modelar log(preciom) suele estabilizar la
varianza en datos inmobiliarios. 2. Tratamiento de valores
atípicos: Se debe revisar el registro de las casas que aparecen
como extremas (como la 632) para verificar si hubo un error de
digitación en el área o en el precio y evaluar su exclusión del conjunto
de datos de entrenamiento.
# ---------------------------------------------------------
# PASO 5: PREDICCIÓN DEL PRECIO DE LA VIVIENDA 1
# ---------------------------------------------------------
# 1. Creamos un data frame con las características de la solicitud 1.
# Hacemos dos filas: una para estrato 4 y otra para estrato 5.
solicitud_1 <- data.frame(
areaconst = c(200, 200),
estrato = c(4, 5),
habitaciones = c(4, 4),
parqueaderos = c(1, 1),
banios = c(2, 2)
)
# 2. Usamos la función predict() con el modelo
predicciones <- predict(modelo_norte, newdata = solicitud_1)
# 3. Organizamos los resultados en una tabla para verlos claros
resultados_paso5 <- data.frame(
Escenario = c("Estrato 4", "Estrato 5"),
Precio_Estimado_Millones = round(predicciones, 2)
)
print("--- Predicción de Precio para la Vivienda 1 ---")## [1] "--- Predicción de Precio para la Vivienda 1 ---"
## Escenario Precio_Estimado_Millones
## 1 Estrato 4 319.12
## 2 Estrato 5 403.74
Utilizando el modelo de regresión lineal múltiple, estimamos el valor de mercado para una casa en la Zona Norte con 200 m² de área construida, 4 habitaciones, 2 baños y 1 parqueadero, evaluando los dos estratos solicitados:
Conclusión financiera: Dado que la compañía internacional cuenta con un crédito preaprobado máximo de 350 millones de pesos, la búsqueda real de ofertas deberá concentrarse en inmuebles de estrato 4. Buscar esta propiedad en estrato 5 requeriría un esfuerzo de negociación poco realista (buscar un descuento de más de 50 millones respecto al valor de mercado estimado).
# ---------------------------------------------------------
# PASO 6: SUGERENCIA DE 5 OFERTAS POTENCIALES
# ---------------------------------------------------------
# Filtramos la base buscando propiedades reales que se ajusten al presupuesto y área
ofertas_potenciales <- base1 %>%
filter(preciom <= 350) %>% # Límite estricto del crédito
filter(estrato %in% c(4, 5)) %>% # Estratos solicitados
filter(areaconst >= 150) %>% # Área aceptable cercana a la solicitud
arrange(abs(areaconst - 200)) %>% # Ordenamos para que las más cercanas a 200m2 queden de primeras
head(5) # Tomamos el Top 5
# Opciones
print("--- Top 5 Ofertas Reales para el Cliente ---")## [1] "--- Top 5 Ofertas Reales para el Cliente ---"
A partir de las predicciones del modelo y considerando la restricción del crédito preaprobado (350 millones de pesos), se realizó una búsqueda de propiedades reales en la base de datos. Se seleccionaron 5 ofertas potenciales que cumplen con los requerimientos:
# ---------------------------------------------------------
# PASO 7: SEGUNDA SOLICITUD (APARTAMENTO EN EL SUR)
# ---------------------------------------------------------
# 1. Filtro y limpieza de datos (Base 2: Apartamentos, Zona Sur)
base2 <- vivienda %>%
filter(tipo == "Apartamento", zona == "Zona Sur") %>%
filter(!is.na(longitud) & !is.na(latitud)) %>%
# Imputamos NAs en parqueaderos para no perder datos
mutate(parqueaderos = ifelse(is.na(parqueaderos),
median(parqueaderos, na.rm = TRUE),
parqueaderos))
# 2. Estimación del Modelo para el Sur
modelo_sur <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = base2)
print("--- Resumen del Modelo (Apartamentos Zona Sur) ---")## [1] "--- Resumen del Modelo (Apartamentos Zona Sur) ---"
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = base2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1151.66 -37.75 -2.59 38.06 922.20
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -266.91089 12.89132 -20.705 < 2e-16 ***
## areaconst 1.36019 0.04843 28.084 < 2e-16 ***
## estrato 59.23620 2.66624 22.217 < 2e-16 ***
## habitaciones -17.89121 3.32828 -5.376 8.27e-08 ***
## parqueaderos 73.20959 3.65913 20.007 < 2e-16 ***
## banios 44.71978 2.98956 14.959 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 92.99 on 2781 degrees of freedom
## Multiple R-squared: 0.7648, Adjusted R-squared: 0.7643
## F-statistic: 1808 on 5 and 2781 DF, p-value: < 2.2e-16
# 3. Predicción para la Solicitud 2 (Estratos 5 y 6)
solicitud_2 <- data.frame(
areaconst = c(300, 300),
estrato = c(5, 6),
habitaciones = c(5, 5),
parqueaderos = c(3, 3),
banios = c(3, 3)
)
predicciones_sur <- predict(modelo_sur, newdata = solicitud_2)
resultados_sur <- data.frame(
Escenario = c("Estrato 5", "Estrato 6"),
Precio_Estimado_Millones = round(predicciones_sur, 2)
)
print("--- Predicción de Precio para la Vivienda 2 ---")## [1] "--- Predicción de Precio para la Vivienda 2 ---"
## Escenario Precio_Estimado_Millones
## 1 Estrato 5 701.66
## 2 Estrato 6 760.90
1. Interpretación del Modelo (Apartamentos Zona Sur) Al estimar el modelo de regresión lineal para la segunda solicitud, se observan dinámicas de mercado distintas a las de las casas en el norte:
2. Predicción del Precio (Vivienda 2) Se estimó el valor para un apartamento en la Zona Sur con 300 m², 5 habitaciones, 3 parqueaderos y 3 baños:
Conclusión financiera: Dado que la compañía cuenta con un crédito preaprobado de 850 millones de pesos, el cliente tiene amplia capacidad de compra. Puede adquirir un apartamento que cumpla con todas sus exigencias en el estrato más alto (estrato 6) y aún le sobraría un margen de negociación de casi 90 millones de pesos respecto al valor proyectado.
# ---------------------------------------------------------
# OFERTAS POTENCIALES - SOLICITUD 2
# ---------------------------------------------------------
# Filtramos propiedades reales (Presupuesto máx: 850M, Área cercana a 300)
ofertas_sur <- base2 %>%
filter(preciom <= 850) %>%
filter(estrato %in% c(5, 6)) %>%
filter(areaconst >= 250) %>%
arrange(abs(areaconst - 300)) %>%
head(5)
# Tabla
print("--- Top 5 Ofertas Reales (Apartamentos Zona Sur) ---")## [1] "--- Top 5 Ofertas Reales (Apartamentos Zona Sur) ---"
Para responder definitivamente a la segunda solicitud, se filtró la base de datos buscando apartamentos en la Zona Sur que cumplieran con el crédito preaprobado de 850 millones de pesos.
Tras aplicar técnicas de modelación estadística y realizar un análisis espacial detallado de la base de datos de C&A, presentamos las siguientes conclusiones generales para responder a la solicitud de la compañía internacional[cite: 1]: