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)
Iniciaremos el analisis con una revision de los datos y limpieza de los mismos.
dim(vivienda)
## [1] 8322 13
Contamos con 8322 filas y 13 variables o columnas.
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:
zona: Variable categórica nominal.
estrato: Variable categórica ordinal.
tipo (Tipo de vivienda): Variable categórica nominal.
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.
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.
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)")
)
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.
Se puede intrepetar como una correlacion considerable, el valor de la vivienda esta relacionado con el estrato, a mayor estrato, mayor el precio.
Tambien es una correlacion considerable, se puede interpretar que las viviendas con mayor numero de baños poseen un valor más alto.
Se evidencia una relación debil entre el precio y el numero de habitaciones
Se logra evidenciar una relacion debil, los precios no necesariamente estan relacionados con la ubicación.
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.
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.
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.
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
# 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.