Enunciado

Maria comenzó como agente de bienes raíces en Cali hace 10 años. Después de laborar dos años para una empresa nacional, se traslado a Bogotá y trabajó para otra agencia de bienes raíces. Sus amigos y familiares la convencieron de que con su experiencia y conocimientos del negocio debía abrir su propia agencia. Terminó por adquirir la licencia de intermediario y al poco tiempo fundó su propia compañía, C&A (Casas y Apartamentos) en Cali. Santiago y Lina, dos vendedores de la empresa anterior aceptaron trabajar en la nueva compaña. En la actualidad ocho agentes de bienes raíces colaboran con ella en C&A.

Actualmente las ventas de bienes raíces en Cali se han visto disminuidas de manera significativa en lo corrido del año. Durante este periodo muchas instituciones bancarias de ahorro y vivienda están prestando grandes sumas de dinero para la industria y la construcción comercial y residencial. Cuando el efecto producto de las tensiones políticas y sociales disminuya, se espera que la actividad económica de este sector se reactive.

Hace dos días, María recibió una carta solicitando asesoría para la compra de dos viviendas por parte de una compañía internacional que desea ubicar a dos de sus empleados con sus familias en la ciudad. Las solicitudes incluyen las siguientes condiciones:


Frecuencia


Obtención de los Resultados

# Cargue de librerias
library(dlookr); library(paqueteMODELOS); library(leaflet); library(VIM)
library(dplyr); library(ggplot2); library(gridExtra); library(dplyr)
library(plotly); library(broom); library(tidyr)

# Cargue de los datos
data("vivienda"); data <- vivienda; head(vivienda)
## # A tibble: 6 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1147 Zona O… <NA>        3     250        70            1      3            6
## 2  1169 Zona O… <NA>        3     320       120            1      2            3
## 3  1350 Zona O… <NA>        3     350       220            2      2            4
## 4  5992 Zona S… 02          4     400       280            3      5            3
## 5  1212 Zona N… 01          5     260        90            1      2            3
## 6  1724 Zona N… 01          5     240        87            1      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Analisis Vivienda 2: Apartamentos en la Zona Sur

Para facilitar una visualización más clara de la base de datos, se filtra y se proyecta en el mapa para confirmar que la selección de Casas en la Zona Norte sea la correcta.

# 1.1 Filtro a la base de datos, Seleccion de Zona Norte y Tipo: Casa
data_apartamentos <- subset(data, zona == "Zona Sur" & tipo == "Apartamento") # Filtro por filas
head(data_apartamentos, 3) # Mostrar los primeros 3 registros
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  5098 Zona S… 05          4     290        96            1      2            3
## 2   698 Zona S… 02          3      78        40            1      1            2
## 3  8199 Zona S… <NA>        6     875       194            2      5            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
table(data_apartamentos$zona); table(data_apartamentos$tipo) # Generar algunas tablas para comprobar la consulta
## 
## Zona Sur 
##     2787
## 
## Apartamento 
##        2787
leaflet(data_apartamentos %>% filter(!is.na(latitud), !is.na(longitud))) %>%
  addTiles() %>% addCircleMarkers(~longitud, ~latitud, color = "blue", radius = 5) %>%
  setView(lng = mean(data_apartamentos$longitud, na.rm = TRUE), lat = mean(data_apartamentos$latitud, na.rm = TRUE), zoom = 12) %>%
  addControl("<h3>Apartamentos Zona Sur - BD Sin Depurar</h3>", position = "topleft")

Se observa que hay numerosos puntos que no corresponden con la ubicación de Apartamentos en la Zona Sur de Cali. Para depurar los datos y realizar un análisis más preciso, se aplicó un filtro de valores atípicos utilizando los cuartiles, con el objetivo de reducir el margen de error en la ubicación.

Procesamiento de datos

# Eliminación de columnas innecesarias para el análisis
data_apartamentos <- data_apartamentos %>% select(preciom, areaconst, estrato, habitaciones, parqueaderos, banios, longitud, latitud) 
# Convertir la variable 'estrato' en categórica
data_apartamentos$estrato <- as.factor(data_apartamentos$estrato); str(data_apartamentos$estrato)
##  Factor w/ 4 levels "3","4","5","6": 2 1 4 1 1 2 1 1 1 2 ...
# Tratamiento de valores nulos
data_apartamentos <- data_apartamentos[data_apartamentos$habitaciones != 0 & data_apartamentos$banios != 0, ]

Se llevó a cabo un análisis en el que se determinó que las viviendas sin baños ni habitaciones podrían clasificarse como lotes o parqueaderos. Por esta razón, se excluyeron estos datos del análisis.

# Tratamiento de outliers de las variables longitud y latitud
###################################################################
# Inicializar variables
threshold <- 0.01; max_iter <- 10; data_original <- data_apartamentos
percent_outliers <- numeric(max_iter); iterations <- numeric(max_iter)
# Filtrar y registrar datos
for (iter in 1:max_iter) {
  q25_lat <- quantile(data_apartamentos$latitud, 0.25, na.rm = TRUE)
  q75_lat <- quantile(data_apartamentos$latitud, 0.75, na.rm = TRUE)
  iqr_lat <- IQR(data_apartamentos$latitud, na.rm = TRUE)
  q25_lon <- quantile(data_apartamentos$longitud, 0.25, na.rm = TRUE)
  q75_lon <- quantile(data_apartamentos$longitud, 0.75, na.rm = TRUE)
  iqr_lon <- IQR(data_apartamentos$longitud, na.rm = TRUE)
  data_apartamentos <- data_apartamentos %>%
    filter(between(latitud, q25_lat - 1.5 * iqr_lat, q75_lat + 1.5 * iqr_lat),
           between(longitud, q25_lon - 1.5 * iqr_lon, q75_lon + 1.5 * iqr_lon))
  
  percent_outliers[iter] <- (1 - nrow(data_apartamentos) / nrow(data_original)) * 100
  iterations[iter] <- iter
  
  if ((1 - nrow(data_apartamentos) / nrow(data_original)) <= threshold) break
}
# Graficar porcentaje de valores atípicos
ggplot(data.frame(Iteration = iterations[1:iter], PercentOutliers = percent_outliers[1:iter]), 
       aes(x = Iteration, y = PercentOutliers)) +
  geom_line() + geom_point() +
  labs(title = "Porcentaje de Valores Atípicos por Iteración", x = "Número de Iteración", y = "Porcentaje de Valores Atípicos (%)") +
  theme_minimal()

# Crear el mapa
leaflet(data_apartamentos %>% filter(!is.na(latitud), !is.na(longitud))) %>%
  addTiles() %>%
  addCircleMarkers(~longitud, ~latitud, color = "blue", radius = 5) %>%
  setView(lng = mean(data_apartamentos$longitud, na.rm = TRUE), lat = mean(data_apartamentos$latitud, na.rm = TRUE), zoom = 12) %>%
  addControl(paste0("<h3>Apartamentos Zona Sur - Iteración ", iter, "</h3>"), position = "topleft")

Podemos observar que, tras 5 iteraciones, el filtro de datos por cuartiles aplicado a las variables de latitud y longitud se estabilizó. Además, el mapa resultante muestra una visualización más depurada y concentrada en la Zona Sur, lo que permitirá realizar un análisis más preciso del modelo, sin embargo aun se observan valores atipicos que no se lograron corregir con este metodo.

Datos Missing e Imputación

data_apartamentos <- data_apartamentos %>% select(preciom, areaconst, estrato, habitaciones, parqueaderos, banios)
# Tratamiento de NA
###################################################################
# Calcular la correlación entre parqueaderos y preciom antes de la imputación
cor_before <- cor(data_apartamentos$parqueaderos, data_apartamentos$preciom, use = "complete.obs")
# Recuento y porcentaje de NA por variable sin imputación
na_summary <- data_apartamentos %>%  summarise(across(everything(), ~sum(is.na(.)))) %>%
  pivot_longer(cols = everything(), names_to = "variable", values_to = "count_na") %>%
  mutate(percent_na = count_na / nrow(data_apartamentos) * 100)
print(na_summary)
## # A tibble: 6 × 3
##   variable     count_na percent_na
##   <chr>           <int>      <dbl>
## 1 preciom             0          0
## 2 areaconst           0          0
## 3 estrato             0          0
## 4 habitaciones        0          0
## 5 parqueaderos      357         14
## 6 banios              0          0

Tenemos 357 datos faltantes en la variable “parqueaderos”, lo que representa el 14% del total. Se decidió realizar una imputación utilizando la técnica de KNN para abordar este problema.

# Imputar con KNN
##############################################
data_apartamentos_imputado <- kNN(data_apartamentos, variable = "parqueaderos")
# Comparar distribuciones
data_apartamentos %>%  mutate(source = ifelse(is.na(parqueaderos), "Original NA", "Original Not NA")) %>%
  bind_rows(data_apartamentos_imputado %>% mutate(source = "Imputado")) %>% ggplot(aes(x = parqueaderos, fill = source)) +
  geom_density(alpha = 0.5) + labs(title = "Distribución de 'parqueaderos': Original vs Imputado", x = "Valor de parqueaderos", y = "Densidad") + theme_minimal()

# Recuento y porcentaje de NA por variable con imputación
na_summary <- data_apartamentos_imputado %>%  summarise(across(everything(), ~sum(is.na(.)))) %>%
  pivot_longer(cols = everything(), names_to = "variable", values_to = "count_na") %>%
  mutate(percent_na = count_na / nrow(data_apartamentos) * 100)
print(na_summary)
## # A tibble: 7 × 3
##   variable         count_na percent_na
##   <chr>               <int>      <dbl>
## 1 preciom                 0          0
## 2 areaconst               0          0
## 3 estrato                 0          0
## 4 habitaciones            0          0
## 5 parqueaderos            0          0
## 6 banios                  0          0
## 7 parqueaderos_imp        0          0
# Calcular la correlación entre parqueaderos y preciom después de la imputación
cor_after <- cor(data_apartamentos_imputado$parqueaderos, data_apartamentos_imputado$preciom, use = "complete.obs")
# Crear un dataframe con las correlaciones antes y después
correlation_comparison <- data.frame(
  Metodo = c("Antes de imputación", "Después de imputación"),
  Correlacion = c(cor_before, cor_after)
)
# Mostrar el dataframe con las correlaciones
print(correlation_comparison)
##                  Metodo Correlacion
## 1   Antes de imputación   0.7322150
## 2 Después de imputación   0.7472423

Después de la imputación, no quedan valores faltantes en las variables, lo que confirma la efectividad del método KNN utilizado. Además, la correlación entre “parqueaderos” y “preciom” aumentó de 0.7322150 a 0.7472423, no es un cambio significativo pero ayudara a la calidad y precisión del análisis, lo que resulta en un modelo predictivo más robusto.

Análisis exploratorio de los datos

Variables Numericas:

# 2.1. Análisis de Variables Numéricas
###################################################################
# 2.1.1. Matriz de Correlación
# Seleccionar variables numéricas
datos_numericos <- data_apartamentos %>% select(preciom, areaconst, banios, habitaciones, parqueaderos)
# Calcular matriz de correlación
corr_matrix <- cor(datos_numericos, use = "complete.obs")
# Convertir a formato largo
corr_long <- as.data.frame(as.table(corr_matrix))
# Graficar heatmap
plot_ly(corr_long, x = ~Var2, y = ~Var1, z = ~Freq, type = 'heatmap',
        colorscale = 'Viridis', text = ~paste0(round(Freq, 2)), texttemplate = '%{text}') %>%
  layout(title = 'Matriz de Correlación entre Variables Numéricas',
         xaxis = list(title = 'Variables'),
         yaxis = list(title = 'Variables'))

Matriz de Correlación: La matriz de correlación entre las variables numéricas muestra relaciones importantes entre ellas:

  • Área Construida y Parqueaderos tienen la correlación más fuerte con el Precio (0.73 cada uno). Estas son las variables más influyentes en el valor de la propiedad.

  • Baños también muestra una correlación moderada con el precio (0.71), indicando que un mayor número de baños generalmente se asocia con precios más altos.

  • Habitaciones tiene una correlación más baja con el precio (0.31), sugiriendo que, aunque influye, su impacto es menor comparado con el área construida y los parqueaderos.

# 2.1.2. Gráficos de Dispersión
# Crear gráficos de dispersión
plots_numeric <- list(
  plot_ly(data_apartamentos, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers',
          name = 'Precio vs Área Construida') %>%
    layout(title = 'Precio vs Área Construida',
           xaxis = list(title = 'Área Construida'), 
           yaxis = list(title = 'Precio'),
           legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2)), # Leyenda debajo del título
  
  plot_ly(data_apartamentos, x = ~banios, y = ~preciom, type = 'scatter', mode = 'markers',
          name = 'Precio vs Número de Baños') %>%
    layout(title = 'Precio vs Número de Baños',
           xaxis = list(title = 'Número de Baños'), 
           yaxis = list(title = 'Precio'),
           legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2)), # Leyenda debajo del título
  
  plot_ly(data_apartamentos, x = ~habitaciones, y = ~preciom, type = 'scatter', mode = 'markers',
          name = 'Precio vs Número de Habitaciones') %>%
    layout(title = 'Precio vs Número de Habitaciones',
           xaxis = list(title = 'Número de Habitaciones'), 
           yaxis = list(title = 'Precio'),
           legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2)), # Leyenda debajo del título
  
  plot_ly(data_apartamentos, x = ~parqueaderos, y = ~preciom, type = 'scatter', mode = 'markers',
          name = 'Precio vs Número de Parqueaderos') %>%
    layout(title = 'Precio vs Número de Parqueaderos',
           xaxis = list(title = 'Número de Parqueaderos'), 
           yaxis = list(title = 'Precio'),
           legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2))  # Leyenda debajo del título
)

# Mostrar gráficos en un layout de 2x2
subplot(plots_numeric, nrows = 2, margin = 0.05) %>%
  layout(title = 'Diagramas de Dispersión de Variables Numéricas',
         showlegend = TRUE) # Asegúrate de que la leyenda se muestre

Diagramas de Dispersión:

  • Área Construida es el factor más fuerte en la determinación del precio: a mayor área, mayor precio.
  • Número de Baños también muestra una relación positiva con el precio: más baños suelen estar asociados con precios más altos.
  • Número de Parqueaderos tiene un impacto positivo en el precio, aunque con mayor variabilidad.
  • Número de Habitaciones tiene la menor influencia en el precio, con una relación menos clara y más dispersa.

Variables Categoricas:

# 2.2.1. Realizar el análisis ANOVA
anova_result <- aov(preciom ~ estrato, data = data_apartamentos)
summary(anova_result)
##               Df   Sum Sq  Mean Sq F value Pr(>F)    
## estrato        3 49153796 16384599   963.2 <2e-16 ***
## Residuals   2546 43308274    17010                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 2.2.2. Boxplot para Estrato
# Definir colores para cada nivel de la variable estrato
colores_estrato <- c("red", "blue", "green", "orange")  # Ajusta los colores según sea necesario
# Crear boxplot para la variable estrato con colores diferenciados
boxplot_estrato <- plot_ly(data_apartamentos, x = ~estrato, y = ~preciom, type = 'box', color = ~estrato, colors = colores_estrato) %>%
  layout(title = 'Distribución del Precio por Estrato',
         xaxis = list(title = 'Estrato'), yaxis = list(title = 'Precio'))
# Mostrar el boxplot
boxplot_estrato

Incremento del Precio con el Estrato: A medida que el estrato aumenta (de 3 a 6), también se observa un incremento en el precio de las viviendas. Esto sugiere una relación directa entre el estrato socioeconómico y el valor de la propiedad, donde los estratos más altos tienden a tener precios más elevados.

Significancia Estadística: La tabla que acompaña la gráfica muestra un resultado de ANOVA con un valor de p muy pequeño (<2e-16), lo que indica que las diferencias en el precio entre los diferentes estratos son estadísticamente significativas. Esto respalda la observación visual de que el estrato tiene un impacto considerable en el precio de las viviendas.

Estimación Modelo Lineal

modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = data_apartamentos)
summary(modelo) # Resumen del modelo
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = data_apartamentos)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -986.47  -40.57   -0.32   37.32  900.26 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -32.91496   13.59069  -2.422  0.01552 *  
## areaconst      1.20606    0.05254  22.956  < 2e-16 ***
## estrato4      30.62408    9.83109   3.115  0.00186 ** 
## estrato5      49.72514    9.89218   5.027 5.40e-07 ***
## estrato6     196.32714   11.56796  16.972  < 2e-16 ***
## habitaciones -17.28858    3.98984  -4.333 1.54e-05 ***
## parqueaderos  75.88290    4.52495  16.770  < 2e-16 ***
## banios        40.19756    3.44246  11.677  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 92.65 on 2185 degrees of freedom
##   (357 observations deleted due to missingness)
## Multiple R-squared:  0.7731, Adjusted R-squared:  0.7723 
## F-statistic:  1063 on 7 and 2185 DF,  p-value: < 2.2e-16
coeficientes <- tidy(modelo); print(coeficientes) # Obtener coeficientes y p-valores
## # A tibble: 8 × 5
##   term         estimate std.error statistic   p.value
##   <chr>           <dbl>     <dbl>     <dbl>     <dbl>
## 1 (Intercept)    -32.9    13.6        -2.42 1.55e-  2
## 2 areaconst        1.21    0.0525     23.0  1.18e-104
## 3 estrato4        30.6     9.83        3.12 1.86e-  3
## 4 estrato5        49.7     9.89        5.03 5.40e-  7
## 5 estrato6       196.     11.6        17.0  8.79e- 61
## 6 habitaciones   -17.3     3.99       -4.33 1.54e-  5
## 7 parqueaderos    75.9     4.52       16.8  1.80e- 59
## 8 banios          40.2     3.44       11.7  1.33e- 30

Modelo de Regresión: El modelo de regresión tiene un R-cuadrado múltiple de 0.6057 y un R-cuadrado ajustado de 0.5985, lo que indica que aproximadamente el 60% de la variabilidad en el precio puede explicarse por las variables independientes incluidas en el modelo. Esto sugiere que el modelo es moderadamente bueno para predecir el precio basado en las variables seleccionadas.

  • El valor de F-statistic de 83.84 y un p-valor < 2.2e-16 indican que el modelo en su conjunto es altamente significativo, lo que significa que al menos una de las variables independientes tiene una relación significativa con la variable dependiente (precio).

Intercepto: Es significativo con un p-valor de 0.0155, y su coeficiente de -32.9 indica que, cuando todas las variables independientes son cero, el precio predicho sería negativo, lo que sugiere que no tiene una interpretación práctica directa en este contexto.

areaconst (Área Construida): Tiene un coeficiente de 1.21, que es altamente significativo (p-valor de 1.18e-104), lo que indica que por cada unidad adicional de área construida, el precio aumenta en 1.21 unidades, manteniendo las demás variables constantes.

Estratos: Todos los coeficientes asociados con los estratos (4, 5, 6) son significativos y positivos:

  • Estrato 4: Incrementa el precio en 30.6 unidades (p-valor de 0.00186).
  • Estrato 5: Incrementa el precio en 49.7 unidades (p-valor de 5.40e-7).
  • Estrato 6: Incrementa el precio en 196 unidades (p-valor de 8.79e-61). Esto confirma que el estrato socioeconómico tiene un impacto significativo en el precio de las propiedades, siendo mayor en los estratos más altos.

Habitaciones: Tiene un coeficiente negativo de -17.3, que es estadísticamente significativo (p-valor de 1.54e-5), lo que sugiere que, contrariamente a lo que podría esperarse, un mayor número de habitaciones está asociado con una disminución en el precio, posiblemente debido a que más habitaciones podrían estar asociadas con un diseño menos eficiente o propiedades más antiguas.

Parqueaderos: Tiene un coeficiente significativo de 75.9 (p-valor de 1.80e-59), lo que indica que tener más parqueaderos aumenta considerablemente el precio de la propiedad.

Baños: Es significativo con un coeficiente de 40.2 (p-valor de 1.33e-30), lo que sugiere que el número de baños tiene un impacto positivo importante en el precio, aunque es menos pronunciado en comparación con el área construida y los estratos.

Supuestos

# 4. Validación de supuestos
###################################################################
# 4.1 Linealidad y Homoscedasticidad: Graficar residuos vs. valores ajustados
###################################################################
ggplot(modelo, aes(x = .fitted, y = .resid)) +
  geom_point() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "Residuos vs. Valores Ajustados", x = "Valores Ajustados", y = "Residuos")

###################################################################
# 4.2 Independencia de los Errores: Gráfico de residuos vs. orden
###################################################################
ggplot(modelo, aes(x = seq_along(.resid), y = .resid)) +
  geom_point() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "Residuos vs. Orden", x = "Orden", y = "Residuos")

###################################################################
# 4.3 Normalidad de los Errores: Histograma de residuos y Q-Q plot
###################################################################
par(mfrow = c(1, 2))  # Configurar para múltiples gráficos
hist(modelo$residuals, main = "Histograma de Residuos", xlab = "Residuos")
qqnorm(modelo$residuals, main = "Q-Q Plot de Residuos")
qqline(modelo$residuals, col = "red")

par(mfrow = c(1, 1))  # Volver a la configuración original
# Prueba de Shapiro-Wilk
shapiro_test <- shapiro.test(modelo$residuals)
print(shapiro_test)
## 
##  Shapiro-Wilk normality test
## 
## data:  modelo$residuals
## W = 0.78343, p-value < 2.2e-16
# Cargar el paquete lmtest
library(lmtest)

# Prueba de Breusch-Pagan
bp_test <- bptest(modelo)
print(bp_test)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo
## BP = 648.08, df = 7, p-value < 2.2e-16

Análisis Supuestos

Linealidad:

El gráfico de residuos vs. valores ajustados sugiere que la relación entre las variables independientes y la dependiente es aproximadamente lineal. Sin embargo, hay cierta variabilidad en los residuos, especialmente en los valores altos de los ajustados, lo que podría indicar que la linealidad no es perfecta. Independencia de los Errores:

El gráfico de residuos vs. orden no muestra un patrón claro, lo que sugiere que los errores son independientes entre sí, cumpliendo con este supuesto.

Normalidad de los Residuos: La prueba de Shapiro-Wilk arrojó un p-valor extremadamente bajo (< 2.2e-16), indicando que los residuos no siguen una distribución normal. Esto podría afectar la validez de las inferencias estadísticas basadas en el modelo.

Homoscedasticidad: La prueba de Breusch-Pagan mostró un p-valor muy bajo (< 2.2e-16), lo que indica la presencia significativa de heterocedasticidad. Esto significa que la variabilidad de los errores no es constante, lo que podría llevar a estimaciones ineficientes y errores estándar incorrectos

Predicción:

# 5. Predicción
###################################################################
# Crear un DataFrame con las características del apartamento
apartamento1 <- data.frame(areaconst = 300, estrato = factor(c(5, 6), levels = levels(data_apartamentos$estrato)), banios = 3, habitaciones = 5, parqueaderos = 3)
# Predecir el precio
predicciones <- predict(modelo, newdata = apartamento1)
# Mostrar las predicciones
print(predicciones)
##        1        2 
## 640.4267 787.0287

Al comparar las dos predicciones, se observa que el apartamento ubicado en el estrato 6 tiene un precio predicho significativamente más alto (alrededor de 146.60 unidades más) que el apartamento en el estrato 5, manteniendo constantes las demás características (área construida de 300, 3 baños, 5 habitaciones, y 3 parqueaderos).

Esto confirma nuevamente la influencia significativa del estrato socioeconómico en el precio de las propiedades, con los precios incrementando a medida que se sube de estrato.

Sugerencias potenciales:

# 6. Sugerencias potenciales
###################################################################
# Filtrar y seleccionar las 5 ofertas más baratas
ofertas <- data %>%
  filter(preciom <= 850, 
         areaconst >= 300,  # Ajustar según el rango deseado
         #parqueaderos == 3, 
         banios == 3, 
         #habitaciones == 5, 
         tipo == "Apartamento",
         zona == "Zona Sur",
         estrato %in% c(5, 6)) %>%
  arrange(preciom) %>%
  head(5)
# Crear el mapa
leaflet(ofertas) %>% addTiles() %>%
  addCircleMarkers(~longitud, ~latitud, color = 'blue', 
                   popup = ~paste("<br>Tipo:", tipo, "<br>Área:", areaconst, "<br>Parqueaderos:", parqueaderos, "<br>Baños:", banios, "<br>Habitaciones:", habitaciones, "<br>Estrato:", estrato, "<br>Zona:", zona, "<br>Precio:", preciom), 
                   radius = 8, fillOpacity = 0.7) %>% setView(lng = mean(ofertas$longitud), lat = mean(ofertas$latitud), zoom = 12)
# Mostrando los resultados
print(ofertas %>% select(preciom, areaconst, parqueaderos, banios, habitaciones, estrato))
## # A tibble: 2 × 6
##   preciom areaconst parqueaderos banios habitaciones estrato
##     <dbl>     <dbl>        <dbl>  <dbl>        <dbl>   <dbl>
## 1     299       932            1      3            3       5
## 2     850       352            4      3            3       6

Resultado:

  • Después de aplicar estos filtros, no tenemos alguna sugerencia por parte del modelo, al ampliar un poco mas el rango podemos ver mas posibles ofertas.
ofertas <- data %>%
  filter(preciom >= (min(predicciones) - 50) & preciom <= (max(predicciones) + 50), 
         ## areaconst >= 300,  # Ajustar según el rango deseado
         ## parqueaderos == 1, 
         banios >= 2,  # Relajar este criterio
         habitaciones >= 4,  # Relajar este criterio
         tipo == "Apartamento",
         zona == "Zona Sur",
         estrato %in% c(5, 6)) %>%
arrange(preciom) %>%
head(5)
# Crear el mapa
leaflet(ofertas) %>% addTiles() %>%
  addCircleMarkers(~longitud, ~latitud, color = 'blue', 
                   popup = ~paste("<br>Tipo:", tipo, "<br>Área:", areaconst, "<br>Parqueaderos:", parqueaderos, "<br>Baños:", banios, "<br>Habitaciones:", habitaciones, "<br>Estrato:", estrato, "<br>Zona:", zona, "<br>Precio:", preciom), 
                   radius = 8, fillOpacity = 0.7) %>% setView(lng = mean(ofertas$longitud), lat = mean(ofertas$latitud), zoom = 12)
# Mostrando los resultados
print(ofertas %>% select(preciom, areaconst, parqueaderos, banios, habitaciones, estrato))
## # A tibble: 5 × 6
##   preciom areaconst parqueaderos banios habitaciones estrato
##     <dbl>     <dbl>        <dbl>  <dbl>        <dbl>   <dbl>
## 1     594       133            2      5            4       6
## 2     595       146            2      4            4       6
## 3     595       128            2      5            4       6
## 4     600       204            2      4            4       5
## 5     600       200            2      5            4       6