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:
# Cargue de librerias
library(dlookr); library(paqueteMODELOS); library(leaflet); library(VIM)
library(dplyr); library(ggplot2); library(gridExtra); library(dplyr)
library(plotly); library(broom); library(tidyr)
# Cargue de los datos
data("vivienda"); data <- vivienda; head(vivienda)
## # A tibble: 6 × 13
## id zona piso estrato preciom areaconst parqueaderos banios habitaciones
## <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1147 Zona O… <NA> 3 250 70 1 3 6
## 2 1169 Zona O… <NA> 3 320 120 1 2 3
## 3 1350 Zona O… <NA> 3 350 220 2 2 4
## 4 5992 Zona S… 02 4 400 280 3 5 3
## 5 1212 Zona N… 01 5 260 90 1 2 3
## 6 1724 Zona N… 01 5 240 87 1 3 3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
Para facilitar una visualización más clara de la base de datos, se filtra y se proyecta en el mapa para confirmar que la selección de Casas en la Zona Norte sea la correcta.
# 1.1 Filtro a la base de datos, Seleccion de Zona Norte y Tipo: Casa
data_casas <- subset(data, zona == "Zona Norte" & tipo == "Casa") # Filtro por filas
leaflet(data_casas %>% filter(!is.na(latitud), !is.na(longitud))) %>%
addTiles() %>% addCircleMarkers(~longitud, ~latitud, color = "blue", radius = 5) %>%
setView(lng = mean(data_casas$longitud, na.rm = TRUE), lat = mean(data_casas$latitud, na.rm = TRUE), zoom = 12) %>%
addControl("<h3>Viviendas Zona Norte - BD Sin Depurar</h3>", position = "topleft")
Se observa que hay numerosos puntos que no corresponden con la ubicación de Casas en la Zona Norte de Cali. Para depurar los datos y realizar un análisis más preciso, se aplicó un filtro de valores atípicos utilizando los cuartiles, con el objetivo de reducir el margen de error en la ubicación.
# Eliminación de columnas innecesarias para el análisis
data_casas <- data_casas %>% select(preciom, areaconst, estrato, habitaciones, parqueaderos, banios, longitud, latitud)
# Convertir la variable 'estrato' en categórica
data_casas$estrato <- as.factor(data_casas$estrato); str(data_casas$estrato)
## Factor w/ 4 levels "3","4","5","6": 3 3 4 2 3 2 3 3 1 1 ...
# Tratamiento de valores nulos
data_casas <- data_casas[data_casas$habitaciones != 0 & data_casas$banios != 0, ]
Se llevó a cabo un análisis en el que se determinó que las viviendas sin baños ni habitaciones podrían clasificarse como lotes o parqueaderos. Por esta razón, se excluyeron estos datos del análisis.
# Tratamiento de outliers de las variables longitud y latitud
###################################################################
# Inicializar variables
threshold <- 0.01; max_iter <- 10; data_original <- data_casas
percent_outliers <- numeric(max_iter); iterations <- numeric(max_iter)
# Filtrar y registrar datos
for (iter in 1:max_iter) {
q25_lat <- quantile(data_casas$latitud, 0.25, na.rm = TRUE)
q75_lat <- quantile(data_casas$latitud, 0.75, na.rm = TRUE)
iqr_lat <- IQR(data_casas$latitud, na.rm = TRUE)
q25_lon <- quantile(data_casas$longitud, 0.25, na.rm = TRUE)
q75_lon <- quantile(data_casas$longitud, 0.75, na.rm = TRUE)
iqr_lon <- IQR(data_casas$longitud, na.rm = TRUE)
data_casas <- data_casas %>%
filter(between(latitud, q25_lat - 1.5 * iqr_lat, q75_lat + 1.5 * iqr_lat),
between(longitud, q25_lon - 1.5 * iqr_lon, q75_lon + 1.5 * iqr_lon))
percent_outliers[iter] <- (1 - nrow(data_casas) / nrow(data_original)) * 100
iterations[iter] <- iter
if ((1 - nrow(data_casas) / nrow(data_original)) <= threshold) break
}
# Graficar porcentaje de valores atípicos
ggplot(data.frame(Iteration = iterations[1:iter], PercentOutliers = percent_outliers[1:iter]),
aes(x = Iteration, y = PercentOutliers)) +
geom_line() + geom_point() +
labs(title = "Porcentaje de Valores Atípicos por Iteración", x = "Número de Iteración", y = "Porcentaje de Valores Atípicos (%)") +
theme_minimal()
# Crear el mapa
leaflet(data_casas %>% filter(!is.na(latitud), !is.na(longitud))) %>%
addTiles() %>%
addCircleMarkers(~longitud, ~latitud, color = "blue", radius = 5) %>%
setView(lng = mean(data_casas$longitud, na.rm = TRUE), lat = mean(data_casas$latitud, na.rm = TRUE), zoom = 12) %>%
addControl(paste0("<h3>Casas Zona Norte - Iteración ", iter, "</h3>"), position = "topleft")
Podemos observar que, tras 5 iteraciones, el filtro de datos por cuartiles aplicado a las variables de latitud y longitud se estabilizó. Además, el mapa resultante muestra una visualización más depurada y concentrada en la Zona Norte, lo que permitirá realizar un análisis más preciso del modelo.
# Datos Missing
# Calcular la correlación entre parqueaderos y preciom antes de la imputación
cor_before <- cor(data_casas$parqueaderos, data_casas$preciom, use = "complete.obs")
# Recuento y porcentaje de NA por variable sin imputación
na_summary <- data_casas %>% summarise(across(everything(), ~sum(is.na(.)))) %>%
pivot_longer(cols = everything(), names_to = "variable", values_to = "count_na") %>%
mutate(percent_na = count_na / nrow(data_casas) * 100)
print(na_summary)
## # A tibble: 8 × 3
## variable count_na percent_na
## <chr> <int> <dbl>
## 1 preciom 0 0
## 2 areaconst 0 0
## 3 estrato 0 0
## 4 habitaciones 0 0
## 5 parqueaderos 201 34.0
## 6 banios 0 0
## 7 longitud 0 0
## 8 latitud 0 0
Tenemos 201 datos faltantes en la variable “parqueaderos”, lo que representa el 34% del total. Se decidió realizar una imputación utilizando la técnica de KNN para abordar este problema.
# Imputar con KNN
data_casas_imputado <- kNN(data_casas, variable = "parqueaderos")
# Evaluación del metodo de imputación aplicado
# Comparar distribuciones
data_casas %>% mutate(source = ifelse(is.na(parqueaderos), "Original NA", "Original Not NA")) %>%
bind_rows(data_casas_imputado %>% mutate(source = "Imputado")) %>% ggplot(aes(x = parqueaderos, fill = source)) +
geom_density(alpha = 0.5) + labs(title = "Distribución de 'parqueaderos': Original vs Imputado", x = "Valor de parqueaderos", y = "Densidad") + theme_minimal()
# Recuento y porcentaje de NA por variable con imputación
na_summary <- data_casas_imputado %>% summarise(across(everything(), ~sum(is.na(.)))) %>%
pivot_longer(cols = everything(), names_to = "variable", values_to = "count_na") %>%
mutate(percent_na = count_na / nrow(data_casas) * 100)
print(na_summary)
## # A tibble: 9 × 3
## variable count_na percent_na
## <chr> <int> <dbl>
## 1 preciom 0 0
## 2 areaconst 0 0
## 3 estrato 0 0
## 4 habitaciones 0 0
## 5 parqueaderos 0 0
## 6 banios 0 0
## 7 longitud 0 0
## 8 latitud 0 0
## 9 parqueaderos_imp 0 0
# Calcular la correlación entre parqueaderos y preciom después de la imputación
cor_after <- cor(data_casas_imputado$parqueaderos, data_casas_imputado$preciom, use = "complete.obs")
# Crear un dataframe con las correlaciones antes y después
correlation_comparison <- data.frame(
Metodo = c("Antes de imputación", "Después de imputación"),
Correlacion = c(cor_before, cor_after)
)
# Mostrar el dataframe con las correlaciones
print(correlation_comparison)
## Metodo Correlacion
## 1 Antes de imputación 0.4321497
## 2 Después de imputación 0.4941782
# Definiendo dataset limpio
data_casas_clean <- data_casas_imputado; str(data_casas_clean)
## 'data.frame': 591 obs. of 9 variables:
## $ preciom : num 320 780 230 180 500 520 380 395 460 390 ...
## $ areaconst : num 150 380 160 120 210 455 300 165 319 357 ...
## $ estrato : Factor w/ 4 levels "3","4","5","6": 3 3 1 1 1 3 1 3 3 3 ...
## $ habitaciones : num 6 3 3 3 6 4 8 4 4 6 ...
## $ parqueaderos : num 2 2 1 1 1 2 2 2 2 2 ...
## $ banios : num 4 3 2 3 6 5 5 4 5 3 ...
## $ longitud : num -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ latitud : num 3.48 3.49 3.45 3.47 3.45 ...
## $ parqueaderos_imp: logi FALSE FALSE TRUE TRUE TRUE TRUE ...
## - attr(*, "spec")=List of 3
## ..$ cols :List of 13
## .. ..$ id : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ zona : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ piso : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ estrato : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ preciom : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ areaconst : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ parqueaderos: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ banios : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ habitaciones: list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ tipo : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ barrio : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
## .. ..$ longitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## .. ..$ latitud : list()
## .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
## ..$ default: list()
## .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
## ..$ delim : chr ";"
## ..- attr(*, "class")= chr "col_spec"
## - attr(*, "problems")=<externalptr>
Después de la imputación, no quedan valores faltantes en las variables, lo que confirma la efectividad del método KNN utilizado. Además, la correlación entre “parqueaderos” y “preciom” aumentó de 0.4321 a 0.4942, indicando que la imputación ha fortalecido la relación entre estas variables. Estos cambios mejoran la calidad y precisión del análisis, lo que resulta en un modelo predictivo más robusto.
# 2.1. Análisis de Variables Numéricas
# 2.1.1. Matriz de Correlación
# Seleccionar variables numéricas
datos_numericos <- data_casas %>% select(preciom, areaconst, banios, habitaciones)
# Calcular matriz de correlación
corr_matrix <- cor(datos_numericos, use = "complete.obs")
# Convertir a formato largo
corr_long <- as.data.frame(as.table(corr_matrix))
# Graficar heatmap
plot_ly(corr_long, x = ~Var2, y = ~Var1, z = ~Freq, type = 'heatmap',
colorscale = 'Viridis', text = ~paste0(round(Freq, 2)), texttemplate = '%{text}') %>%
layout(title = 'Matriz de Correlación entre Variables Numéricas',
xaxis = list(title = 'Variables'),
yaxis = list(title = 'Variables'))
Matriz de Correlación: La matriz de correlación entre las variables numéricas muestra relaciones importantes entre ellas:
La variable “areaconst” (Área Construida) tiene una correlación alta (0.74) con el “preciom” (Precio), lo cual es esperado ya que generalmente, el precio de una propiedad aumenta con el tamaño del área construida.
También se observa una correlación moderada entre el número de “banios” (baños) y “habitaciones” con “preciom” (0.57 y 0.43 respectivamente), lo que indica que estos factores también influyen en el valor de la propiedad, aunque en menor medida que el área construida.
# 2.1.2. Gráficos de Dispersión
# Crear gráficos de dispersión
plots_numeric <- list(
plot_ly(data_casas_clean, x = ~areaconst, y = ~preciom, type = 'scatter', mode = 'markers',
name = 'Precio vs Área Construida') %>%
layout(title = 'Precio vs Área Construida',
xaxis = list(title = 'Área Construida'),
yaxis = list(title = 'Precio'),
legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2)), # Leyenda debajo del título
plot_ly(data_casas_clean, x = ~banios, y = ~preciom, type = 'scatter', mode = 'markers',
name = 'Precio vs Número de Baños') %>%
layout(title = 'Precio vs Número de Baños',
xaxis = list(title = 'Número de Baños'),
yaxis = list(title = 'Precio'),
legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2)), # Leyenda debajo del título
plot_ly(data_casas_clean, x = ~habitaciones, y = ~preciom, type = 'scatter', mode = 'markers',
name = 'Precio vs Número de Habitaciones') %>%
layout(title = 'Precio vs Número de Habitaciones',
xaxis = list(title = 'Número de Habitaciones'),
yaxis = list(title = 'Precio'),
legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2)), # Leyenda debajo del título
plot_ly(data_casas_clean, x = ~parqueaderos, y = ~preciom, type = 'scatter', mode = 'markers',
name = 'Precio vs Número de Parqueaderos') %>%
layout(title = 'Precio vs Número de Parqueaderos',
xaxis = list(title = 'Número de Parqueaderos'),
yaxis = list(title = 'Precio'),
legend = list(orientation = 'h', x = 0.5, xanchor = 'center', y = -0.2)) # Leyenda debajo del título
)
# Mostrar gráficos en un layout de 2x2
subplot(plots_numeric, nrows = 2, margin = 0.05) %>%
layout(title = 'Diagramas de Dispersión de Variables Numéricas',
showlegend = TRUE) # Asegúrate de que la leyenda se muestre
Diagramas de Dispersión: En los diagramas de dispersión, se confirma visualmente la relación positiva entre el “preciom” y el “areaconst”, observándose una tendencia de aumento del precio con el incremento del área construida. La dispersión del precio frente al número de baños y habitaciones sugiere una tendencia similar, aunque con más variabilidad, lo que podría indicar la influencia de otros factores no considerados en este análisis.
# 2.2. Análisis de Variables Categóricas
# 2.2.1. Realizar el análisis ANOVA
anova_result <- aov(preciom ~ estrato, data = data_casas)
summary(anova_result)
## Df Sum Sq Mean Sq F value Pr(>F)
## estrato 3 14420497 4806832 110.2 <2e-16 ***
## Residuals 587 25611077 43630
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 2.2.2. Boxplot para Estrato
# Definir colores para cada nivel de la variable estrato
colores_estrato <- c("red", "blue", "green", "orange") # Ajusta los colores según sea necesario
# Crear boxplot para la variable estrato con colores diferenciados
boxplot_estrato <- plot_ly(data_casas, x = ~estrato, y = ~preciom, type = 'box', color = ~estrato, colors = colores_estrato) %>%
layout(title = 'Distribución del Precio por Estrato',
xaxis = list(title = 'Estrato'), yaxis = list(title = 'Precio'))
# Mostrar el boxplot
boxplot_estrato
Incremento del Precio con el Estrato: A medida que el estrato aumenta (de 3 a 6), también se observa un incremento en el precio de las viviendas. Esto sugiere una relación directa entre el estrato socioeconómico y el valor de la propiedad, donde los estratos más altos tienden a tener precios más elevados.
Significancia Estadística: La tabla que acompaña la gráfica muestra un resultado de ANOVA con un valor de p muy pequeño (<2e-16), lo que indica que las diferencias en el precio entre los diferentes estratos son estadísticamente significativas. Esto respalda la observación visual de que el estrato tiene un impacto considerable en el precio de las viviendas.
# 3. Estimación del modelo de regresión lineal múltiple
modelo <- lm(preciom ~ areaconst + estrato + habitaciones + parqueaderos + banios, data = data_casas)
summary(modelo) # Resumen del modelo
##
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos +
## banios, data = data_casas)
##
## Residuals:
## Min 1Q Median 3Q Max
## -759.01 -70.05 -14.87 40.70 1000.15
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 9.88597 29.04995 0.340 0.7338
## areaconst 0.65604 0.05714 11.480 < 2e-16 ***
## estrato4 78.22125 26.27548 2.977 0.0031 **
## estrato5 143.11394 24.34022 5.880 8.97e-09 ***
## estrato6 265.12634 39.90018 6.645 1.05e-10 ***
## habitaciones 7.15024 6.19484 1.154 0.2491
## parqueaderos 27.94967 6.13971 4.552 7.14e-06 ***
## banios 18.74554 8.47921 2.211 0.0276 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 155.8 on 382 degrees of freedom
## (201 observations deleted due to missingness)
## Multiple R-squared: 0.6057, Adjusted R-squared: 0.5985
## F-statistic: 83.84 on 7 and 382 DF, p-value: < 2.2e-16
coeficientes <- tidy(modelo); print(coeficientes) # Obtener coeficientes y p-valores
## # A tibble: 8 × 5
## term estimate std.error statistic p.value
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) 9.89 29.0 0.340 7.34e- 1
## 2 areaconst 0.656 0.0571 11.5 2.07e-26
## 3 estrato4 78.2 26.3 2.98 3.10e- 3
## 4 estrato5 143. 24.3 5.88 8.97e- 9
## 5 estrato6 265. 39.9 6.64 1.05e-10
## 6 habitaciones 7.15 6.19 1.15 2.49e- 1
## 7 parqueaderos 27.9 6.14 4.55 7.14e- 6
## 8 banios 18.7 8.48 2.21 2.76e- 2
Modelo de Regresión: El modelo de regresión tiene un R-cuadrado múltiple de 0.6057 y un R-cuadrado ajustado de 0.5985, lo que indica que aproximadamente el 60% de la variabilidad en el precio puede explicarse por las variables independientes incluidas en el modelo. Esto sugiere que el modelo es moderadamente bueno para predecir el precio basado en las variables seleccionadas.
El valor de F-statistic de 83.84 y un p-valor < 2.2e-16 indican que el modelo en su conjunto es altamente significativo, lo que significa que al menos una de las variables independientes tiene una relación significativa con la variable dependiente (precio).
Intercepto: No es significativo con un p-valor de 0.734, lo que sugiere que el valor predicho del precio cuando todas las variables independientes son cero no es diferente de cero.
areaconst (Área Construida): Tiene un coeficiente de 0.656, que es altamente significativo (p-valor de 2.07e-26), lo que indica que por cada unidad adicional de área construida, el precio aumenta en 0.656 unidades, manteniendo las demás variables constantes.
Estratos: Todos los coeficientes asociados con los estratos (4, 5, 6) son significativos y positivos: Estrato 4: Incrementa el precio en 78.2 unidades (p-valor de 0.0031). Estrato 5: Incrementa el precio en 143 unidades (p-valor de 8.97e-9). Estrato 6: Incrementa el precio en 265 unidades (p-valor de 1.05e-10).
Esto confirma que el estrato socioeconómico tiene un impacto significativo en el precio de las propiedades, siendo mayor en los estratos más altos.
Habitaciones: Aunque su coeficiente es positivo (7.15), no es estadísticamente significativo (p-valor de 0.249), lo que sugiere que **el número de habitaciones no tiene un impacto significativo en el precio dentro de este modelo.
Parqueaderos: Tiene un coeficiente significativo de 27.9 (p-valor de 7.14e-6), lo que indica que tener parqueaderos aumenta el precio de la propiedad.
Baños: También es significativo con un coeficiente de 18.7 (p-valor de 0.0276), lo que sugiere que el número de baños tiene un impacto positivo en el precio, aunque es menos pronunciado en comparación con otras variables como el área construida y los estratos.
# 4. Validación de supuestos
###################################################################
# 4.1 Linealidad y Homoscedasticidad: Graficar residuos vs. valores ajustados
###################################################################
ggplot(modelo, aes(x = .fitted, y = .resid)) +
geom_point() +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
labs(title = "Residuos vs. Valores Ajustados", x = "Valores Ajustados", y = "Residuos")
###################################################################
# 4.2 Independencia de los Errores: Gráfico de residuos vs. orden
###################################################################
ggplot(modelo, aes(x = seq_along(.resid), y = .resid)) +
geom_point() +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
labs(title = "Residuos vs. Orden", x = "Orden", y = "Residuos")
###################################################################
# 4.3 Normalidad de los Errores: Histograma de residuos y Q-Q plot
###################################################################
par(mfrow = c(1, 2)) # Configurar para múltiples gráficos
hist(modelo$residuals, main = "Histograma de Residuos", xlab = "Residuos")
qqnorm(modelo$residuals, main = "Q-Q Plot de Residuos")
qqline(modelo$residuals, col = "red")
par(mfrow = c(1, 1)) # Volver a la configuración original
# Prueba de Shapiro-Wilk
shapiro_test <- shapiro.test(modelo$residuals)
print(shapiro_test)
##
## Shapiro-Wilk normality test
##
## data: modelo$residuals
## W = 0.83179, p-value < 2.2e-16
# Cargar el paquete lmtest
library(lmtest)
# Prueba de Breusch-Pagan
bp_test <- bptest(modelo)
print(bp_test)
##
## studentized Breusch-Pagan test
##
## data: modelo
## BP = 68.919, df = 7, p-value = 2.443e-12
Linealidad:
El gráfico de residuos vs. valores ajustados sugiere que la relación entre las variables independientes y la dependiente es aproximadamente lineal, aunque hay cierta variabilidad en los residuos que podría indicar que la linealidad no es perfecta. Independencia de los Errores:
El gráfico de residuos vs. orden muestra que no hay un patrón claro, lo que sugiere que los errores son independientes entre sí, cumpliendo así con este supuesto.
Normalidad de los Residuos: La prueba de Shapiro-Wilk arrojó un p-valor extremadamente bajo (< 2.2e-16), lo que indica que los residuos no siguen una distribución normal. Esto podría afectar la validez de las inferencias estadísticas basadas en este modelo.
Homoscedasticidad: La prueba de Breusch-Pagan arrojó un p-valor muy bajo (2.443e-12), indicando la presencia de heterocedasticidad. Esto significa que la variabilidad de los errores no es constante, lo que podría llevar a estimaciones ineficientes y errores estándar incorrectos.
# Crear un DataFrame con las características de la vivienda
vivienda1 <- data.frame(areaconst = 200,estrato = factor(c(4, 5), levels = levels(data_casas_clean$estrato)), banios = 2,habitaciones = 4, parqueaderos = 1)
# Predecir el precio
predicciones <- predict(modelo, newdata = vivienda1)
# Mostrar las predicciones
print(predicciones)
## 1 2
## 313.3562 378.2489
Al comparar las dos predicciones, se observa que la vivienda ubicada en el estrato 5 tiene un precio predicho significativamente más alto (alrededor de 64.89 unidades más) que la vivienda en el estrato 4, manteniendo constantes las demás características. Esto confirma nuevamente la influencia significativa del estrato socioeconómico en el precio de las propiedades, con los precios incrementando a medida que se sube de estrato.
# Filtrar y seleccionar las 5 ofertas más baratas
ofertas <- data %>%
filter(preciom >= min(predicciones) & preciom <= max(predicciones),
areaconst >= 200, # Ajustar según el rango deseado
parqueaderos == 1,
banios == 2,
habitaciones == 4,
tipo == "Casa",
zona == "Zona Norte",
estrato %in% c(4, 5)) %>%
arrange(preciom) %>%
head(5)
# Crear el mapa
leaflet(ofertas) %>% addTiles() %>%
addCircleMarkers(~longitud, ~latitud, color = 'blue',
popup = ~paste("<br>Tipo:", tipo, "<br>Área:", areaconst, "<br>Parqueaderos:", parqueaderos, "<br>Baños:", banios, "<br>Habitaciones:", habitaciones, "<br>Estrato:", estrato, "<br>Zona:", zona, "<br>Precio:", preciom),
radius = 8, fillOpacity = 0.7) %>% setView(lng = mean(ofertas$longitud), lat = mean(ofertas$latitud), zoom = 12)
# Mostrando los resultados
print(ofertas %>% select(preciom, areaconst, parqueaderos, banios, habitaciones, estrato))
## # A tibble: 1 × 6
## preciom areaconst parqueaderos banios habitaciones estrato
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 350 346 1 2 4 5
Resultado:
Después de aplicar estos filtros, solo una vivienda cumple con todos los criterios especificados. Esto indica que las condiciones de búsqueda son bastante específicas y que la base de datos contiene muy pocas propiedades que se ajustan exactamente a este perfil. Interpretación:
Esta única vivienda representa un caso que encaja perfectamente con las condiciones establecidas para la búsqueda, lo cual puede ser útil para análisis más detallados, comparaciones con predicciones o decisiones de compra.
# Filtrar y seleccionar las 5 ofertas más baratas
ofertas <- data %>%
filter(preciom >= min(predicciones) & preciom <= max(predicciones),
##areaconst >= 300, # Ajustar según el rango deseado
##parqueaderos == 1,
banios == 2,
habitaciones == 4,
tipo == "Casa",
zona == "Zona Norte",
estrato %in% c(4, 5)) %>%
arrange(preciom) %>%
head(5)
# Crear el mapa
leaflet(ofertas) %>% addTiles() %>%
addCircleMarkers(~longitud, ~latitud, color = 'blue',
popup = ~paste("<br>Tipo:", tipo, "<br>Área:", areaconst, "<br>Parqueaderos:", parqueaderos, "<br>Baños:", banios, "<br>Habitaciones:", habitaciones, "<br>Estrato:", estrato, "<br>Zona:", zona, "<br>Precio:", preciom),
radius = 8, fillOpacity = 0.7) %>% setView(lng = mean(ofertas$longitud), lat = mean(ofertas$latitud), zoom = 12)
# Mostrando los resultados
print(ofertas %>% select(preciom, areaconst, parqueaderos, banios, habitaciones, estrato))
## # A tibble: 4 × 6
## preciom areaconst parqueaderos banios habitaciones estrato
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 340 295 2 2 4 4
## 2 350 216 2 2 4 5
## 3 350 346 1 2 4 5
## 4 360 216 2 2 4 4
Resultado: