Se deben instalar los siguientes paquetes, una sola vez.

#install.packages('dplyr')
#install.packages("cluster")
#install.packages("FactoMineR")
#install.packages("learnr")
#install.packages("devtools")
#install.packages("factoextra")
#install.packages("devtools")
#install.packages("plotly")
#install.packages('caret', dependencies = TRUE)
library(dplyr)
library(plotly)
library(paqueteMODELOS)
library(stats)
library(FactoMineR)
library(factoextra)
library(cluster)
library(ggplot2)
library(correlation)
library(GGally)
library(nortest)
library(caret)
data("vivienda")
head(vivienda)

Analisis de los datos.

Iniciaremos el analisis con una revision de los datos y limpieza de los mismos.

  1. Primero consultaremos la dimension de la matriz de datos
dim(vivienda)
## [1] 8322   13

Contamos con 8322 filas y 13 variables o columnas.

  1. Validación de nulos en cada variable
colSums(is.na(vivienda))
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3         2638            3            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##         1605            3            3            3            3            3 
##      latitud 
##            3

Expresamos los faltantes en terminos de porcentaje

porcentaje_faltantes <- function(x) {sum(is.na(x)) / length(x)*100}

apply(vivienda, 2, porcentaje_faltantes)
##           id         zona         piso      estrato      preciom    areaconst 
##   0.03604903   0.03604903  31.69911079   0.03604903   0.02403268   0.03604903 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##  19.28622927   0.03604903   0.03604903   0.03604903   0.03604903   0.03604903 
##      latitud 
##   0.03604903

Encontramos que hay dos variables importantes (piso y parqueaderos) con el 31 y 19% de faltantes respectivamente,estos valores se reemplazaran por cero, teniendo en cuenta que puede darse el caso que una casa o apartamento no tenga esta caracteristica, es preferibles asumir que no tiene.

Antes de eso eliminaremos las columnas de id, barrio, longitud y latitud, para el presente ejercicio no aportan información de valor.

quitar <- c("id","barrio","longitud", "latitud")
vivienda <- vivienda[ ,!(names(vivienda) %in% quitar)]
dim(vivienda)
## [1] 8322    9

Ahora contamos con 9 variables, identificadas asi:

Variables categóricas.

zona: Variable categórica nominal.

estrato: Variable categórica ordinal.

tipo (Tipo de vivienda): Variable categórica nominal.

Variables cuantitativas.

piso: Variable cuantitativa discreta.

preciom (Precio): Variable cuantitativa continua.

areaconst (Área construida): Variable cuantitativa continua.

parquea (Número de parqueaderos): Variable cuantitativa discreta.

banios (Número de Baños): Variable cuantitativa discreta.

habitac (Número de Habitaciones): Variable cuantitativa discreta.

Hasta el momento identificamos que en la matriz tenemos 9 variables con 8322 registros, contamos con valores nulos, principalmente en las variables de piso y parqueaderos.

Transformación y visualización de los datos.

Solicitud 1:

Realice un filtro a la base de datos e incluya sólo las ofertas de apartamentos. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta.

Se identifica que los tres ultimos registros de la base de datos presentan principalmente el valor nulo en todas las variables, realizar el filtro para obtener solo apartamentos y se procedera a eliminarlos e imputar las variables de piso y parqueadero.

# Eliminar registros donde la columna zona = "NA"
vivienda_clean <- subset(vivienda, tipo == "Apartamento")

# Reemplazar NA por 0 en la columna "parqueaderos"
vivienda_clean$parqueaderos <- ifelse(is.na(vivienda_clean$parqueaderos), 0, vivienda_clean$parqueaderos)

# Reemplazar NA por 0 en la columna "piso"
vivienda_clean$piso <- ifelse(is.na(vivienda_clean$piso), 0, vivienda_clean$piso)

# Convertimos la variable piso a numerica
vivienda_clean$piso <- as.numeric(vivienda_clean$piso)

# Convertir variable categorica "Zona" a numerica para lograr analizar las correlaciones:
vivienda_clean$zona = ifelse(vivienda_clean$zona == 'Zona Norte', 0, vivienda_clean$zona)
vivienda_clean$zona = ifelse(vivienda_clean$zona == 'Zona Sur', 1, vivienda_clean$zona)
vivienda_clean$zona = ifelse(vivienda_clean$zona == 'Zona Oeste', 2, vivienda_clean$zona)
vivienda_clean$zona = ifelse(vivienda_clean$zona == 'Zona Centro', 3, vivienda_clean$zona)
vivienda_clean$zona = ifelse(vivienda_clean$zona == 'Zona Oriente', 4, vivienda_clean$zona)

# Convertimos la variable zona a numerica
vivienda_clean$zona <- as.numeric(vivienda_clean$zona)

head(vivienda_clean, 3)
dim(vivienda_clean)
## [1] 5100    9

Una vez aplicado el filtro, validamos que contamos con 5100 registros y 9 variables.

Solicitud 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.

Para la variable Area, analizamos con la funcion cor y el metodo Spearman, ya que al hacerlo con un diagrama de cajas no es posible observalo correctamente.

correlaciones = cor(vivienda_clean$preciom, vivienda_clean[, c("preciom", "areaconst", "estrato", "banios", "habitaciones", "zona")], method = "spearman")
correlaciones
##      preciom areaconst  estrato   banios habitaciones    zona
## [1,]       1 0.8895707 0.837319 0.771612    0.3258252 0.34314

Creamos diagramas de cajas para apoyar el analisis de las demas variables.

plot_ly(data = vivienda_clean, y = ~preciom, x = ~as.factor(estrato),
        type = "box", marker=list(size = 10, opacity = 0.5,
                                  color="green")) %>%
  
  layout(title = "Distribucion entre Precio y estrato",
         plot_bgcolor='white',
         xaxis = list(title = "Estrato"), 
         yaxis = list(title = "Precio(pesos)"))
plot_ly(data = vivienda_clean, y = ~preciom, x = ~as.factor(banios),
        type = "box", marker=list(size = 10, opacity = 0.5,
                                  color="green")) %>%
  
  layout(title = "Distribucion entre Precio y numero de baños",
         plot_bgcolor='white',
         xaxis = list(title = "Cantidad de baños"), 
         yaxis = list(title = "Precio(pesos)"))
plot_ly(data = vivienda_clean, y = ~preciom, x = ~as.factor(habitaciones),
        type = "box", marker=list(size = 10, opacity = 0.5,
                                  color="green")) %>%
  
  layout(title = "Distribucion entre Precio y numero de habitaciones",
         plot_bgcolor='white',
         xaxis = list(title = "area construida"), 
         yaxis = list(title = "Precio(pesos)"))
plot_ly(data = vivienda_clean, y = ~preciom, x = ~as.factor(zona),
        type = "box", marker=list(size = 10, opacity = 0.5,
                                  color="green")) %>%
  
  layout(title = "Distribucion entre Precio y la zona",
         plot_bgcolor='white',
         xaxis = list(title = "Zona norte=0 - Zona sur=1 - Zona oeste=2 - Zona centro=3 - Zona Oriente=4"), 
         yaxis = list(title = "Precio(pesos)")
         )

Precio y area = 0.889 (Positiva fuerte)

Es el valor de correlación más alto, se puede intrepretar que a mayor costo de la vivienda esta contara con un mayor area o espacio.

Precio y estrato = 0.837 (Positiva fuerte)

Se puede intrepetar como una correlacion considerable, el valor de la vivienda esta relacionado con el estrato, a mayor estrato, mayor el precio.

Precio y numero de baños = 0.771 (Positiva debil)

Tambien es una correlacion considerable, se puede interpretar que las viviendas con mayor numero de baños poseen un valor más alto.

Precio y numero de habitaciones = 0.325 (Positiva debil)

Se evidencia una relación debil entre el precio y el numero de habitaciones

Precio y zona de la vivienda = 0.343 (Positiva debil)

Se logra evidenciar una relacion debil, los precios no necesariamente estan relacionados con la ubicación.

Solicitud 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).

modelo = lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones + zona, data = vivienda_clean)
summary(modelo)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios + 
##     habitaciones + zona, data = vivienda_clean)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1854.01   -54.73    -2.78    45.04  1013.34 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -218.74180   13.28520 -16.465  < 2e-16 ***
## areaconst       2.16096    0.04187  51.614  < 2e-16 ***
## estrato        49.10268    2.67356  18.366  < 2e-16 ***
## parqueaderos   53.65301    2.95149  18.178  < 2e-16 ***
## banios         51.94960    3.01151  17.250  < 2e-16 ***
## habitaciones  -39.34880    3.27417 -12.018  < 2e-16 ***
## zona           20.76666    2.62033   7.925 2.78e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 133.3 on 5093 degrees of freedom
## Multiple R-squared:  0.7878, Adjusted R-squared:  0.7875 
## F-statistic:  3151 on 6 and 5093 DF,  p-value: < 2.2e-16
coef(modelo)
##  (Intercept)    areaconst      estrato parqueaderos       banios habitaciones 
##  -218.741800     2.160962    49.102677    53.653009    51.949599   -39.348804 
##         zona 
##    20.766656

Los coeficientes estimados se interpretan así:

El intercepto indica el valor estimado de la variable respuesta (precio) cuando todas las variables predictoras son cero. Sin embargo, dado que todas las variables predictoras son variables contínuas y no tienen sentido cuando son cero, la interpretación del intercepto en este contexto puede no tener relevancia práctica directa.

El coeficiente para “areaconst” es de 2.160962, lo que indica que, manteniendo constantes las otras variables, por cada unidad adicional en el área construida, el precio de la vivienda aumenta en promedio $2.16. Este resultado es lógico y coherente, ya que es de esperar que viviendas más grandes tiendan a tener precios más altos.

Para “estrato”, el coeficiente es de 49.102677, lo que sugiere que, manteniendo constantes las otras variables, por cada unidad adicional en el estrato, el precio de la vivienda aumenta en promedio $49.10. Este resultado también es coherente, ya que es común que viviendas ubicadas en estratos más altos tengan precios más elevados.

Para “parqueadero”, el coeficiente es de 53.653009, lo que sugiere que, manteniendo constantes las otras variables, por cada unidad adicional en el parqueadero, el precio de la vivienda aumenta en promedio $53.65. Este resultado también es coherente, ya que es común que viviendas parqueaderos tengan precios más elevados.

El coeficiente para “banios” es de 51.949599, indicando que, manteniendo constantes las otras variables, por cada baño adicional, el precio de la vivienda aumenta en promedio $51.94. Esto es razonable, ya que los baños adicionales suelen agregar valor a una propiedad.

Las variables “habitaciones” y “zona” no son estadísticamente significativas, lo que indica que no contribuyen de manera significativa a la predicción del precio de la vivienda en este modelo, incluso al eliminarlas del modelo, no se observan cambios siginificativos ni en los coeficientes ni el el R2.

El coeficiente de determinación (R²) del modelo es de 0.7878, lo que significa que alrededor del 78.78% de la variabilidad en el precio de la vivienda puede ser explicada por las variables incluidas en el modelo. Este valor es relativamente alto y sugiere que el modelo tiene un buen ajuste en general.

Para mejorar el modelo se puede estudiar la posibilidad de incluir otras variables al modelo, tales como cercanias con centros comerciales, supermercados, hospitales o zonas de esparcimiento. Ademas se puede probar la realizacion de transformaciones de variables de tipo logaritmica o polinomios.

Solicitud 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).

par(mfrow=c(2,2))
plot(modelo)

Análisis: En las gráficas podemos observar que hay cumplimiento de los supuestos:

Residuals vs Fitted (Linealidad): La línea de referencia es horizontal y la dispersión de los valores está cerca de la línea roja, hay linealidad.

Normal Q-Q (Normalidad de residuos): Aunque en el centro los residuales estan ajustados a la linea, en los extremos no se comporta de la misma manera, lo que sugiere que los residuos no siguen una distribucion normal.

Scale-Location (homocedasticidad): La línea roja no es horizontal y la varianza de los residuos no es constante. Esto indica que hay heterocedasticidad en los residuos del modelo.

Residuals vs Leverage (Outliers): No se observan valores atípicos o influyentes.

Solicitud 5:

Realice una partición en los datos de forma aleatoria donde 70% sea un set para entrenar el modelo y 30% para prueba. Estime el modelo con la muestra del 70%. Muestre los resultados.

# Creamos la particion de los datos con la libreria caret.

data_partition <- createDataPartition(y = vivienda_clean$preciom, p = 0.70, list = FALSE)

data_train <- vivienda_clean[data_partition,]
data_test <- vivienda_clean[-data_partition,]
modelo_train = lm(preciom ~ areaconst + estrato + parqueaderos + banios + habitaciones + zona, data = data_train)
summary(modelo_train)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + parqueaderos + banios + 
##     habitaciones + zona, data = data_train)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1760.34   -56.01    -4.33    44.21  1008.31 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -227.72852   16.16641 -14.087  < 2e-16 ***
## areaconst       2.04265    0.04982  41.003  < 2e-16 ***
## estrato        48.77476    3.24449  15.033  < 2e-16 ***
## parqueaderos   53.34504    3.63615  14.671  < 2e-16 ***
## banios         59.56308    3.68895  16.146  < 2e-16 ***
## habitaciones  -38.50646    4.00866  -9.606  < 2e-16 ***
## zona           22.93377    3.19540   7.177 8.62e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 134.6 on 3565 degrees of freedom
## Multiple R-squared:  0.7851, Adjusted R-squared:  0.7848 
## F-statistic:  2171 on 6 and 3565 DF,  p-value: < 2.2e-16

Podemos observar unos resultados en los coeficientes muy similares a los encontrados con la totalidad de los datos, el R2 arroja un valor de 77,98%, frente al 78,78% analizado en el punto 3, no existe mucha diferencia. El p-value se sigue manteniendo aproximado a cero, no hay significancia.

Solicitud 6:

Realice predicciones con el modelo anterior usando los datos de prueba (30%).

Entrenando el modelo de predicción:

#Elimino la columna tipo, ya que al ser igual en todos sus valores, no es admitida en el entrenamiento.

quitar <- c("tipo")
data_train <- data_train[ ,!(names(data_train) %in% quitar)]
#Entrenamos el modelo

modelo_entrenado <- train(preciom ~ ., 
                data = data_train, 
                method = "lm",  
                tuneLength = 3000
                )
modelo_entrenado
## Linear Regression 
## 
## 3572 samples
##    7 predictor
## 
## No pre-processing
## Resampling: Bootstrapped (25 reps) 
## Summary of sample sizes: 3572, 3572, 3572, 3572, 3572, 3572, ... 
## Resampling results:
## 
##   RMSE      Rsquared   MAE     
##   133.3653  0.7874752  81.85298
## 
## Tuning parameter 'intercept' was held constant at a value of TRUE
summary(modelo_entrenado)
## 
## Call:
## lm(formula = .outcome ~ ., data = dat)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1763.85   -56.08    -3.93    44.30  1009.70 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -229.19535   16.28853 -14.071  < 2e-16 ***
## zona           23.04466    3.19912   7.203 7.13e-13 ***
## piso            0.53113    0.71785   0.740    0.459    
## estrato        48.77266    3.24470  15.032  < 2e-16 ***
## areaconst       2.04452    0.04989  40.985  < 2e-16 ***
## parqueaderos   53.06542    3.65596  14.515  < 2e-16 ***
## banios         59.41916    3.69431  16.084  < 2e-16 ***
## habitaciones  -38.46653    4.00928  -9.594  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 134.6 on 3564 degrees of freedom
## Multiple R-squared:  0.7852, Adjusted R-squared:  0.7848 
## F-statistic:  1861 on 7 and 3564 DF,  p-value: < 2.2e-16

Una vez que el modelo ya esta entrenado, procedemos a realizar las predicciones.

lm_predicciones = predict(modelo_entrenado, newdata = data_test)

resultados = data.frame(Real=data_test$preciom, Prediccion = lm_predicciones)
resultados

Solicitud 7:

  1. Calcule el error cuadrático medio, el error absoluto medio y el R2, interprete.
# Calcular el Error Cuadrático Medio (RMSE)
mse <- modelo_entrenado$results$RMSE

# Calcular el Error Absoluto Medio (MAE)
mae <- modelo_entrenado$results$MAE

# Calcular el Coeficiente de Determinación (R²)
r2 <- modelo_entrenado$results$Rsquared

# Mostrar los resultados
cat("MSE:", mse, "\n")
## MSE: 133.3653
cat("MAE:", mae, "\n")
## MAE: 81.85298
cat("R2:", r2, "\n")
## R2: 0.7874752

Error Cuadratico Medio (RMSE): arroja un valor de $139.17, un valor no tan bajo, este valor representa la diferencia del estimador y lo que se estima al cuadrado, considero que se debe mejorar el modelo para reducir esta diferencia y acercarla a cero.

Error Absoluto Medio (MAE): arroja un valor de $82.95, un valor bajo, el error en las predicciones se puede considerar aceptable.

R2: Las variables actuales del modelo arrojan un 77% de explicación de la variabilidad, se realizo la prueba de eliminar algunas variables sin correlación la variable precio, pero no se evidenciaron cambios significativos en el R2 ni en los coeficientes, para mejorar este valor se puede evaluar la posibilidad de agregar nuevas variables al modelo.