library(paqueteMODELOS)
library(naniar)
library(knitr)
library(kableExtra)
library(lmtest)
library(leaflet)
library(ggplot2)
library(plotly)
library(corrplot)
data(vivienda)
datos <- vivienda
#visualizar datos faltantes
print(faltantes <- colSums(is.na(datos)) %>%
as.data.frame())
## .
## id 3
## zona 3
## piso 2638
## estrato 3
## preciom 2
## areaconst 3
## parqueaderos 1605
## banios 3
## habitaciones 3
## tipo 3
## barrio 3
## longitud 3
## latitud 3
gg_miss_var(datos) # Muestra la proporción de datos faltantes por cada variable
Las variables ‘piso’ y ‘parqueadero’ presentan gran cantidad de datos faltantes, por ende, se decide eliminar la variable ‘piso’, y para la variable ‘parqueadero’ se imputará con un valor fijo, tomando (0) suponiendo que las propiedades no tienen parqueaderos. A su vez, se decide por eliminar las variables ‘id’ y ‘barrio’ que no son relevantes en el análisis.
datos <- subset(datos, select = -c(id, piso, barrio))
#Rellenando valores NA de parqueadero
datos$parqueaderos[is.na(datos$parqueaderos)] <- 0
# Posteriormente, se eliminan filas con valores faltantes
datos <- datos[complete.cases(datos), ]
# Se visualiza la efectividad de los procesos de eliminación de datos faltantes
print(colSums(is.na(datos)) %>%
as.data.frame())
## .
## zona 0
## estrato 0
## preciom 0
## areaconst 0
## parqueaderos 0
## banios 0
## habitaciones 0
## tipo 0
## longitud 0
## latitud 0
print(datos)
## # A tibble: 8,319 × 10
## zona estrato preciom areaconst parqueaderos banios habitaciones tipo
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Zona Oriente 3 250 70 1 3 6 Casa
## 2 Zona Oriente 3 320 120 1 2 3 Casa
## 3 Zona Oriente 3 350 220 2 2 4 Casa
## 4 Zona Sur 4 400 280 3 5 3 Casa
## 5 Zona Norte 5 260 90 1 2 3 Apar…
## 6 Zona Norte 5 240 87 1 3 3 Apar…
## 7 Zona Norte 4 220 52 2 2 3 Apar…
## 8 Zona Norte 5 310 137 2 3 4 Apar…
## 9 Zona Norte 5 320 150 2 4 6 Casa
## 10 Zona Norte 5 780 380 2 3 3 Casa
## # ℹ 8,309 more rows
## # ℹ 2 more variables: longitud <dbl>, latitud <dbl>
df_casas = subset(datos, (datos$zona == "Zona Norte" & datos$tipo == "Casa"))
head(df_casas, 3)
## # A tibble: 3 × 10
## zona estrato preciom areaconst parqueaderos banios habitaciones tipo
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Zona Norte 5 320 150 2 4 6 Casa
## 2 Zona Norte 5 780 380 2 3 3 Casa
## 3 Zona Norte 6 750 445 0 7 6 Casa
## # ℹ 2 more variables: longitud <dbl>, latitud <dbl>
resul = data.frame(table(df_casas$tipo), table(df_casas$zona))
colnames(resul) = c("tipo", "conteo", "zona", "conteo")
resul
## tipo conteo zona conteo
## 1 Casa 722 Zona Norte 722
mapa_nort = leaflet() %>% addCircleMarkers(lng = df_casas$longitud,
lat = df_casas$latitud,
radius = 0.3,
color = "blue",
label = df_casas$id) %>% addTiles()
mapa_nort
A partir del análisis de la ubicación de las propiedades, se ha observado que gran parte de las propiedades de la zona norte son casas. Además, se detectan otras propiedades que se distribuyen de manera poco común en otras áreas de la ciudad. Esta anomalía es causada por posibles errores en la recopilación de datos.
Esta variabilidad atípica puede deberse a la interpretación de los resultados y a la toma de decisiones fundamentadas en estos datos. Por ello, es crucial tener en cuenta este factor al examinar y emplear información geoespacial, con el fin de evitar conclusiones inexactas o sesgadas. Siempre que sea posible, se sugiere realizar una revisión minuciosa de los registros de ubicación para identificar y corregir posibles errores, garantizando así la precisión de los datos geográficos en el análisis.
df_casas = subset(datos, (datos$tipo == "Casa"))
grafico_area <- plot_ly(data = df_casas, x = ~areaconst, y = ~preciom, type = "scatter", mode = "markers") %>%
layout(title = "Precio vs Área Construida",
xaxis = list(title = "Área Construida"),
yaxis = list(title = "Precio"))
grafico_area
summary(df_casas$areaconst)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 30.0 154.0 240.0 273.4 350.0 1745.0
correlacion_pearson <- cor(df_casas$areaconst, df_casas$preciom, method = "pearson")
print(correlacion_pearson)
## [1] 0.6529498
La media con respecto al área de la vivienda se sitúa en 273.4 metros cuadrados, lo que indica el promedio de todos los valores registrados. Por otro lado, la mediana se ubica en 240 metros cuadrados, lo que sugiere que la mitad de las propiedades tienen un área inferior a este valor central. Al observar la relación entre el metro cuadrado y el precio, se nota que no existe una correlación fuerte y directamente proporcional. Esto es respaldado por el coeficiente de correlación de Pearson, con un valor específico de 0.6529.
grafico_estrato <- plot_ly(data = df_casas, x = ~estrato, y = ~preciom, type = "box") %>%
layout(title = "Precio vs Estrato",
xaxis = list(title = "Estrato"),
yaxis = list(title = "Precio"))
grafico_estrato
correlacion_spearman <- cor(df_casas$preciom, df_casas$estrato, method = "spearman")
print(correlacion_spearman)
## [1] 0.7530054
En primer lugar, se puede apreciar que la relación entre el estrato socioeconómico y el precio es proporcional directa, y se justifica por el coeficiente de correlación de 0.7530. Algunas de las propiedades ubicadas en estrato 5 presentan valores de venta más altos, cerca de 1999 millones de pesos, debido a la presencia de valores atípicos identificados. Además, el 75 % de las propiedades tienen un precio por encia de los 650 millones de pesos y la mediana en el precio de venta es 480 millones de pesos, indicando que mitad de las propiedades tienen un precio de venta inferior a este valor.
grafico_banos <- plot_ly(data = df_casas, x = ~banios, y = ~preciom, type = "scatter", mode = "markers") %>%
layout(title = "Precio vs Número de Baños",
xaxis = list(title = "Número de Baños"),
yaxis = list(title = "Precio"))
grafico_banos
correlacion_pearson <- cor(df_casas$preciom, df_casas$banios, method = "pearson")
print(correlacion_pearson)
## [1] 0.5581002
summary(df_casas$banios)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 3.000 4.000 3.894 5.000 10.000
Para el número de baños, se calcula una media de 3.89 unidades, representando el valor promedio de todos los valores, mientras que la mediana es de 4 unidades, lo que sugiere que la mitad de las propiedades tienen cuatro baños o menos. Al examinar la relación entre el número de baños y el precio, se observa una dispersión en los datos. El coeficiente de correlación de Pearson obtenido es 0.5581, lo que indica una relación débil entre el precio y el número de baños.
grafico_habitaciones <- plot_ly(data = df_casas, x = ~habitaciones, y = ~preciom, type = "scatter", mode = "markers") %>%
layout(title = "Precio vs Número de Habitaciones",
xaxis = list(title = "Número de Habitaciones"),
yaxis = list(title = "Precio"))
grafico_habitaciones
correlacion_pearson <- cor(df_casas$preciom, df_casas$habitaciones, method = "pearson")
print(correlacion_pearson)
## [1] 0.09683573
summary(df_casas$habitaciones)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 3.00 4.00 4.61 5.00 10.00
En cuanto al número de habitaciones, la media es de 4.61 unidades y la mediana es de 4 unidades. Esto sugiere que, en promedio, las propiedades tienen aproximadamente cuatro habitaciones, y la mitad de las propiedades tienen cuatro habitaciones o menos. Al igual que con el número de baños, se observa una dispersión debil en la relación entre el número de habitaciones y el precio. El coeficiente de correlación de Pearson presenta un valor de de 0.097.
grafico_zona <- plot_ly(data = df_casas, x = ~zona, y = ~preciom, type = "box") %>%
layout(title = "Precio vs Zona",
xaxis = list(title = "Zona"),
yaxis = list(title = "Precio"))
grafico_zona
anova_result <- aov(preciom ~ zona, data = df_casas)
summary(anova_result)
## Df Sum Sq Mean Sq F value Pr(>F)
## zona 4 52244372 13061093 116.4 <2e-16 ***
## Residuals 3214 360654741 112214
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
En cuanto a la ubicación de las propiedades, la zona oeste presenta la mediana más alta, indicando que la mitad de las propiedades tienen un precio de 680 millones de pesos en el mercado inmobiliario. Además, alrededor del 75 % de las casas tienen un precio de venta cercano a 935 millones de pesos en dicha zona. El análisis de varianza (ANOVA) sugiere que existen diferencias significativas en el precio de la casa entre las diferentes zonas.El valor p (<2e-16) es mucho menor que el nivel de significancia común (0.05), por lo que rechazamos la hipótesis nula de que no hay diferencias entre las zonas.
df_casas$estrato = as.numeric(df_casas$estrato)
modelo1=lm(preciom~ areaconst + estrato + habitaciones + parqueaderos + banios, df_casas)
summary(modelo1)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = df_casas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1319.88 -113.30 -25.16 69.75 1179.44
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -345.92562 20.29873 -17.042 < 2e-16 ***
## areaconst 0.81001 0.02538 31.913 < 2e-16 ***
## estrato 112.80957 4.44614 25.372 < 2e-16 ***
## habitaciones -13.63190 2.57845 -5.287 1.33e-07 ***
## parqueaderos 40.30572 2.78541 14.470 < 2e-16 ***
## banios 38.52338 3.32115 11.599 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 203.9 on 3213 degrees of freedom
## Multiple R-squared: 0.6765, Adjusted R-squared: 0.676
## F-statistic: 1344 on 5 and 3213 DF, p-value: < 2.2e-16
El término independiente, o intercepto, se establece en -345.9256. Esto indica el valor estimado de una vivienda cuando todas las demás variables en el modelo están en cero. En la práctica, este escenario es poco probable, ya que no puede haber una casa con área construida, estrato, habitaciones, parqueaderos y baños iguales a cero.
El coeficiente correspondiente al área construida es de 0.81. Esto implica que por cada metro cuadrado adicional en la propiedad, el precio aumenta en 0.81 millones de pesos, manteniendo las otras variables constantes. Similarmente, el coeficiente para el estrato es de 112.81, indicando que por cada aumento de un nivel en el estrato socioeconómico, el precio de la casa aumenta en 112.81 millones de pesos, manteniendo constantes las demás variables. A su vez, el coeficiente indicado parra el número de habitaciones indica que por cada habitación adicional, el precio de la casa disminuye en 13.63 millones de pesos, manteniendo constantes las demás variables. Este resultado podría indicar un problema de multicolinealidad o una relación no lineal. El coeficiente correspondiente a parqueaderos indica que por cada parqueadero adicional, el precio de la casa aumenta en 40.31 millones de pesos, manteniendo constantes las demás variables. Del mismo modo, El coeficiente relacionado por el número de baños indica que por cada baño adicional, el precio de la casa aumenta en 38.52 millones de pesos, manteniendo constantes las demás variables.
El coeficiente de determinación R² se calcula en 0.6765. Esto significa que aproximadamente el 67.65% de la variabilidad observada en los precios de las casas puede ser explicada por las variables incluidas en el modelo.
En términos de mejoras al modelo, se sugiere considerar la eliminación de variables que no aporten significativamente al modelo para aumentar su eficacia o realizar transformaciones a relaciones no lineales.
#Linealidad
# Gráfico de residuos vs valores ajustados
plot(fitted(modelo1), residuals(modelo1), main = "Residuos vs Ajustados", xlab = "Valores Ajustados", ylab = "Residuos")
abline(h = 0, col = "red")
# Prueba de Durbin-Watson
library(lmtest)
dwtest(modelo1)
##
## Durbin-Watson test
##
## data: modelo1
## DW = 1.5127, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
# Prueba de Breusch-Pagan
library(lmtest)
bptest(modelo1)
##
## studentized Breusch-Pagan test
##
## data: modelo1
## BP = 397.81, df = 5, p-value < 2.2e-16
# Histograma de residuos
hist(residuals(modelo1), main = "Histograma de Residuos", xlab = "Residuos")
# Prueba de Shapiro-Wilk
shapiro.test(residuals(modelo1))
##
## Shapiro-Wilk normality test
##
## data: residuals(modelo1)
## W = 0.88308, p-value < 2.2e-16
# Calcular VIF
library(car)
vif(modelo1)
## areaconst estrato habitaciones parqueaderos banios
## 1.465483 1.818414 1.613973 1.552399 2.102466
En la gráfica de linealidad se observa que los residuos no se distribuyen aleatoriamente alrededor de la línea horizontal en 0, creando patrones claros de agrupamiento, y por tanto no se cumple el supuesto de linealidad. En el valor estadístico de Durbin-Watson, se aprecia que DW = 1.51, indicando que existe autocorrelación positiva. Asimismo, en la prueba de Breusch-Pagan, el valor p es menor que 0.05, indicando presencia de heterocedasticidad. La prueba de Shapiro-Wilk el valor p es menor que el umbral 0.05, y los residuos no siguen una distribución normal. Además, el Factor de Inflación de la Varianza (VIF) para cada variable fue menor que 5, indicando que no hay multicolinealidad.
Para corregir estos aspectos se podría considerar la transformación de la variable dependiente o también se podría solucionar utilizando modelos más robustos.
df1= data.frame(
areaconst = 200,
parqueaderos = 1,
estrato = c(4, 5),
banios = 2,
habitaciones = 4,
tipo='Casa',
zona='Norte'
)
df1
## areaconst parqueaderos estrato banios habitaciones tipo zona
## 1 200 1 4 2 4 Casa Norte
## 2 200 1 5 2 4 Casa Norte
predict(modelo1,df1)
## 1 2
## 330.1387 442.9483
# Generar predicciones
df_casas$prediccion <- predict(modelo1, newdata = df_casas)
# Filtrar viviendas dentro del rango
ofertas <- df_casas %>% filter(prediccion <= 350, areaconst <= 200, parqueaderos <= 1,
banios <= 2, habitaciones <= 4, zona == "Zona Norte",
estrato ==c(4, 5))
# Ordenar por precio predicho y seleccionar las 5 mejores ofertas
ofertas <- ofertas %>% arrange(prediccion) %>% head(5)
# Seleccionar columnas relevantes para la tabla
ofertas_tabla <- ofertas %>%
select(prediccion, areaconst, estrato, habitaciones, banios, parqueaderos, latitud, longitud)
library(DT)
# Creación de la tabla
datatable(ofertas_tabla,
colnames = c("#", "Precio Predicho (Millones de pesos)", "Área Construida (m²)", "Estrato",
"Habitaciones", "Baños", "Parqueaderos", "Latitud", "Longitud"),
options = list(
pageLength = 5,
dom = 't',
scrollX = TRUE
))
library(leaflet)
mapa <- leaflet(ofertas) %>%
addTiles() %>%
addMarkers(
lng = ~longitud, lat = ~latitud,
popup = ~paste(
"Precio Predicho: $", round(prediccion), "M<br>",
"Área Construida: ", areaconst, "m²<br>",
"Estrato: ", estrato, "<br>",
"Habitaciones: ", habitaciones, "<br>",
"Baños: ", banios, "<br>",
"Parqueaderos: ", parqueaderos
)
)
mapa
Por medio de un análisis se puede concluir que la quinta oferta es la más apropiada y cumple con gran parte de las características. Además, es importante precisar que cumple con el límite de crédito preaprobado de 350 millones de pesos. Sin embargo, las demás ofertas presentan características y ubicaciones diferentes para discutir opciones viables con el cliente.