A continuación, se presenta un informe detallado sobre el trabajo realizado para una inmobiliaria en respuesta a una solicitud de compra de vivienda en dos zonas distintas de Cali. Este análisis se basa en un conjunto de datos de ofertas inmobiliarias y tiene como objetivo filtrar, analizar y modelar la información para identificar las mejores opciones disponibles según las necesidades del cliente y las condiciones del crédito pre-aprobado.
El informe se estructura en varias secciones. Primero, se realiza un filtro de la base de datos para incluir únicamente las casas ubicadas en la zona norte de la ciudad, presentando un resumen de los primeros registros y una visualización geoespacial de las ofertas disponibles. Luego, se lleva a cabo un análisis exploratorio de datos enfocado en la correlación entre el precio de la vivienda y diversas características como el área construida, el estrato, el número de habitaciones y baños, entre otras. Posteriormente, se estima un modelo de regresión lineal múltiple para evaluar la relación entre estas variables y el precio de la vivienda, interpretando los coeficientes y la calidad del ajuste del modelo. Además, se realiza la validación de supuestos del modelo y se formulan recomendaciones para mejorar su desempeño.
Con base en el modelo identificado, se predicen los precios de viviendas con características específicas de la solicitud y se sugieren opciones viables dentro del presupuesto establecido. Finalmente, este procedimiento se replica para la segunda solicitud, asegurando un análisis completo y detallado para ambas zonas de interés.Para la base de datos completa de la ciudad de Cali se hallo un total de 5,100 apartamentos y 3,219 casas, lo que indica una mayor oferta de apartamentos en comparación con casas.
Distribución de Viviendas por EstratoEn cuanto a la distribución de viviendas por estrato, se encontró que:
El estrato 5 es el más predominante, seguido del estrato 4.
Distribución por ZonasRespecto a la distribución por zonas, la mayor concentración de viviendas se encuentra en:
Tras evaluar distintos enfoques para preservar la variable estrato en la regresión, dado su impacto en la valorización de la vivienda y su relación con el nivel socioeconómico, se logró identificar su importancia en la determinación del precio. Para la primera solicitud, una vivienda con 200 m² de área construida, 1 parqueadero, 2 baños y 4 habitaciones, ubicada en estratos 4 y 5, se estimaron los siguientes valores:
Para la segunda solictud, un apartamento en la Zona Sur de Cali con 300 m² de área construida, 3 parqueaderos, 3 baños y 5 habitaciones, se realizó un análisis considerando el impacto del estrato en la valorización del inmueble.
Los resultados muestran que, manteniendo las mismas características y variando únicamente el estrato, se obtuvieron los siguientes valores estimados:
##
## Apartamento Casa
## 5100 3219
Se encuentra que en la ciudad de Cali existen 5100 apartamentos y 3219 casas.
##
## 3 4 5 6
## 1453 2129 2750 1987
En relación al estrato se encutra que el estrato 5 es el concepto mayor numero de viviendas, seguido del estrato 4.
##
## Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
## 124 1920 1198 351 4726
Por ultimo, la zonas donde se ubican en mayor preponderiancia las viviendas son la zona sur con 4726 viviedas seguido de la zona norte con 1920.
## 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
## # 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>
Observamos cuantos elementos tenemos para nuestro tipo de vivienda y su zona geografica respectiva.
##
## Casa
## Zona Norte 722
Por lo anterior, se tiene que existen 722 casas en la zona norte.
mapa_norte = leaflet(data = variable_1) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitud, lat = ~latitud,
radius = 2,
color = "red",
fillOpacity = 0.7,
stroke = FALSE)
mapa_norte## id zona piso estrato preciom areaconst
## 0 0 372 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 287 0 0 0 0 0
## latitud
## 0
Procedo a mirar las caracteriticas de la variable piso. Para lo cual arroja como resultado que tiene formato de texto.
## Length Class Mode
## 722 character character
Por lo anterior, como la variable contiene números en formato de texto los proceso a cambiar a numeros. por consiguiente procedo a mirar las estadisticas de esa variable.
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.000 2.000 2.000 1.994 2.000 7.000 372
Miramos ahora la distribución de la variable para poder determinar la imputación.
Si el p-valor es mayor a 0.05, no se rechaza la hipótesis nula,
indicando que los datos podrían no seguir una distribución normal.
Si el p-valor es menor a 0.05, se rechaza la hipótesis nula, concluyendo
que los datos siguen una distribución normal.
##
## Shapiro-Wilk normality test
##
## data: variable_1$piso
## W = 0.7956, p-value < 2.2e-16
Tenemos un p-valor obtenido es < 2.2e-16, se cumple la condición para rechazar la hipótesis nula. Por lo tanto, se concluye que la variable piso no sigue una distribución normal. Así pues, cumpliendo el criterio de una no normalidad = mediana. Se procede a utilizar una tabla de resumen con la mediana del área construida en relación al número de pisos para poder hacer imputación.
tabla_resumen = aggregate(variable_1$areaconst,
by = list(Piso = variable_1$piso),
FUN = median, na.rm = TRUE)
colnames(tabla_resumen)[2] = "Mediana_AreaConstruida"
print(tabla_resumen)## Piso Mediana_AreaConstruida
## 1 1 246.5
## 2 2 254.0
## 3 3 200.0
## 4 4 177.5
## 5 7 470.0
#variable_1$piso = ifelse(
# is.na(variable_1$piso) & variable_1$areaconst <= 177.5, 4,
# ifelse(is.na(variable_1$piso) & variable_1$areaconst > 177.5 & variable_1$areaconst <= 200.0, 3,
# ifelse(is.na(variable_1$piso) & variable_1$areaconst > 200.0 & variable_1$areaconst <= 246.5, 1,
# ifelse(is.na(variable_1$piso) & variable_1$areaconst > 246.5 & variable_1$areaconst <= 254.0, 2,
# ifelse(is.na(variable_1$piso) & variable_1$areaconst > 254.0 & variable_1$areaconst <= 470.0, 7,
# ifelse(is.na(variable_1$piso) & variable_1$areaconst > 470.0, 7,
# variable_1$piso))))))
#cat("Valores NA restantes en 'piso':", sum(is.na(variable_1$piso)), "\n")
#table(variable_1$piso)imputacion_piso = variable_1[, c("piso", "areaconst")]
# Aplicar la imputación KNN (k = 5 es un valor común, pero se puede ajustar)
variable_1_imputado = kNN(imputacion_piso,
variable = "piso", # Variable a imputar
k = 5, # Número de vecinos
imp_var = FALSE) # No agregar columnas auxiliares
variable_1$piso = variable_1_imputado$piso # Reemplazar la columna imputada en el dataset original
cat("Valores NA restantes en 'piso':", sum(is.na(variable_1$piso)), "\n") # Mirar si quedaron datos faltantes## Valores NA restantes en 'piso': 0
##
## 1 2 3 4 7
## 135 494 86 6 1
El proceso de imputación fue correcto.
ggplot(variable_1, aes(x = factor(piso))) +
geom_bar(fill = "red", color = "black") +
labs(title = "Distribucion de Pisos Tras la Imputacion KNN",
x = "Piso",
y = "Frecuencia") +
theme_minimal()ggplot(variable_1, aes(x = areaconst, y = factor(piso), color = factor(piso))) +
geom_jitter(alpha = 0.7, size = 2) +
labs(title = "Relacion entre Area Construida y Piso Imputado",
x = "Area Construida",
y = "Piso") +
theme_minimal()## id zona piso estrato preciom areaconst
## 0 0 0 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 287 0 0 0 0 0
## latitud
## 0
Bajo el anterior resultado, se constata que la variable con Na solo es parqueaderos, para lo cual imputamos de nuevo.
imputacion_parqueadero = variable_1[, c("parqueaderos", "areaconst")]
variable_2_imputado = kNN(imputacion_parqueadero,
variable = "parqueaderos",
k = 5,
imp_var = FALSE)
variable_1$parqueaderos = variable_2_imputado$parqueaderos
cat("Valores NA restantes en 'parqueaderos':", sum(is.na(variable_1$parqueaderos)), "\n")## Valores NA restantes en 'parqueaderos': 0
##
## 1 2 3 4 5 6 7 8 9 10
## 296 268 80 51 11 8 5 1 1 1
El proceso de imputación fue correcto.
Procedemos a mirar la relación entre precio y area:
grafica_area_precio = plot_ly(data = variable_1, x = ~areaconst, y = ~preciom, color = ~zona,
type = "scatter", mode = "markers", marker = list(size = 10),
text = ~paste("Zona:", zona, "<br>Precio:", preciom, "<br>Area Construida:", areaconst)) %>%
layout(title = "Correlacion entre Precio y Área Construida",
xaxis = list(title = "Area Construida"),
yaxis = list(title = "Precio"))
grafica_area_precio## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
Bajo lo anterior, podemos aceverar que existe una correlación del 73% para afirmar que a medida que el area construida de la vivienda de la zona norte aumenta, asi mimso lo hace el precio.
Zona_casa = subset(variable_1, tipo == "Casa")
variables_interes = Zona_casa[, c("preciom", "areaconst", "estrato", "banios", "habitaciones", "parqueaderos")]
correlation_matrix = cor(variables_interes)
corrplot(correlation_matrix, method = "color", addCoef.col = "black", number.cex = 0.7)
La matriz de correlación muestra la relación lineal entre las variables
del modelo, con valores entre -1 y 1. Se observa una fuerte correlación
positiva entre el precio (preciom) y el área construida
(areaconst) con un valor de 0.73, indicando que a mayor
área, mayor es el precio. El estrato (estrato) también
presenta una correlación significativa con el precio (0.61), seguido por
el número de baños (banios) con 0.52 y los parqueaderos
(parqueaderos) con 0.45. Las habitaciones
(habitaciones) tienen una correlación baja (0.32) con el
precio. En cuanto a las relaciones entre predictores, se destaca la
correlación moderada entre baños y habitaciones (0.57) y entre área
construida y estrato (0.46). No se identifican correlaciones
extremadamente altas entre las variables predictoras, lo que puede que
indique una baja probabilidad de multicolinealidad.
modelo1 = lm(preciom ~ areaconst + habitaciones + parqueaderos + banios + estrato, data = variable_1)
summary(modelo1)##
## Call:
## lm(formula = preciom ~ areaconst + habitaciones + parqueaderos +
## banios + estrato, data = variable_1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -897.27 -79.61 -14.84 43.05 1088.01
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -236.6023 29.4534 -8.033 3.91e-15 ***
## areaconst 0.7878 0.0443 17.783 < 2e-16 ***
## habitaciones 0.7455 4.0932 0.182 0.85553
## parqueaderos 20.0147 5.4955 3.642 0.00029 ***
## banios 23.6731 5.3524 4.423 1.13e-05 ***
## estrato 82.4298 7.2011 11.447 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 157.7 on 716 degrees of freedom
## Multiple R-squared: 0.6571, Adjusted R-squared: 0.6547
## F-statistic: 274.4 on 5 and 716 DF, p-value: < 2.2e-16
Para validar supuestos de un modelo lineal:
Si el p-valor es mayor que el nivel de significancia del 5%, no se rechaza la hipótesis nula, indicando que los residuos siguen una distribución normal.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere que los residuos no son normales.
##
## Anderson-Darling normality test
##
## data: modelo1$residuals
## A = 25.5, p-value < 2.2e-16
Dado que el p-valor es menor que un nivel de significancia, se rechaza la hipótesis nula de que los residuos siguen una distribución normal.
Si el p-valor es mayor que el nivel de significancia del 5%, no se rechaza la hipótesis nula, indicando que los residuos son normales.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere que los residuos no son normales.
##
## Shapiro-Wilk normality test
##
## data: resid(modelo1)
## W = 0.8385, p-value < 2.2e-16
El p-valor es menor que el nivel de significancia por tanto se rechaza la hipótesis nula, que establece que los residuos tienen una distribución normal. Es decir, igual que el Anderson-Darling los residuos del modelo no son normales.
Si el p-valor es mayor que el nivel de significancia (por ejemplo, 0.05), no se rechaza la hipótesis nula, indicando homocedasticidad.
Si el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula, lo que sugiere heterocedasticidad en los residuos.
##
## studentized Breusch-Pagan test
##
## data: modelo1
## BP = 129.23, df = 5, p-value < 2.2e-16
Si el p-valor es mayor que un nivel de significancia del 5%, NO se rechaza H₀, lo que indica que no hay evidencia de heterocedasticidad.
Si el p-valor es menor que el nivel de significancia del 5%, SE rechaza H₀, lo que sugiere que hay evidencia de heterocedasticidad.
##
## Goldfeld-Quandt test
##
## data: modelo1
## GQ = 1.1028, df1 = 355, df2 = 355, p-value = 0.1785
## alternative hypothesis: variance increases from segment 1 to 2
El estadístico de Durbin-Watson (DW) varía entre 0 y 4:
##
## Durbin-Watson test
##
## data: modelo1
## DW = 1.6398, p-value = 5.095e-07
## alternative hypothesis: true autocorrelation is greater than 0
## areaconst habitaciones parqueaderos banios estrato
## 1.589877 1.622511 1.312713 1.928622 1.452233
Estamos buscando una casa en la zona norte, con un area de 200mt2 que tenga 1 parqueadero, 2 baños y 4 habitaciones ademas de que este en un estrato de 4 y 5.
solicitud1 = data.frame(
areaconst = 200,
parqueaderos = 1,
estrato = c(4, 5),
banios = 2,
habitaciones = 4
)
print(solicitud1)## areaconst parqueaderos estrato banios habitaciones
## 1 200 1 4 2 4
## 2 200 1 5 2 4
Bajo el anterior resultado encontramos productos adecuados a la solicitud, empero estos no tiene
Como tenemos una variable ordinal, para manejar usamos el one-hot encoding para convertirlas en variables dummy.
library(fastDummies)
variable_1 = dummy_cols(variable_1,
select_columns = "estrato",
remove_first_dummy = FALSE,
remove_selected_columns = FALSE)
colnames(variable_1) = sub("^estrato_", "estrato.", colnames(variable_1))
head(variable_1)## # A tibble: 6 × 17
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1209 Zona N… 2 5 320 150 2 4 6
## 2 1592 Zona N… 2 5 780 380 2 3 3
## 3 4057 Zona N… 2 6 750 445 2 7 6
## 4 4460 Zona N… 2 4 625 355 3 5 5
## 5 6081 Zona N… 2 5 750 237 2 6 6
## 6 7824 Zona N… 2 4 600 160 1 4 5
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # estrato.3 <int>, estrato.4 <int>, estrato.5 <int>, estrato.6 <int>
modelohot = lm(preciom ~ areaconst + habitaciones + parqueaderos + banios +
estrato.3 + estrato.4 + estrato.5 + estrato.6,
data = variable_1)
summary(modelohot)##
## Call:
## lm(formula = preciom ~ areaconst + habitaciones + parqueaderos +
## banios + estrato.3 + estrato.4 + estrato.5 + estrato.6, data = variable_1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -905.96 -73.54 -14.87 46.56 1081.06
##
## Coefficients: (1 not defined because of singularities)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 339.33007 30.78775 11.022 < 2e-16 ***
## areaconst 0.78765 0.04365 18.043 < 2e-16 ***
## habitaciones 1.27377 4.06436 0.313 0.754069
## parqueaderos 20.92767 5.41954 3.862 0.000123 ***
## banios 22.60229 5.35561 4.220 2.75e-05 ***
## estrato.3 -321.66433 26.30550 -12.228 < 2e-16 ***
## estrato.4 -240.95403 25.01771 -9.631 < 2e-16 ***
## estrato.5 -190.42701 23.34232 -8.158 1.53e-15 ***
## estrato.6 NA NA NA NA
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 155.4 on 714 degrees of freedom
## Multiple R-squared: 0.6681, Adjusted R-squared: 0.6648
## F-statistic: 205.3 on 7 and 714 DF, p-value: < 2.2e-16
Varias cosas aqui, el hecho de que el estrato.6 esté marcado como NA indica colinealidad, lo que podría distorsionar las interpretaciones de los coeficiente puesto que el coeficiente de los estratos es negativo, lo que parece contrario a la intuición (normalmente, se espera que el precio aumente con el estrato). Asi pues comprobamos la muticolenalidad con el siguiente resultado (esta en #, puesto que al compilar en Rmarkdown ponia limitantes):
modelohot_ajustado = lm(preciom ~ areaconst + habitaciones + parqueaderos + banios
+ estrato.4 + estrato.5 + estrato.6,
data = variable_1)
summary(modelohot_ajustado)##
## Call:
## lm(formula = preciom ~ areaconst + habitaciones + parqueaderos +
## banios + estrato.4 + estrato.5 + estrato.6, data = variable_1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -905.96 -73.54 -14.87 46.56 1081.06
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 17.66574 17.73965 0.996 0.319668
## areaconst 0.78765 0.04365 18.043 < 2e-16 ***
## habitaciones 1.27377 4.06436 0.313 0.754069
## parqueaderos 20.92767 5.41954 3.862 0.000123 ***
## banios 22.60229 5.35561 4.220 2.75e-05 ***
## estrato.4 80.71030 17.16526 4.702 3.09e-06 ***
## estrato.5 131.23732 16.12267 8.140 1.76e-15 ***
## estrato.6 321.66433 26.30550 12.228 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 155.4 on 714 degrees of freedom
## Multiple R-squared: 0.6681, Adjusted R-squared: 0.6648
## F-statistic: 205.3 on 7 and 714 DF, p-value: < 2.2e-16
El modelo muestra que eliminar estrato.3 como referencia mejora la interpretación de los coeficientes. Ahora, los coeficientes de los estratos reflejan cuánto más costoso es un estrato en comparación con el estrato 3, lo que tiene más sentido lógico. Además, el R² del modelo sigue siendo 66.8%, indicando que el modelo sigue explicando una cantidad significativa de la variabilidad en los precios de la vivienda sin perder capacidad predictiva.
Para validar supuestos de un modelo lineal:
##
## Anderson-Darling normality test
##
## data: modelohot_ajustado$residuals
## A = 26.859, p-value < 2.2e-16
##
## Shapiro-Wilk normality test
##
## data: resid(modelohot_ajustado)
## W = 0.83131, p-value < 2.2e-16
##
## studentized Breusch-Pagan test
##
## data: modelohot_ajustado
## BP = 131.38, df = 7, p-value < 2.2e-16
##
## Goldfeld-Quandt test
##
## data: modelohot_ajustado
## GQ = 1.1729, df1 = 353, df2 = 353, p-value = 0.0673
## alternative hypothesis: variance increases from segment 1 to 2
##
## Durbin-Watson test
##
## data: modelohot_ajustado
## DW = 1.7117, p-value = 3.966e-05
## alternative hypothesis: true autocorrelation is greater than 0
Estamos buscando una casa en la zona norte, con un area de 200mt2 que tenga 1 parqueadero, 2 baños y 4 habitaciones ademas de que este en un estrato de 4 y 5.
library(fastDummies)
solicitudhot = data.frame(
areaconst = 200,
parqueaderos = 1,
estrato = c(4, 5),
banios = 2,
habitaciones = 4
)
solicitudhot = dummy_cols(solicitudhot, select_columns = "estrato",
remove_first_dummy = FALSE,
remove_selected_columns = FALSE)
print(solicitudhot)## areaconst parqueaderos estrato banios habitaciones estrato_4 estrato_5
## 1 200 1 4 2 4 1 0
## 2 200 1 5 2 4 0 1
colnames(solicitudhot) = sub("estrato_", "estrato.", colnames(solicitudhot))
dummies_necesarias = c("estrato.3", "estrato.4", "estrato.5", "estrato.6")
for (col in dummies_necesarias) {
if (!col %in% colnames(solicitudhot)) {
solicitudhot[[col]] = 0
}
}
solicitudhot = solicitudhot[, c("areaconst", "parqueaderos", "banios", "habitaciones",
"estrato.3", "estrato.4", "estrato.5", "estrato.6")]
predicciones = predict(modelohot_ajustado, solicitudhot) #Predicciones
print(predicciones)## 1 2
## 327.1338 377.6608
Bajo los anteriores resultados la casa 1 con las mismas caracteristicas a expceion del estrato, se encutra que la primera tiene un valor de 327 millones y la segunda de 377 millones.
## # 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>
##
## Apartamento
## Zona Sur 2787
Observamos cuantos elementos tenemos para nuestro tipo de vivienda y su zona geografica respectiva. Por lo anterior, se tiene que existen 28787 departamentos en la zona sur
Mapa 1. Departamentos zona sur
mapa_sur = leaflet(data = variable_2) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitud, lat = ~latitud,
radius = 2,
color = "blue",
fillOpacity = 0.7,
stroke = FALSE)
mapa_surEn relación al mapa anterior, se evidencia que los elementos que hacen referencia a los departamentos de la zona sur, no estan del todo ubicados en esta zona. Si bien existe una concentración en la zona ya mencionada - en contraste existen algunas cosas que se ubican en el centro y norte de la ciudad.
## id zona piso estrato preciom areaconst
## 0 0 622 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 406 0 0 0 0 0
## latitud
## 0
imputacion_piso2 = variable_2[, c("piso", "areaconst")]
variable_1_imputado2 = kNN(imputacion_piso2,
variable = "piso",
k = 5,
imp_var = FALSE)
variable_2$piso = variable_1_imputado2$piso
cat("Valores NA restantes en 'piso':", sum(is.na(variable_2$piso)), "\n") ## Valores NA restantes en 'piso': 0
##
## 1 2 3 4 7
## 135 494 86 6 1
El proceso de imputación fue el correcto en cuanto tenemos cero valores faltantes.
ggplot(variable_2, aes(x = factor(piso))) +
geom_bar(fill = "blue", color = "black") +
labs(title = "Distribucion de Pisos Tras la Imputacion KNN",
x = "Piso",
y = "Frecuencia") +
theme_minimal()Del anterior grafico podemos afirmar que la mayor cantidad de viviendas se encuentran en departamentos de 1 a 5 pisos.
ggplot(variable_2, aes(x = areaconst, y = factor(piso), color = factor(piso))) +
geom_jitter(alpha = 0.7, size = 2) +
labs(title = "Relacion entre Area Construida y Piso Imputado",
x = "Area Construida",
y = "Piso") +
theme_minimal()## id zona piso estrato preciom areaconst
## 0 0 0 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 406 0 0 0 0 0
## latitud
## 0
imputacion_parqueadero2 = variable_2[, c("parqueaderos", "areaconst")]
variable_2_imputado2 = kNN(imputacion_parqueadero2,
variable = "parqueaderos",
k = 5,
imp_var = FALSE)
variable_2$parqueaderos = variable_2_imputado2$parqueaderos
cat("Valores NA restantes en 'parqueaderos':", sum(is.na(variable_2$parqueaderos)), "\n")## Valores NA restantes en 'parqueaderos': 0
##
## 1 2 3 4 10
## 1930 741 83 31 2
El proceso de imputación fue el correcto en cuanto tenemos cero valores faltantes.
grafica_area_precio2 = plot_ly(data = variable_2, x = ~areaconst, y = ~preciom, color = ~zona,
type = "scatter", mode = "markers", marker = list(size = 10),
text = ~paste("Zona:", zona, "<br>Precio:", preciom, "<br>Area Construida:", areaconst)) %>%
layout(title = "Correlación entre Precio y Área Construida",
xaxis = list(title = "Area Construida"),
yaxis = list(title = "Precio"))
grafica_area_precio2## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
Zona_apartamento = subset(variable_1, tipo == "Casa")
variables_interes = Zona_apartamento[, c("preciom", "areaconst", "estrato", "banios", "habitaciones", "parqueaderos")]
correlation_matrix = cor(variables_interes)
corrplot(correlation_matrix, method = "number", addCoef.col = "red", number.cex = 0.7)areaconst y estrato.
Finalmente, el número de habitaciones presenta una correlación más baja
con el precio (0.32), lo que indica que su efecto sobre
el valor de la vivienda es menos significativo en comparación con las
demás variables.
library(fastDummies)
variable_2 = dummy_cols(variable_2,
select_columns = "estrato",
remove_first_dummy = FALSE,
remove_selected_columns = FALSE)
colnames(variable_2) = sub("^estrato_", "estrato.", colnames(variable_2))
head(variable_2)## # A tibble: 6 × 17
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 5098 Zona S… 5 4 290 96 1 2 3
## 2 698 Zona S… 2 3 78 40 1 1 2
## 3 8199 Zona S… 4 6 875 194 2 5 3
## 4 1241 Zona S… 3 3 135 117 2 2 3
## 5 5370 Zona S… 4 3 135 78 1 1 3
## 6 6975 Zona S… 6 4 220 75 1 2 3
## # ℹ 8 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## # estrato.3 <int>, estrato.4 <int>, estrato.5 <int>, estrato.6 <int>
modelohot2 = lm(preciom ~ areaconst + habitaciones + parqueaderos + banios
+ estrato.4 + estrato.5 + estrato.6,
data = variable_2)
summary(modelohot2)##
## Call:
## lm(formula = preciom ~ areaconst + habitaciones + parqueaderos +
## banios + estrato.4 + estrato.5 + estrato.6, data = variable_2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1068.53 -35.30 -1.53 35.24 899.89
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -42.75112 10.13781 -4.217 2.55e-05 ***
## areaconst 1.29897 0.04646 27.962 < 2e-16 ***
## habitaciones -12.13429 3.16646 -3.832 0.00013 ***
## parqueaderos 61.71619 3.54214 17.423 < 2e-16 ***
## banios 39.39832 2.84552 13.846 < 2e-16 ***
## estrato.4 29.46584 6.86920 4.290 1.85e-05 ***
## estrato.5 56.13105 7.09131 7.915 3.53e-15 ***
## estrato.6 209.82000 8.89017 23.601 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 87.67 on 2779 degrees of freedom
## Multiple R-squared: 0.7911, Adjusted R-squared: 0.7905
## F-statistic: 1503 on 7 and 2779 DF, p-value: < 2.2e-16
El modelo es altamente explicativo
(R² = 79.11%), lo que indica que el 79.1% de la
variabilidad en el precio se explica por las variables
incluidas.
Todos los coeficientes son estadísticamente
significativos (p < 0.05), lo que confirma que
cada variable tiene un impacto real en el precio de la
vivienda.
El área construida y los parqueaderos son de los factores más determinantes, mientras que las habitaciones tienen un efecto negativo inesperado. Este resultado sugiere que, en el contexto del mercado analizado, el número de habitaciones no es un factor clave en la determinación del precio y que otros atributos, como la distribución del espacio o la calidad de la construcción, podrían ser más relevantes.
Los estratos más altos aumentan significativamente el precio, lo cual es lógico, ya que las viviendas en estratos más altos tienden a estar ubicadas en zonas con mejor infraestructura y mayor demanda.
##
## Anderson-Darling normality test
##
## data: modelohot2$residuals
## A = 92.193, p-value < 2.2e-16
##
## Shapiro-Wilk normality test
##
## data: resid(modelohot2)
## W = 0.77557, p-value < 2.2e-16
##
## studentized Breusch-Pagan test
##
## data: modelohot2
## BP = 795.02, df = 7, p-value < 2.2e-16
##
## Goldfeld-Quandt test
##
## data: modelohot2
## GQ = 0.9008, df1 = 1386, df2 = 1385, p-value = 0.974
## alternative hypothesis: variance increases from segment 1 to 2
Los resultados del análisis de supuestos muestran que el modelo presenta problemas de normalidad, heterocedasticidad y autocorrelación en los residuos. Las pruebas de Anderson-Darling y Shapiro-Wilk indican que los residuos no siguen una distribución normal, lo que podría afectar la validez de los intervalos de confianza y pruebas de hipótesis. Además, la prueba de Breusch-Pagan sugiere la presencia de heterocedasticidad, lo que indica que la varianza de los errores no es constante. Sin embargo, la prueba de Goldfeld-Quandt no confirma este resultado con certeza. Por otro lado, la prueba de Durbin-Watson evidencia autocorrelación positiva en los residuos, lo que sugiere una posible dependencia en los datos. Dado que estos problemas pueden afectar la validez y eficiencia de los estimadores, se recomienda considerar transformaciones en la variable dependiente (logaritmo o Box-Cox) para mejorar la normalidad, así como el uso de errores estándar robustos para corregir la heterocedasticidad y posibles métodos que mitiguen la autocorrelación en los residuos, como modelos autorregresivos o errores estándar corregidos por autocorrelación.
Estamos buscando un Apartamento en la zona sur, con un area de 300mt2 que tenga 3 parqueadero, 3 baños y 5 habitaciones ademas de que este en un estrato de 5 y 6.
library(fastDummies)
solicitudhot2 = data.frame(
areaconst = 300,
parqueaderos = 3,
estrato = c(5, 6),
banios = 3,
habitaciones = 5
)
solicitudhot2 = dummy_cols(solicitudhot2, select_columns = "estrato",
remove_first_dummy = FALSE,
remove_selected_columns = FALSE)
print(solicitudhot2)## areaconst parqueaderos estrato banios habitaciones estrato_5 estrato_6
## 1 300 3 5 3 5 1 0
## 2 300 3 6 3 5 0 1
colnames(solicitudhot2) = sub("estrato_", "estrato.", colnames(solicitudhot2))
dummies_necesarias2 = c("estrato.3", "estrato.4", "estrato.5", "estrato.6")
for (col in dummies_necesarias) {
if (!col %in% colnames(solicitudhot2)) {
solicitudhot2[[col]] = 0
}
}
solicitudhot2 = solicitudhot2[, c("areaconst", "parqueaderos", "banios", "habitaciones",
"estrato.3", "estrato.4", "estrato.5", "estrato.6")]
predicciones2 = predict(modelohot2, solicitudhot2)
print(predicciones2)## 1 2
## 645.7426 799.4315
Bajo los anteriores resultados el departamento 1 con las mismas caracteristicas a exepcion del estrato, se encuentra que la primera tiene un valor de 645 millones y la segunda de 799 millones.
El objetivo de estas conclusiones es relatar el proceso metodológico empleado en el análisis de la información. En primer lugar, se realizó un análisis exploratorio de la base de datos vivienda. A partir de este análisis, se creó una nueva variable denominada variable_1, con el propósito de delimitar las casas ubicadas en la zona norte de la ciudad. Como resultado, se identificaron 722 casas en dicha zona. Sin embargo, se evidenció que algunos registros clasificados como parte de la zona norte estaban en realidad ubicados en otras zonas, como el centro y el sur de la ciudad. A pesar de que la mayor concentración de viviendas sí correspondía a la zona norte, esta discrepancia resaltó la necesidad de una revisión más detallada de la variable de ubicación.
Posteriormente, en el proceso de limpieza de datos, se detectaron valores faltantes en variables como piso y parqueaderos. Además, se identificó que la variable piso contenía números almacenados en formato de texto, lo que requirió su transformación a valores numéricos. Para la imputación de los valores faltantes, inicialmente se consideró la metodología clásica basada en la evaluación de normalidad, utilizando la media o mediana según los resultados. No obstante, se optó por aplicar la técnica de imputación KNN, utilizando la relación entre piso y área construida. Esta metodología ofreció resultados coherentes, por lo que se replicó para imputar los valores faltantes en la variable parqueadero.
Una vez finalizado el proceso de imputación, se analizaron las correlaciones entre las variables. Se observó una fuerte correlación positiva (0.73) entre el precio de la vivienda (preciom) y el área construida (areaconst), indicando que, a mayor área, mayor es el precio de la vivienda.
Posteriormente, se llevó a cabo la regresión lineal múltiple. En una primera instancia, se omitió la variable estrato, dado su carácter ordinal. Sin embargo, al incluirla en el modelo sin ningún tipo de tratamiento, se obtuvieron estimaciones para una vivienda con 200 m² de área construida, 1 parqueadero, 2 baños y 4 habitaciones, ubicada en los estratos 4 y 5, con precios de 321 millones y 403 millones de pesos, respectivamente.
Para mejorar la interpretación del modelo, la variable estrato se transformó mediante el enfoque de one-hot encoding, convirtiéndola en variables dummy. No obstante, los resultados indicaban la presencia de colinealidad, lo que podía distorsionar la interpretación de los coeficientes. En particular, el coeficiente de los estratos era negativo, lo que contradecía la intuición económica, ya que se espera que el precio aumente con el estrato. Identificando el problema, se realizó un ajuste en la referencia del estrato, eliminando el estrato 3 como categoría base. Con este ajuste, los coeficientes pasaron a reflejar de manera más lógica el aumento del precio con respecto al estrato 3.
El modelo ajustado presentó un R² de 66.8%, indicando que sigue explicando una cantidad significativa de la variabilidad en los precios de las viviendas sin pérdida de capacidad predictiva. Además, ninguna variable presentó problemas de multicolinealidad. No obstante, se identificaron ciertas deficiencias en los supuestos del modelo, tales como:
A pesar de estos problemas, el modelo permitió obtener estimaciones coherentes y útiles para la toma de decisiones.
Para una vivienda con 200 m² de área construida, 1 parqueadero, 2 baños y 4 habitaciones, ubicada en estratos 4 y 5, se estimaron los siguientes valores:
Para un apartamento en la Zona Sur de Cali con 300 m² de área construida, 3 parqueaderos, 3 baños y 5 habitaciones, se obtuvieron los siguientes valores estimados:
Estos resultados confirman que el estrato es una variable clave en la determinación del precio de las viviendas, ya que, a igualdad de condiciones estructurales, los precios varían significativamente entre los distintos estratos socioeconómicos.