summary(vivienda)
## id zona piso estrato
## Min. : 1 Length:8322 Length:8322 Min. :3.000
## 1st Qu.:2080 Class :character Class :character 1st Qu.:4.000
## Median :4160 Mode :character Mode :character Median :5.000
## Mean :4160 Mean :4.634
## 3rd Qu.:6240 3rd Qu.:5.000
## Max. :8319 Max. :6.000
## NA's :3 NA's :3
## preciom areaconst parqueaderos banios
## Min. : 58.0 Min. : 30.0 Min. : 1.000 Min. : 0.000
## 1st Qu.: 220.0 1st Qu.: 80.0 1st Qu.: 1.000 1st Qu.: 2.000
## Median : 330.0 Median : 123.0 Median : 2.000 Median : 3.000
## Mean : 433.9 Mean : 174.9 Mean : 1.835 Mean : 3.111
## 3rd Qu.: 540.0 3rd Qu.: 229.0 3rd Qu.: 2.000 3rd Qu.: 4.000
## Max. :1999.0 Max. :1745.0 Max. :10.000 Max. :10.000
## NA's :2 NA's :3 NA's :1605 NA's :3
## habitaciones tipo barrio longitud
## Min. : 0.000 Length:8322 Length:8322 Min. :-76.59
## 1st Qu.: 3.000 Class :character Class :character 1st Qu.:-76.54
## Median : 3.000 Mode :character Mode :character Median :-76.53
## Mean : 3.605 Mean :-76.53
## 3rd Qu.: 4.000 3rd Qu.:-76.52
## Max. :10.000 Max. :-76.46
## NA's :3 NA's :3
## latitud
## Min. :3.333
## 1st Qu.:3.381
## Median :3.416
## Mean :3.418
## 3rd Qu.:3.452
## Max. :3.498
## NA's :3
faltantes <- colSums(is.na(vivienda))
faltantes
## 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
vivienda_sin_estrato_faltante <- vivienda[!is.na(vivienda$estrato), ]
media_preciom <- mean(vivienda_sin_estrato_faltante$preciom, na.rm = TRUE)
media_areaconst <- mean(vivienda_sin_estrato_faltante$areaconst, na.rm = TRUE)
media_parqueaderos <- mean(vivienda_sin_estrato_faltante$parqueaderos, na.rm = TRUE)
media_banios <- mean(vivienda_sin_estrato_faltante$banios, na.rm = TRUE)
media_habitaciones <- mean(vivienda_sin_estrato_faltante$habitaciones, na.rm = TRUE)
vivienda_imputada <- vivienda_sin_estrato_faltante
vivienda_imputada$preciom[is.na(vivienda_imputada$preciom)] <- media_preciom
vivienda_imputada$areaconst[is.na(vivienda_imputada$areaconst)] <- media_areaconst
vivienda_imputada$parqueaderos[is.na(vivienda_imputada$parqueaderos)] <- media_parqueaderos
vivienda_imputada$banios[is.na(vivienda_imputada$banios)] <- media_banios
vivienda_imputada$habitaciones[is.na(vivienda_imputada$habitaciones)] <- media_habitaciones
moda_zona <- names(which.max(table(vivienda_sin_estrato_faltante$zona)))
moda_piso <- names(which.max(table(vivienda_sin_estrato_faltante$piso)))
moda_tipo <- names(which.max(table(vivienda_sin_estrato_faltante$tipo)))
vivienda_imputada$zona[is.na(vivienda_imputada$zona)] <- moda_zona
vivienda_imputada$piso[is.na(vivienda_imputada$piso)] <- moda_piso
vivienda_imputada$tipo[is.na(vivienda_imputada$tipo)] <- moda_tipo
grafico <-md.pattern(vivienda_imputada, rotate.names = TRUE)
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
summary(vivienda_imputada)
## id zona piso estrato
## Min. : 1 Length:8319 Length:8319 Min. :3.000
## 1st Qu.:2080 Class :character Class :character 1st Qu.:4.000
## Median :4160 Mode :character Mode :character Median :5.000
## Mean :4160 Mean :4.634
## 3rd Qu.:6240 3rd Qu.:5.000
## Max. :8319 Max. :6.000
## preciom areaconst parqueaderos banios
## Min. : 58.0 Min. : 30.0 Min. : 1.000 Min. : 0.000
## 1st Qu.: 220.0 1st Qu.: 80.0 1st Qu.: 1.000 1st Qu.: 2.000
## Median : 330.0 Median : 123.0 Median : 1.835 Median : 3.000
## Mean : 433.9 Mean : 174.9 Mean : 1.835 Mean : 3.111
## 3rd Qu.: 540.0 3rd Qu.: 229.0 3rd Qu.: 2.000 3rd Qu.: 4.000
## Max. :1999.0 Max. :1745.0 Max. :10.000 Max. :10.000
## habitaciones tipo barrio longitud
## Min. : 0.000 Length:8319 Length:8319 Min. :-76.59
## 1st Qu.: 3.000 Class :character Class :character 1st Qu.:-76.54
## Median : 3.000 Mode :character Mode :character Median :-76.53
## Mean : 3.605 Mean :-76.53
## 3rd Qu.: 4.000 3rd Qu.:-76.52
## Max. :10.000 Max. :-76.46
## latitud
## Min. :3.333
## 1st Qu.:3.381
## Median :3.416
## Mean :3.418
## 3rd Qu.:3.452
## Max. :3.498
par(mfrow=c(2,3))
hist(vivienda_imputada$preciom, main="Precio de la vivienda", xlab="Precio (en millones de pesos)")
hist(vivienda_imputada$areaconst, main="Área construida", xlab="Área (en metros cuadrados)")
hist(vivienda_imputada$parqueaderos, main="Número de parqueaderos", xlab="Número de parqueaderos")
hist(vivienda_imputada$banios, main="Número de baños", xlab="Número de baños")
hist(vivienda_imputada$habitaciones, main="Número de habitaciones", xlab="Número de habitaciones")
table(vivienda_imputada$zona)
##
## Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
## 124 1920 1198 351 4726
barplot(prop.table(table(vivienda$zona)),col=c("orange","blue", "red", "green", "yellow"),
legend.text=c("Zona Centro","Zona Norte","Zona Oeste","Zona Oriente", "Zona Sur"),
ylim=c(0,1.2),ylab="Frecuencias Relativas")
Inicialmente empezaremos a conocer las variables cualitativas, donde nos encontramos con que la zona mas común en la que viven las personas es la zona sur (4726 registros), seguido de la zona norte (1920 registros) y la zona oeste (1198 registros).
table(vivienda_imputada$tipo)
##
## Apartamento Casa
## 5100 3219
proporciones <- c(5100, 3219) # creamos un vector con proporciones
etiquetas <- c("apartamento", "casa") # vector con etiquetas
pct <- round(proporciones/sum(proporciones)*100)
etiquetas <- paste(etiquetas, pct) # Añadimos porcentajes a etiquetas
etiquetas <- paste(etiquetas,"%",sep="") # Añadimos el símbolo de %
pie(proporciones,labels = etiquetas,
col=rainbow(length(etiquetas)),
main="Diagrama de torta: tipo de vivienda")
legend("topright", c("apartamento","casa"), cex = 0.8,
fill = rainbow(length(proporciones)))
tabla_cruce <- table(vivienda_imputada$tipo, vivienda_imputada$zona)
tabla_cruce
##
## Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
## Apartamento 24 1198 1029 62 2787
## Casa 100 722 169 289 1939
base_filtrada <- subset(vivienda_imputada, tipo == "Casa" & zona == "Zona Norte")
head(base_filtrada, 3)
## # A tibble: 3 x 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 1.84 7 6
## # i 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
table(base_filtrada$tipo) # Verificar que solo haya casas en la base filtrada
##
## Casa
## 722
table(base_filtrada$zona) # Verificar que solo haya la zona norte en la base filtrada
##
## Zona Norte
## 722
datos_numericos <- subset(vivienda_imputada, select = c(areaconst, estrato, banios, habitaciones, preciom))
scatter_price_area <- plot_ly(data = vivienda_imputada, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers',
marker = list(color = ~estrato, colorscale = 'Viridis'), text = ~paste("Precio:", preciom, "<br>Area construida:", areaconst))
bar_price_zone <- plot_ly(data = vivienda_imputada, x = ~zona, y = ~preciom, type = 'bar', text = ~paste("Precio medio:", round(preciom, 2)))
correlation_plot <- plot_ly(data = vivienda_imputada, z = ~cor(datos_numericos), type = "heatmap", colorscale = "Viridis",
colorbar = list(title = "Coeficiente de correlación"))
subplot(scatter_price_area, bar_price_zone, correlation_plot, nrows = 3)
correlacion_numerica <- cor(datos_numericos)
correlacion_numerica
## areaconst estrato banios habitaciones preciom
## areaconst 1.0000000 0.27432332 0.6484165 0.51691292 0.6873520
## estrato 0.2743233 1.00000000 0.4203218 -0.07137615 0.6098066
## banios 0.6484165 0.42032178 1.0000000 0.58990641 0.6691456
## habitaciones 0.5169129 -0.07137615 0.5899064 1.00000000 0.2640912
## preciom 0.6873520 0.60980664 0.6691456 0.26409121 1.0000000
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = vivienda_imputada)
summary(modelo)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = vivienda_imputada)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1426.78 -85.07 -15.14 54.10 1133.31
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -411.62275 11.17832 -36.82 <2e-16 ***
## areaconst 0.87314 0.01881 46.42 <2e-16 ***
## estrato 101.92605 2.26465 45.01 <2e-16 ***
## habitaciones -23.41983 1.82839 -12.81 <2e-16 ***
## parqueaderos 72.94084 2.29843 31.73 <2e-16 ***
## banios 54.98500 2.18084 25.21 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 170.9 on 8313 degrees of freedom
## Multiple R-squared: 0.7296, Adjusted R-squared: 0.7295
## F-statistic: 4487 on 5 and 8313 DF, p-value: < 2.2e-16
RESIDUALES: Estas son las diferencias entre los valores observados y los valores predichos por el modelo. Los residuos son cercanos a cero, lo que indica que el modelo ajustado está capturando bien la variabilidad en los datos.
COEFICIENTES:
NIVEL DE SIGNIFICANCIA: Indican el nivel de significancia de cada coeficiente. En este caso, todos los coeficientes tienen un p-value muy bajo (< 0.001), lo que indica que son estadísticamente significativos.
AJUSTE DEL MODELO: Es una medida de la proporción de la variabilidad en la variable respuesta que es explicada por el modelo. En este caso, el R-cuadrado ajustado es 0.7295, lo que significa que aproximadamente el 73% de la variabilidad en el precio de la casa puede ser explicada por las variables predictoras incluidas en el modelo.
ESTADISTICO F: Es una prueba de la significancia global del modelo. Un valor alto del estadístico F y un p-value bajo indican que al menos una de las variables predictoras tiene un efecto significativo en la variable respuesta. En este caso, el p-value es muy bajo (< 0.001), lo que indica que el modelo en su conjunto es significativo.
En general, el modelo parece tener un buen ajuste a los datos, ya que explica una proporción significativa de la variabilidad en el precio de la casa, como lo indica el R-cuadrado ajustado de aproximadamente 0.73. Esto sugiere que las variables incluidas en el modelo son importantes para predecir el precio de la casa.
Los coeficientes estimados tienen sentido en el contexto del mercado inmobiliario. Por ejemplo, es lógico esperar que el área construida, el estrato, el número de parqueaderos y el número de baños tengan un efecto positivo en el precio de la casa, ya que estas características suelen aumentar el valor de una propiedad. Por otro lado, el número de habitaciones podría tener un efecto negativo si las casas con más habitaciones tienden a ser más grandes pero menos costosas por habitación.
Para mejorar el modelo, podríamos considerar la inclusión de otras variables relevantes, como la ubicación específica de la vivienda o explorar interacciones entre variables. La inclusión de estas variables adicionales podría ayudar a capturar aún más la variabilidad en el precio de la casa y mejorar la capacidad predictiva del modelo.
hist(resid(modelo), main = "Histograma de Residuos", xlab = "Residuos")
qqnorm(resid(modelo), main = "Gráfico Q-Q de Residuos")
qqline(resid(modelo))
ks.test(resid(modelo), "pnorm", mean = mean(resid(modelo)), sd = sd(resid(modelo)))
## Warning in ks.test(resid(modelo), "pnorm", mean = mean(resid(modelo)), sd =
## sd(resid(modelo))): ties should not be present for the Kolmogorov-Smirnov test
##
## One-sample Kolmogorov-Smirnov test
##
## data: resid(modelo)
## D = 0.13735, p-value < 2.2e-16
## alternative hypothesis: two-sided
Prueba de Kolmogorov-Smirnov: Esta prueba compara la distribución empírica de los datos con una distribución teórica (en este caso, una distribución normal) y evalúa si hay evidencia suficiente para concluir que los datos provienen de la distribución especificada.
Dado que el valor p es menor que el nivel de significancia (0.05) indica que hay evidencia suficiente para rechazar la hipótesis nula de que los datos siguen una distribución normal.
plot(fitted(modelo), rstandard(modelo), main = "Gráfico de Residuos Estandarizados vs. Valores Ajustados", xlab = "Valores Ajustados", ylab = "Residuos Estandarizados")
abline(h = 0, col = "red")
residuos <- residuals(modelo)
bptest(modelo)
##
## studentized Breusch-Pagan test
##
## data: modelo
## BP = 1473, df = 5, p-value < 2.2e-16
Prueba de Breusch-Pagan: La prueba de Breusch-Pagan es una prueba de heterocedasticidad que se basa en la idea de que si hay heterocedasticidad en el modelo, entonces la varianza de los residuos estará correlacionada con una o más variables independientes del modelo. La hipótesis nula de la prueba es que no hay heterocedasticidad en el modelo. La prueba de Breusch-Pagan calcula un estadístico de prueba que sigue una distribución chi-cuadrado bajo la hipótesis nula.
Dado que el valor p es menor que el nivel de significancia (0.05), se puede concluir que hay evidencia de heterocedasticidad y que el supuesto de homocedasticidad no se cumple.
acf(resid(modelo), main = "Gráfico de Autocorrelación de Residuos")
dwtest(modelo)
##
## Durbin-Watson test
##
## data: modelo
## DW = 1.6166, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
Prueba de Durbin-Watson: La prueba de Durbin-Watson es una prueba estadística utilizada para detectar la presencia de autocorrelación de primer orden en los residuos de un modelo de regresión. La autocorrelación de primer orden se refiere a la correlación entre los residuos adyacentes en el tiempo o en el orden de observación. La hipótesis nula de la prueba es que no hay autocorrelación de primer orden en los residuos. Los valores de la estadística de prueba de Durbin-Watson oscilan entre 0 y 4. Un valor cercano a 2 sugiere que no hay autocorrelación de primer orden. Un valor significativamente menor que 2 sugiere autocorrelación positiva (residuos adyacentes están correlacionados positivamente), mientras que un valor significativamente mayor que 2 sugiere autocorrelación negativa (residuos adyacentes están correlacionados negativamente).
Dado que el valor p es menor que el nivel de significancia (0.05), se puede concluir que hay evidencia de autocorrelación de primer orden en los residuos del modelo.
vif_values <- vif(modelo)
print(vif_values)
## areaconst estrato habitaciones parqueaderos banios
## 2.057973 1.546350 2.027009 1.536296 2.761337
Se puede verificar la multicolinealidad calculando los coeficientes de correlación entre las variables predictoras o mediante pruebas estadísticas como el factor de inflación de la varianza (VIF). Si se observa multicolinealidad, podrían considerarse técnicas de selección de variables o combinación de variables para reducir la multicolinealidad.
Factor de inflación de la varianza (VIF): El VIF mide cuánto aumenta la varianza de un coeficiente de regresión debido a la multicolinealidad con otras variables predictoras. Un VIF mayor que 10 o 5 podría indicar la presencia de multicolinealidad problemática.
Dado que el VIF es menor que 5 no hay presencia de multicolinealidad problematica como resultado.
set.seed(123)
indices_entrenamiento <- createDataPartition(vivienda_imputada$preciom, p = 0.7, list = FALSE)
datos_entrenamiento <- vivienda_imputada[indices_entrenamiento, ]
datos_prueba <- vivienda_imputada[-indices_entrenamiento, ]
modelo_entrenado <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = datos_entrenamiento)
summary(modelo_entrenado)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = datos_entrenamiento)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1353.45 -86.72 -15.35 55.81 1144.12
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -420.38034 13.52766 -31.08 <2e-16 ***
## areaconst 0.82752 0.02261 36.59 <2e-16 ***
## estrato 102.78029 2.74496 37.44 <2e-16 ***
## habitaciones -23.76279 2.21615 -10.72 <2e-16 ***
## parqueaderos 73.97200 2.78444 26.57 <2e-16 ***
## banios 58.68108 2.62139 22.39 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 173.4 on 5820 degrees of freedom
## Multiple R-squared: 0.7233, Adjusted R-squared: 0.7231
## F-statistic: 3043 on 5 and 5820 DF, p-value: < 2.2e-16
El modelo ajustado con los datos de entrenamiento muestra un buen ajuste a los datos, con un R cuadrado ajustado de 0.7231, lo que indica que alrededor del 72.31% de la variabilidad en el precio de las viviendas se explica por las variables predictoras incluidas en el modelo.
Área construida (areaconst): El coeficiente estimado es aproximadamente 0.8275. Esto sugiere que, manteniendo constantes las demás variables, un aumento de 1 metro cuadrado en el área construida se asocia con un aumento de aproximadamente 0.8275 millones de pesos en el precio de la vivienda.
Estrato (estrato): El coeficiente estimado es 102.7803. Esto indica que, manteniendo constantes las demás variables, pasar de un estrato a otro se asocia con un aumento de aproximadamente 102.7803 millones de pesos en el precio de la vivienda.
Número de habitaciones (habitaciones): El coeficiente estimado es -23.7628. Esto indica que, manteniendo constantes las demás variables, un incremento de una habitación se asocia con una disminución de aproximadamente 23.7628 millones de pesos en el precio de la vivienda.
Número de parqueaderos (parqueaderos): El coeficiente estimado es 73.972. Esto sugiere que, manteniendo constantes las demás variables, un parqueadero adicional se asocia con un aumento de aproximadamente 73.972 millones de pesos en el precio de la vivienda.
Número de baños (banios): El coeficiente estimado es 58.6811. Esto indica que, manteniendo constantes las demás variables, un baño adicional se asocia con un aumento de aproximadamente 58.6811 millones de pesos en el precio de la vivienda.
Todos los coeficientes estimados son estadísticamente significativos (p < 0.05), lo que sugiere que estas variables tienen un efecto significativo en el precio de las viviendas.
predicciones <- predict(modelo_entrenado, newdata = datos_prueba)
head(predicciones)
## 1 2 3 4 5 6
## 288.04388 344.24239 681.01852 647.09753 372.77366 74.20807
mse <- mean((datos_prueba$preciom - predicciones)^2)
mae <- mean(abs(datos_prueba$preciom - predicciones))
r_squared <- 1 - sum((datos_prueba$preciom - predicciones)^2) / sum((datos_prueba$preciom - mean(datos_prueba$preciom))^2)
print(paste("Error Cuadrático Medio (MSE):", mse))
## [1] "Error Cuadrático Medio (MSE): 27330.7683221446"
print(paste("Error Absoluto Medio (MAE):", mae))
## [1] "Error Absoluto Medio (MAE): 107.31688167852"
print(paste("Coeficiente de Determinación (R cuadrado):", r_squared))
## [1] "Coeficiente de Determinación (R cuadrado): 0.743745336320348"
Los resultados de la evaluación del modelo con los datos de prueba son los siguientes:
Error Cuadrático Medio (MSE=27330.77): Esto indica que, en promedio, el cuadrado de la diferencia entre las predicciones del modelo y los valores reales es de aproximadamente 27330.77.
Error Absoluto Medio (MAE=107.32): Esto indica que, en promedio, la diferencia absoluta entre las predicciones del modelo y los valores reales es de aproximadamente 107.32.
Coeficiente de Determinación (R cuadrado=0.7437): Esto indica que aproximadamente el 74.37% de la variabilidad en el precio de las viviendas se explica por las variables incluidas en el modelo.