Maria comenzó como agente de bienes raíces en Cali hace 10 años. Después de laborar dos años para una empresa nacional, se traslado a Bogotá y trabajó para otra agencia de bienes raíces. Sus amigos y familiares la convencieron de que con su experiencia y conocimientos del negocio debía abrir su propia agencia. Terminó por adquirir la licencia de intermediario y al poco tiempo fundó su propia compañía, C&A (Casas y Apartamentos) en Cali. Santiago y Lina, dos vendedores de la empresa anterior aceptaron trabajar en la nueva compaña. En la actualidad ocho agentes de bienes raíces colaboran con ella en C&A.
Actualmente las ventas de bienes raíces en Cali se han visto disminuidas de manera significativa en lo corrido del año. Durante este periodo muchas instituciones bancarias de ahorro y vivienda están prestando grandes sumas de dinero para la industria y la construcción comercial y residencial. Cuando el efecto producto de las tensiones políticas y sociales disminuya, se espera que la actividad económica de este sector se reactive.
Hace dos días, María recibió una carta solicitando asesoría para la compra de dos viviendas por parte de una compañía internacional que desea ubicar a dos de sus empleados con sus familias en la ciudad. Las solicitudes incluyen las siguientes condiciones:
| Características | Vivienda 1 | Vivienda 2 |
|---|---|---|
| Tipo | Casa | Apartamento |
| área construida | 200 | 300 |
| parqueaderos | 1 | 3 |
| baños | 2 | 3 |
| habitaciones | 4 | 5 |
| estrato | 4 o 5 | 5 o 6 |
| zona | Norte | Sur |
| crédito preaprobado | 350 millones | 850 millones |
Ayude a María a responder la solicitud, mediante técnicas modelación que usted conoce. Ella requiere le envíe un informe ejecutivo donde analice los dos casos y sus recomendaciones (Informe). Como soporte del informe debe anexar las estimaciones, validaciones y comparación de modelos requeridos (Anexos) .
Los datos de los tres últimos meses se adjuntan en la base que puede obtener con el siguiente código en R
| variable | descripción |
|---|---|
| zona | ubicación de la vivienda : Zona Centro, Zona Norte,… |
| piso | piso que ocupa la vivienda : primer piso, segundo piso… |
| estrato | estrato socio-económico : 3,4,5,6 |
| preciom | precio de la vivienda en millones de pesos |
| areaconst | área construida |
| parqueaderos | número de parqueaderos |
| banios | número de baños |
| habitaciones | número de habitaciones |
| tipo | tipo de vivienda : Casa, Apartamento |
| barrio | barrio de ubicación de la vivienda : 20 de Julio, alamos,.. |
| longitud | coordenada geográfica |
| latitud | coordenada geográfica |
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
#librerías
library(paqueteMODELOS)
library(plotly)
library(dplyr)
library(GGally)
library(lmtest)
library(car)
library(Metrics)
# descargar la data
devtools::install_github("centromagis/paqueteMODELOS", force =TRUE)
## stringi (1.8.3 -> 1.8.4 ) [CRAN]
## rlang (1.1.3 -> 1.1.4 ) [CRAN]
## cli (3.6.2 -> 3.6.3 ) [CRAN]
## Rcpp (1.0.12 -> 1.0.13 ) [CRAN]
## digest (0.6.34 -> 0.6.37 ) [CRAN]
## curl (5.2.0 -> 5.2.2 ) [CRAN]
## fastmap (1.1.1 -> 1.2.0 ) [CRAN]
## backports (1.4.1 -> 1.5.0 ) [CRAN]
## xfun (0.41 -> 0.47 ) [CRAN]
## colorspace (2.1-0 -> 2.1-1 ) [CRAN]
## broom (1.0.5 -> 1.0.6 ) [CRAN]
## matrixStats (1.2.0 -> 1.4.0 ) [CRAN]
## magick (2.8.2 -> 2.8.4 ) [CRAN]
## htmltools (0.5.7 -> 0.5.8.1) [CRAN]
## checkmate (2.3.1 -> 2.3.2 ) [CRAN]
## yaml (2.3.8 -> 2.3.10 ) [CRAN]
## knitr (1.45 -> 1.48 ) [CRAN]
##
## There is a binary version available but the source version is later:
## binary source needs_compilation
## matrixStats 1.3.0 1.4.0 TRUE
##
## Binaries will be installed
## package 'stringi' successfully unpacked and MD5 sums checked
## package 'rlang' successfully unpacked and MD5 sums checked
## package 'cli' successfully unpacked and MD5 sums checked
## package 'Rcpp' successfully unpacked and MD5 sums checked
## package 'digest' successfully unpacked and MD5 sums checked
## package 'curl' successfully unpacked and MD5 sums checked
## package 'fastmap' successfully unpacked and MD5 sums checked
## package 'backports' successfully unpacked and MD5 sums checked
## package 'xfun' successfully unpacked and MD5 sums checked
## package 'colorspace' successfully unpacked and MD5 sums checked
## package 'matrixStats' successfully unpacked and MD5 sums checked
## package 'magick' successfully unpacked and MD5 sums checked
## package 'htmltools' successfully unpacked and MD5 sums checked
## package 'checkmate' successfully unpacked and MD5 sums checked
## package 'yaml' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Usuario\AppData\Local\Temp\RtmpAfi95M\downloaded_packages
## ── R CMD build ─────────────────────────────────────────────────────────────────
## ✔ checking for file 'C:\Users\Usuario\AppData\Local\Temp\RtmpAfi95M\remotes49d829ef134f\Centromagis-paqueteMODELOS-78ce06f/DESCRIPTION' (406ms)
## ─ preparing 'paqueteMODELOS': (3.3s)
## checking DESCRIPTION meta-information ... ✔ checking DESCRIPTION meta-information
## ─ checking for LF line-endings in source and make files and shell scripts
## ─ checking for empty or unneeded directories
## ─ building 'paqueteMODELOS_0.1.0.tar.gz'
##
##
data(vivienda)
vivienda_df <- vivienda
Verificar valores únicos
# Verificar valores faltantes en las variables del conjunto de prueba
sapply(vivienda_df, function(x) sum(is.na(x)))
## 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
# Opcional: Filtrar filas que contengan NA en las variables predictoras
vivienda_df <- na.omit(vivienda_df)
# Verificar valores faltantes en las variables del conjunto de prueba
sapply(vivienda_df, function(x) sum(is.na(x)))
## id zona piso estrato preciom areaconst
## 0 0 0 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 0 0 0 0 0 0
## latitud
## 0
# Verificar valores únicos en la columna tipo
unique(vivienda_df$tipo)
## [1] "Casa" "Apartamento"
# Filtrar la base de datos para incluir solo casas en la zona norte
vivienda_filtrada <- vivienda_df %>%
filter(tipo == "Apartamento")
# Mostrar los primeros 3 registros
head(vivienda_filtrada, 3)
## # A tibble: 3 × 13
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1212 Zona N… 01 5 260 90 1 2 3
## 2 1724 Zona N… 01 5 240 87 1 3 3
## 3 2326 Zona N… 01 4 220 52 2 2 3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
# Tabla de frecuencias del tipo de vivienda
table(vivienda_filtrada$tipo)
##
## Apartamento
## 3182
# Crear un mapa con las ubicaciones de los apartamentos
grafica <- plot_ly(data = vivienda_filtrada, lat = ~latitud, lon = ~longitud, type = 'scattermapbox', mode = 'markers',
marker = list(size = 10, color = 'red'))
grafica <- grafica %>% layout(
mapbox = list(
style = "open-street-map",
zoom = 10,
center = list(lat = mean(vivienda_filtrada), lon = mean(vivienda_filtrada$longitud))
),
title = "Ubicación de apartamentos"
)
grafica
# Resumen estadístico de algunas variables de interés
resumen_precio <- summary(vivienda_filtrada$preciom)
print(resumen_precio)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 58 220 300 390 450 1900
resumen_habitaciones <- summary(vivienda_filtrada$habitaciones)
print(resumen_habitaciones)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 3.000 3.000 3.023 3.000 7.000
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.
# Seleccionar las variables de interés
vivienda_seleccion <- vivienda_filtrada %>%
select(preciom, areaconst, estrato, banios, habitaciones, zona)
Gráfico de dispersión Precio y Área Construida:
El gráfico de dispersión muestra cómo se relacionan el precio y el área construida del apartamernto.
Esperamos ver una correlación positiva, donde los precios aumentan a medida que aumenta el área construida.
# 1. Gráfico de dispersión: Precio vs Área construida
grafico_area_precio <- plot_ly(vivienda_seleccion, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers',
marker = list(size = 8, color = 'blue', opacity = 0.5)) %>%
layout(title = 'Relación entre Precio y Área Construida',
xaxis = list(title = 'Área Construida (m²)'),
yaxis = list(title = 'Precio (COP)'))
grafico_area_precio
En el gráfico de dispersión que representa la relación entre el precio y el área construida de los apartamentos se observa una tendencia ascendente en este gráfico que indica que a medida que aumenta el tamaño del apartamento, también lo hace el precio. Los valores atípicos que se visualizan pueden correspoder a propiedades de lujo con características especiales o, por el contrario, propiedades que están sobrevaloradas o subvaloradas según su tamaño
Gráfico de cajas y bigotes del precio por cada estrato:
# 2. Gráfico de cajas: Precio vs Estrato
grafico_estrato_precio <- plot_ly(vivienda_seleccion, x = ~factor(estrato), y = ~preciom, type = 'box',
marker = list(color = 'red')) %>%
layout(title = 'Distribución del precio por estrato',
xaxis = list(title = 'Estrato'),
yaxis = list(title = 'Precio (COP)'))
grafico_estrato_precio
El gráfico de cajas muestra que los estratos más altos presentan precios de vivienda más elevados lo que se puede visualizar por tener cajas más altas en el gráfico. La mediana indica el precio típico de un apartamento en cada estrato por ejemplo para el estrato 3 el valor típico es 130 millones mientras en el estrato 6 es de 600 millones. La anchura de la caja del estrato 6 por ejemplo representa la variabilidad de los precios pueden tener una mezcla de viviendas de diferentes tamaños y caracteristicas que se traduce en una dispersión mayor de los precios. Los valores atípicos altos que se presentan en cada estrato pueden corrresponder corresponder a propiedades de lujo que, a pesar de estar en un estrato medio, son excepcionales por su tamaño, diseño, o características únicas.
Gráfico de cajas y bigotes del precio por el número de baños:
# 3. Gráfico de cajas: Precio vs Número de Baños
grafico_banos_precio <- plot_ly(vivienda_seleccion, x = ~factor(banios), y = ~preciom, type = 'box',
marker = list(color = 'green')) %>%
layout(title = 'Distribución del precio por número de baños',
xaxis = list(title = 'Número de Baños'),
yaxis = list(title = 'Precio (COP)'))
grafico_banos_precio
El gráfico de cajas que representa la distribución del precio por número de baños permite visualizar cómo el precio de los apartamentos varía en función de la cantidad de baños, es decir que los apartamentos con más baños tienden a tener precios más altos. Más baños suelen estar asociados con propiedades más grandes o de mayor lujo, lo que incrementa su valor.
Gráfica de cajas y bigotes del precio por número de habitaciones:
# 4. Gráfico de cajas: Precio vs Número de Habitaciones
grafico_habitaciones_precio <- plot_ly(vivienda_seleccion, x = ~factor(habitaciones), y = ~preciom, type = 'box',
marker = list(color = 'orange')) %>%
layout(title = 'Distribución del precio por número de habitaciones',
xaxis = list(title = 'Número de Habitaciones'),
yaxis = list(title = 'Precio (COP)'))
grafico_habitaciones_precio
El gráfico de cajas ofrece una visión clara de cómo el precio de los apartamentos varía según la cantidad de habitaciones que tienen. Esto se debe a que más habitaciones suelen implicar una mayor área construida, más comodidades, y por lo tanto, un mayor valor en el mercado.
Gráfico de cajas y bigotes del precio por zona:
# 5. Gráfico de cajas: Precio vs Zona
grafico_zona_precio <- plot_ly(vivienda_seleccion, x = ~zona, y = ~preciom, type = 'box',
marker = list(color = 'purple')) %>%
layout(title = 'Distribución del Precio por Zona',
xaxis = list(title = 'Zona'),
yaxis = list(title = 'Precio (COP)'))
grafico_zona_precio
# Calcular la matriz de correlación para las variables seleccionadas
variables_de_interes <- c('preciom', 'areaconst', 'estrato', 'banios', 'habitaciones')
correlaciones <- cor(vivienda_filtrada[, variables_de_interes], use = "complete.obs")
# Visualizar la matriz de correlación utilizando un heatmap interactivo
plot_ly(
z = correlaciones,
x = colnames(correlaciones),
y = colnames(correlaciones),
type = "heatmap",
colorscale = "Viridis" # Opción para una escala de color más atractiva
) %>%
layout(
title = "Matriz de Correlación entre Variables",
xaxis = list(title = "Variables"),
yaxis = list(title = "Variables")
)
La matriz de correlación visualizada nos permite entender cómo se relacionan las distintas variables entre sí. El gráfico utiliza una escala de colores que va del magenta (baja correlación) al amarillo (alta correlació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).
# Verificar las variables disponibles
colnames(vivienda_filtrada)
## [1] "id" "zona" "piso" "estrato" "preciom"
## [6] "areaconst" "parqueaderos" "banios" "habitaciones" "tipo"
## [11] "barrio" "longitud" "latitud"
# Seleccionar las variables de interés
modelo_data <- vivienda_filtrada[, c("preciom", "estrato", "habitaciones", "parqueaderos", "banios", "areaconst")]
# Estimación del modelo
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = modelo_data)
# Resumen del modelo
summary(modelo)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = modelo_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1609.23 -55.44 -0.01 47.99 963.98
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -285.9869 17.5604 -16.29 <2e-16 ***
## areaconst 1.9061 0.0549 34.72 <2e-16 ***
## estrato 52.5560 3.4642 15.17 <2e-16 ***
## habitaciones -35.3350 4.2623 -8.29 <2e-16 ***
## parqueaderos 100.3163 4.9734 20.17 <2e-16 ***
## banios 53.5608 3.8771 13.81 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 133.5 on 3176 degrees of freedom
## Multiple R-squared: 0.7823, Adjusted R-squared: 0.7819
## F-statistic: 2282 on 5 and 3176 DF, p-value: < 2.2e-16
El valor del intercepto es -285.98 es el valor estimado del precio cuando las demas variables son cero, esto práctica esto no tiene sentido.
EL valor 1.9 en areasconst indica que por cada metro cuadrado adicional en el área construida, se espera que el precio de la vivienda aumente en promedio en 1.9 millones, manteniendo constantes las demás variables y va en línea que a mayor área construida incrementa el precio de la vivienda.
El valor 52.55 en estrato indica que por cada aumento en un nivel del estrato, se espera que el precio de la vivienda aumente en promedio en 52.55 millones, manteniendo constantes las demás variables.
EL valor negativo -35.33 de habitaciones sugiere una disminución en el precio de la vivienda a medida que aumenta el número de habitaciones, teniendo en cuenta esto es necesario validar porque podría indicar que el número de habitaciones no necesariamente incrementa el valor de la vivienda, o que hay una relación no lineal o interacción con otras variables no modeladas. Sería importante validar si exite una multicolinealidad entre el númeor de habitaciones y otras variables como el areaconst y se esté compensando la variablidad. Otro aspecto que puede estar pasando es que la realción entre el precio del apartamento y numero de habitaciones no sea lineal por ejemplo incrememntar habitaciones en un apartamento grande puede que no icremente el precio como en un apartamento pequeño.
Respecto a parqueaderos y baños se peude decir que los valores son lógicos teneindo en cuenta que los parqueaderos son una caraterística valiosa y los baños aportan comodidad y valor a los apartamentos
Los coeficientes tienen p-valores < 0.001,lo que indica que estas variables tienen un impacto en el precio de la vivienda.
El R-squared de 0.7823 indica que el 78.23% de la variabilidad en el precio de la vivienda es explicada por las variables incluidas en el modelo. Esto sugiere que el modelo tiene un buen ajuste.
El R-squared ajustado de 0.7819 un poco menor pero sugiere que la inclusión de más variables no está sobre ajustando el modelo.
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)
La homocedasticidad implica que la variabilidad de los residuos es constante a lo largo de los valores ajustados.
bptest(modelo)
##
## studentized Breusch-Pagan test
##
## data: modelo
## BP = 1066.8, df = 5, p-value < 2.2e-16
Interpretación: Un p-valor extremadamente bajo
indica que existe heterocedasticidad. Una posible solución sería aplicar
transformaciones a la variable dependiente, como tomar el logaritmo de
preciom.
shapiro.test(modelo$residuals)
##
## Shapiro-Wilk normality test
##
## data: modelo$residuals
## W = 0.82899, p-value < 2.2e-16
El p-value < 2.2e-16 rechaza la hipótesis nula de normalidad de los residuos, lo que quiere decir que, los residuos no siguen una distribución normal
# Test de Durbin-Watson
library(lmtest)
dwtest(modelo)
##
## Durbin-Watson test
##
## data: modelo
## DW = 1.5868, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0
Interpretación: El p-valor es menor que 0.05, lo que indica que hay evidencia significativa para rechazar la hipótesis nula de no autocorrelación en los residuos. Por consiguiente en el modelo existe autocorrelación positiva en los residuos. Para abordar este problema de autocorrelación en los residuos se podría agregar nuevas variables al modelo o se podría transformar variables que ya están en el modelo..
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
# Establecer la semilla para reproducibilidad
set.seed(123)
# Partición del 70% de los datos para entrenamiento y 30% para prueba
sample_size <- floor(0.7 * nrow(vivienda_filtrada))
# Crear índices aleatorios
train_indices <- sample(seq_len(nrow(vivienda_filtrada)), size = sample_size)
# Crear el set de entrenamiento y prueba
train_data <- vivienda_filtrada[train_indices, ]
test_data <- vivienda_filtrada[-train_indices, ]
# Estimar el modelo con los datos de entrenamiento
# Estimación del modelo
modelo_entrenamiento <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = train_data)
# Mostrar los resultados del modelo
summary(modelo_entrenamiento)
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = train_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1206.30 -52.70 0.72 47.73 949.70
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -275.85441 20.87286 -13.216 < 2e-16 ***
## areaconst 2.11600 0.06812 31.062 < 2e-16 ***
## estrato 49.66599 4.08581 12.156 < 2e-16 ***
## habitaciones -35.53463 5.10337 -6.963 4.37e-12 ***
## parqueaderos 93.05787 5.98705 15.543 < 2e-16 ***
## banios 50.82708 4.64058 10.953 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 132.5 on 2221 degrees of freedom
## Multiple R-squared: 0.791, Adjusted R-squared: 0.7905
## F-statistic: 1681 on 5 and 2221 DF, p-value: < 2.2e-16
Este modelo tiene un buen ajuste, pero los coeficientes como el de las habitaciones sugieren que hay factores no modelados que podrían influir en los resultados.
Realice predicciones con el modelo anterior usando los datos de prueba (30%)
# Realizar predicciones sobre el set de prueba utilizando el modelo entrenado
predicciones <- predict(modelo_entrenamiento, newdata = test_data)
# Mostrar las primeras 6 predicciones junto con los valores reales
resultados <- data.frame(Valor_Real = test_data$preciom, Prediccion = predicciones)
head(resultados)
## Valor_Real Prediccion
## 1 220 214.00766
## 2 320 383.33087
## 3 420 559.91076
## 4 170 163.78733
## 5 78 30.59933
## 6 1130 899.51209
Calcule el error cuadrático medio, el error absoluto medio y el R2, interprete
# Calcular el Error Cuadrático Medio (MSE)
mse <- mse(test_data$preciom, predicciones)
# Calcular el Error Absoluto Medio (MAE)
mae <- mae(test_data$preciom, predicciones)
# Calcular el R²
r2 <- 1 - sum((test_data$preciom - predicciones)^2) / sum((test_data$preciom - mean(test_data$preciom))^2)
# Mostrar los resultados
cat("Error Cuadrático Medio (MSE):", mse, "\n")
## Error Cuadrático Medio (MSE): 18724.53
cat("Error Absoluto Medio (MAE):", mae, "\n")
## Error Absoluto Medio (MAE): 81.80488
cat("R² en el conjunto de prueba:", r2, "\n")
## R² en el conjunto de prueba: 0.7561123
El modelo tiene un buen desempeño, con un alto valor de R2, lo que indica que la mayoría de las variaciones en los precios de las viviendas están explicadas por las variables incluidas en el modelo. Sin embargo, el MSE y el MAE muestran que aún hay errores en las predicciones, lo cual podría mejorarse con variables adicionales o ajustes en el modelo.