De acuerdo a los datos obtenidos de la base de datos “vivienda” del paquete devtools:

1. Realice un filtro a la base de datos e incluya solo las ofertas de casas, de la zona norte de la ciudad. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta. (Adicional un mapa con los puntos de las bases. Discutir si todos los puntos se ubican en la zona correspondiente o se presentan valores en otras zonas, por que?).

Iniciamos con un filtro en nuestra muestra para aquellos registros que cumplan las condiciones:

* Tipo = Casa

* Zona = Zona Norte

filtered_data <- vivienda %>%
  filter(tipo == "Casa" & zona == "Zona Norte")

Apartir de esta muestra visualizamos los primeros 3 registros.

head(filtered_data, 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>

Implementaremos la función table mediante la cual traemos como resultado una tabla que nos permite observar la sumatoria de registros de acuerdo al estrato de viviendas tipo Casa en la Zona Norte de Cali.

table(filtered_data$estrato)
## 
##   3   4   5   6 
## 235 161 271  55

Hacemos uso de la librería leaflet para generar un mapa de Cali donde se ubican las viviendas tipo Casa en la Zona Norte.

Mapa de las viviendas tipo Casa en Zona Norte:

map <- leaflet(filtered_data) %>%
  addTiles() %>%
  addMarkers(lat = ~latitud, lng = ~longitud)  
# Display the map
map

Interpretación del mapa anterior:

Al realizar un análisis sobre la ubicación de las propiedades, es evidente que la mayoría se concentra en la zona norte de la ciudad. No obstante, se observa que algunas pocas están dispersas de manera poco común en el resto del territorio. Esto posiblemente se deba a posibles errores en los datos, como errores de entrada o errores de digitación.

2. Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio de la casa) en función del área construida, estrato, numero de baños, numero de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.

* Gestionamos la instalación y uso del paquete plotly

install.packages("plotly")
library(plotly)

* Construimos un diagrama de dispersión, también conocido como gráfico de dispersión o scatterplot en inglés, el cual nos permite visualizar la relación entre dos variables cuantitativas. Cada punto en el gráfico representa una observación que tiene valores en ambas variables. Esto proporciona una representación gráfica de cómo los valores de una variable están distribuidos con respecto a los valores de la otra. Mediante este gráfico podemos determinar si existe alguna relación entre las variables, por ejemplo, si son directamente proporcionales, inversamente proporcionales o no tienen relación aparente.

Se pueden presentar valores atípicos, los valores atípicos o outliers son valores inusuales que se alejan significativamente de la mayoría de los datos. Un gráfico de dispersión permite también identificar estos valores atípicos, ya que a menudo se representan como puntos que se alejan del patrón general en el gráfico.

Una visual de dispersión es la base para el análisis de modelos de regresión. Es posible ajustar una línea o una curva a los puntos en el gráfico para predecir o modelar una variable en función de la otra. Esto es especialmente útil cuando se desea realizar predicciones o inferencias basadas en los datos.

scatter_plot <- plot_ly(data = filtered_data, x = ~areaconst, y = ~preciom, color = ~zona,
                        type = 'scatter', mode = 'markers',
                        marker = list(size = 10, opacity = 0.6)) %>%
  layout(title = "Scatter Plot Area construida vs. Precio",
         xaxis = list(title = "Area Construida"),
         yaxis = list(title = "Precio de vivienda"))

scatter_plot
box_plot_estrato <- plot_ly(data = filtered_data, x = ~estrato, y = ~preciom, type = 'box') %>%
  layout(title = "Box Plot de Precio por Estrato",
         xaxis = list(title = "Estrato"),
         yaxis = list(title = "Precio de vivienda"))
box_plot_estrato
box_plot_zona <- plot_ly(data = filtered_data, x = ~zona, y = ~preciom, type = 'box') %>%
  layout(title = "Box Plot de Precio por Zona",
         xaxis = list(title = "Zona"),
         yaxis = list(title = "Precio de vivienda"))
box_plot_zona

3. Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f(área construida, estrato, número de cuartos, número de parqueaderos, número de baños ) ) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).

* Para esta finalidad utilizaremos la función lm() en R se utiliza para realizar análisis de regresión lineal. La regresión lineal es una técnica estadística que se utiliza para modelar la relación entre una variable dependiente (o respuesta) y una o más variables independientes (o predictores) al encontrar la mejor línea recta (o hiperplano en dimensiones superiores) que se ajusta a los datos.

En particular, lm() se utiliza para:

Ajuste de modelo: Es posible usar lm() para ajustar un modelo de regresión lineal a tus datos. Esto implica encontrar los coeficientes (pendiente y ordenada al origen) que minimizan la suma de los cuadrados de las diferencias entre los valores observados y los valores predichos por el modelo.

Predicción: Una vez que ajustado un modelo de regresión lineal, se puede utilizar para predecir valores de la variable dependiente en función de los valores de las variables independientes. Esto es útil en la predicción de resultados futuros o para entender cómo una variable responde a cambios en otras.

Evaluación del modelo: Podemos obtener estadísticas sobre la calidad del ajuste del modelo, como los valores R-squared, los coeficientes de regresión, los intervalos de confianza y las p-values. Estas estadísticas ayudan a evaluar la significancia de las relaciones entre las variables y la bondad del ajuste del modelo.

Visualización: La función lm() puede utilizarse en combinación con otras funciones y paquetes de R, como ggplot2, para crear gráficos que muestren el modelo de regresión y sus resultados de manera visual.

En resumen, lm() en R es una herramienta esencial para realizar análisis de regresión lineal, lo que permite modelar y comprender las relaciones entre variables y realizar predicciones basadas en datos observados.

Apartir de lo anterior, generamos el modelo con la función lm() apartir de los datos filtrados por tipo de vivienda: Casa y zona: Norte:

model <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = filtered_data)

Ahora ejecutamos la función summary mediante la cual obtenemos un resumen estadístico detallado del modelo. El resumen incluye información importante sobre las relaciones entre las variables. La información que te proporciona summary() incluye:

Resumen de coeficientes: el resumen mostrará una tabla que incluye los coeficientes estimados para cada variable independiente en el modelo. Esto incluye la estimación de la interceptación (ordenada al origen) y las pendientes de las variables predictoras. Estos coeficientes te permiten entender cómo cada variable independiente contribuye al modelo.

Estadísticas de significancia: junto a cada coeficiente, se proporcionan estadísticas como el valor t y la p-value. Estas estadísticas permiten determinar si los coeficientes son significativamente diferentes de cero. Las p-values más pequeñas indican una mayor significancia.

Estadísticas de ajuste del modelo: El resumen incluye estadísticas como el R-squared (R²), que mide la bondad del ajuste del modelo. El R² indica cuánta variabilidad en la variable dependiente es explicada por el modelo. También se proporciona el R² ajustado, que tiene en cuenta el número de variables en el modelo.

Estadísticas de error: se proporciona información sobre la varianza residual, el error estándar residual y otros estadísticos relacionados con la precisión del modelo.

Información sobre los residuos: Los residuos son las diferencias entre los valores observados y los valores predichos por el modelo. La revisión de los residuos es importante para verificar si se cumplen las suposiciones de la regresión lineal.

Información sobre la multicolinealidad: Si hay multicolinealidad (alta correlación entre las variables predictoras), el resumen puede proporcionar advertencias o información sobre este problema.

Summary() es una herramienta esencial para evaluar la calidad del ajuste de un modelo de regresión y la importancia de las variables predictoras en el modelo. Ayuda a interpretar el modelo y a determinar si es adecuado para los datos disponibles.

summary(model)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = filtered_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -784.29  -77.56  -16.03   47.67  978.61 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -238.17090   44.40551  -5.364 1.34e-07 ***
## areaconst       0.67673    0.05281  12.814  < 2e-16 ***
## estrato        80.63495    9.82632   8.206 2.70e-15 ***
## habitaciones    7.64511    5.65873   1.351    0.177    
## parqueaderos   24.00598    5.86889   4.090 5.14e-05 ***
## banios         18.89938    7.48800   2.524    0.012 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 155.1 on 429 degrees of freedom
##   (287 observations deleted due to missingness)
## Multiple R-squared:  0.6041, Adjusted R-squared:  0.5995 
## F-statistic: 130.9 on 5 and 429 DF,  p-value: < 2.2e-16

4. Realice la validación de supuestos del modelo e interprete los resultados (no es necesario corregir en caso de presentar problemas, solo realizar sugerencias de que se podría hacer).

* Para realizar esta validación de supuestos, calculamos la linealidad.

* Partiremos por realizar un gráfico de dispersión de residuos vs. valores ajustados del modelo. La linealidad es uno de los supuestos fundamentales en la validación de modelos estadísticos, especialmente en el contexto de modelos de regresión lineal. Este supuesto establece que la relación entre las variables independientes y la variable dependiente es lineal, es decir, se puede representar mediante una línea recta en un espacio bidimensional o un hiperplano en espacios de mayor dimensión.

En términos más simples, la linealidad implica que un cambio unitario en una variable independiente debe producir un cambio constante en la variable dependiente, manteniendo todas las demás variables constantes. Esto se refleja en la ecuación de un modelo de regresión lineal.

# 1. Linealidad
# Gráfico de dispersión de residuos vs. valores ajustados
plot(model$residuals ~ model$fitted.values, xlab = "Valores Ajustados", ylab = "Residuos", main = "Linealidad")

# 2. Independencia de Residuos
# Gráfico de residuos en función del orden de observación
plot(model$residuals, xlab = "Orden de Observación", ylab = "Residuos", main = "Independencia de Residuos")

# 3. Homocedasticidad
# Gráfico de dispersión de residuos vs. valores ajustados
plot(model$fitted.values, abs(model$residuals), xlab = "Valores Ajustados", ylab = "|Residuos|", main = "Homocedasticidad")

# 4. Normalidad de Residuos
# Gráfico Q-Q para verificar la normalidad
qqPlot(model$residuals, main = "Normalidad de Residuos")

## 513 405 
## 309 239
# Prueba de Shapiro-Wilk para la normalidad
#shapiro.test(model$residuals)

# 5. Multicolinealidad
# Matriz de correlación entre variables predictoras
cor_matrix <- cor(filtered_data[, c("areaconst", "estrato", "habitaciones", "parqueaderos", "banios")])
print(cor_matrix)
##              areaconst   estrato habitaciones parqueaderos    banios
## areaconst    1.0000000 0.4573818    0.3753323           NA 0.4628152
## estrato      0.4573818 1.0000000    0.1073141           NA 0.4083039
## habitaciones 0.3753323 0.1073141    1.0000000           NA 0.5755314
## parqueaderos        NA        NA           NA            1        NA
## banios       0.4628152 0.4083039    0.5755314           NA 1.0000000
# Prueba de multicolinealidad
vif(model)
##    areaconst      estrato habitaciones parqueaderos       banios 
##     1.460998     1.307757     1.721015     1.226334     1.967421
# 6. Outliers e Influential Points
# Gráfico de valores ajustados vs. residuos estandarizados
plot(model$fitted.values, rstandard(model), xlab = "Valores Ajustados", ylab = "Residuos Estandarizados", main = "Outliers e Influential Points")

# 7. Heteroscedasticidad Condicional
# Calcula los residuos estandarizados
residuals <- rstandard(model)

# Calcula los valores ajustados
fitted_values <- fitted(model)

# Crea un gráfico de residuos estandarizados vs. valores ajustados
plot(fitted_values, residuals, 
     main = "Heteroscedasticidad Condicional",
     xlab = "Valores Ajustados",
     ylab = "Residuos Estandarizados")

# Gráfico de residuos estandarizados vs. una variable relevante (si aplica)
#plot(rstandard(model) ~ vivienda$estrato, xlab = "Variable Relevante", ylab = "Residuos Estandarizados", main = "Heteroscedasticidad Condicional")

Con el modelo identificado se predecirá el precio de la vivienda con las características de la primera solicitud en R

# Datos de la primera solicitud 
nueva_solicitud <- data.frame(
  areaconst = 200,   
  estrato = 4,             
  habitaciones = 4,      
  parqueaderos = 1, 
  banios = 2         
)

# Construir la predicción
prediccion_precio <- predict(model, newdata = nueva_solicitud)

prediccion_precio
##       1 
## 312.101

Con las predicciones del modelo se sugerirá potenciales ofertas que respondan a la solicitud de la vivienda 1. Teniendo en cuenta que la empresa tiene crédito pre-aprobado de máximo 350 millones de pesos. Se realizará un análisis de los resultados y se generará en un mapa al menos 5 ofertas potenciales.

# Realizar la predicción del precio de la vivienda 1
prediccion_precio_vivienda1 <- predict(model, newdata = nueva_solicitud)

# Definir el presupuesto máximo (350 millones de pesos)
presupuesto_maximo <- 350

# Filtrar las ofertas potenciales dentro del presupuesto
ofertas_potenciales <- filtered_data %>%
  filter(preciom <= presupuesto_maximo) %>%
  select(latitud, longitud, preciom)  # Seleccionar columnas relevantes para el mapa

# Visualizar las ofertas potenciales en un mapa (usando leaflet)
library(leaflet)

# Construccion del mapa
mapa_ofertas <- leaflet(data = ofertas_potenciales) %>%
  addTiles() %>%
  addMarkers(
    ~longitud, ~latitud,
    label = ~paste("Precio: $", preciom, "M"),  # el precio ya está formateado en millones en la muestra
    popup = ~paste("Precio: $", preciom, "M"),
    clusterOptions = markerClusterOptions()
  )

# Mostrar el mapa
mapa_ofertas

Realizaremos los pasos pasos anteriores para la segunda solicitud que tiene un crédito pre-aprobado por valor de $850 millones.

Iniciamos con un filtro en nuestra muestra para aquellos registros que cumplan las condiciones:

* Tipo = Apartamento

* Zona = Zona Sur

filtered_data_2 <- vivienda %>%
  filter(tipo == "Apartamento" & zona == "Zona Sur")

Apartir de esta muestra visualizamos los primeros 3 registros.

head(filtered_data_2, 3)
## # 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>

Implementaremos la función table mediante la cual traemos como resultado una tabla que nos permite observar la sumatoria de registros de acuerdo al estrato de viviendas tipo Apartamento en la Zona Sur de Cali.

table(filtered_data_2$estrato)
## 
##    3    4    5    6 
##  201 1091 1033  462

Hacemos uso de la librería leaflet para generar un mapa de Cali donde se ubican las viviendas tipo Apartamento en la Zona Sur.

Mapa de las viviendas tipo Apartamento en la Zona Sur:

map <- leaflet(filtered_data_2) %>%
  addTiles() %>%
  addMarkers(lat = ~latitud, lng = ~longitud)  
# Display the map
map

Realizaremos un análisis exploratorio de nuestra muestra

scatter_plot_2 <- plot_ly(data = filtered_data_2, x = ~areaconst, y = ~preciom, color = ~zona,
                        type = 'scatter', mode = 'markers',
                        marker = list(size = 10, opacity = 0.6)) %>%
  layout(title = "Scatter Plot Area construida vs. Precio",
         xaxis = list(title = "Area Construida"),
         yaxis = list(title = "Precio de vivienda"))

scatter_plot_2
box_plot_estrato_2 <- plot_ly(data = filtered_data_2, x = ~estrato, y = ~preciom, type = 'box') %>%
  layout(title = "Box Plot de Precio por Estrato",
         xaxis = list(title = "Estrato"),
         yaxis = list(title = "Precio de vivienda"))
box_plot_estrato_2
box_plot_zona_2 <- plot_ly(data = filtered_data_2, x = ~zona, y = ~preciom, type = 'box') %>%
  layout(title = "Box Plot de Precio por Zona",
         xaxis = list(title = "Zona"),
         yaxis = list(title = "Precio de vivienda"))
box_plot_zona_2

Construiremos un modelo de regresión lineal con la función lm()

model_2 <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = filtered_data_2)

El resumen del modelo nos permitirá evaluar la calidad del ajuste de un modelo de regresión y la importancia de las variables predictoras en el modelo

summary(model_2)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = filtered_data_2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1092.02   -42.28    -1.33    40.58   926.56 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -261.62501   15.63220 -16.736  < 2e-16 ***
## areaconst       1.28505    0.05403  23.785  < 2e-16 ***
## estrato        60.89709    3.08408  19.746  < 2e-16 ***
## habitaciones  -24.83693    3.89229  -6.381 2.11e-10 ***
## parqueaderos   72.91468    3.95797  18.422  < 2e-16 ***
## banios         50.69675    3.39637  14.927  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 98.02 on 2375 degrees of freedom
##   (406 observations deleted due to missingness)
## Multiple R-squared:  0.7485, Adjusted R-squared:  0.748 
## F-statistic:  1414 on 5 and 2375 DF,  p-value: < 2.2e-16

* Realizaremos la validación de supuestos de nuestro segundo modelo.

# 1. Linealidad
# Gráfico de dispersión de residuos vs. valores ajustados
plot(model_2$residuals ~ model_2$fitted.values, xlab = "Valores Ajustados", ylab = "Residuos", main = "Linealidad")

# 2. Independencia de Residuos
# Gráfico de residuos en función del orden de observación
plot(model_2$residuals, xlab = "Orden de Observación", ylab = "Residuos", main = "Independencia de Residuos")

# 3. Homocedasticidad
# Gráfico de dispersión de residuos vs. valores ajustados
plot(model_2$fitted.values, abs(model_2$residuals), xlab = "Valores Ajustados", ylab = "|Residuos|", main = "Homocedasticidad")

# 4. Normalidad de Residuos
# Gráfico Q-Q para verificar la normalidad
qqPlot(model_2$residuals, main = "Normalidad de Residuos")

## 2383 1533 
## 2042 1316
# Prueba de Shapiro-Wilk para la normalidad
#shapiro.test(model$residuals)

# 5. Multicolinealidad
# Matriz de correlación entre variables predictoras
cor_matrix_2 <- cor(filtered_data_2[, c("areaconst", "estrato", "habitaciones", "parqueaderos", "banios")])
print(cor_matrix_2)
##              areaconst   estrato habitaciones parqueaderos    banios
## areaconst    1.0000000 0.4815593    0.4339608           NA 0.6618179
## estrato      0.4815593 1.0000000    0.2125953           NA 0.5686171
## habitaciones 0.4339608 0.2125953    1.0000000           NA 0.5149227
## parqueaderos        NA        NA           NA            1        NA
## banios       0.6618179 0.5686171    0.5149227           NA 1.0000000
# Prueba de multicolinealidad
vif(model_2)
##    areaconst      estrato habitaciones parqueaderos       banios 
##     2.066518     1.545162     1.429280     1.737878     2.529494
# 6. Outliers e Influential Points
# Gráfico de valores ajustados vs. residuos estandarizados
plot(model_2$fitted.values, rstandard(model_2), xlab = "Valores Ajustados", ylab = "Residuos Estandarizados", main = "Outliers e Influential Points")

# 7. Heteroscedasticidad Condicional
# Calcula los residuos estandarizados
residuals_2 <- rstandard(model_2)

# Calcula los valores ajustados
fitted_values_2 <- fitted(model_2)

# Crea un gráfico de residuos estandarizados vs. valores ajustados
plot(fitted_values_2, residuals_2, 
     main = "Heteroscedasticidad Condicional",
     xlab = "Valores Ajustados",
     ylab = "Residuos Estandarizados")

# Gráfico de residuos estandarizados vs. una variable relevante (si aplica)
#plot(rstandard(model) ~ vivienda$estrato, xlab = "Variable Relevante", ylab = "Residuos Estandarizados", main = "Heteroscedasticidad Condicional")

Con el modelo identificado debe predecir el precio de la vivienda con las características de la segunda solicitud en R

# Datos de la primera solicitud 
nueva_solicitud_2 <- data.frame(
  areaconst = 300,   
  estrato = 5,             
  habitaciones = 5,      
  parqueaderos = 3, 
  banios = 3         
)
#falta poner que el estrato sean 5 o 6 de acuerdo a la solicitud
# Construir la predicción #2
prediccion_precio_2 <- predict(model_2, newdata = nueva_solicitud_2)

prediccion_precio_2
##        1 
## 675.0247

Con las predicciones del modelo se sugerirá potenciales ofertas que respondan a la solicitud de la vivienda 2. Teniendo en cuenta que la empresa tiene crédito pre-aprobado de máximo 850 millones de pesos.

# Realizar la predicción del precio de la vivienda 2
prediccion_precio_vivienda2 <- predict(model_2, newdata = nueva_solicitud_2)

# Definir el presupuesto máximo (350 millones de pesos)
presupuesto_maximo_2 <- 850

# Filtrar las ofertas potenciales dentro del presupuesto
ofertas_potenciales_2 <- filtered_data_2 %>%
  filter(preciom <= presupuesto_maximo_2) %>%
  select(latitud, longitud, preciom)  # Seleccionar columnas relevantes para el mapa

# Visualizar las ofertas potenciales en un mapa (usando leaflet)
library(leaflet)

# Construccion del mapa
mapa_ofertas_2 <- leaflet(data = ofertas_potenciales_2) %>%
  addTiles() %>%
  addMarkers(
    ~longitud, ~latitud,
    label = ~paste("Precio: $", preciom, "M"),  # el precio ya está formateado en millones en la muestra
    popup = ~paste("Precio: $", preciom, "M"),
    clusterOptions = markerClusterOptions()
  )

# Mostrar el mapa
mapa_ofertas_2