You can also embed plots, for example:
# if (!requireNamespace("library(ggplot2)", quietly = TRUE)) {
# install.packages("library(ggplot2)")
# }
library(ggplot2)
#
# if (!requireNamespace("library(dplyr)", quietly = TRUE)) {
# install.packages("library(dplyr)")
# }
library(dplyr)
#
# if (!requireNamespace("devtools", quietly = TRUE)) {
# devtools::install_github("dgonxalex80/paqueteMETODOS")
# }
library(paqueteMETODOS)
#
# if (!requireNamespace("library(corrplot)", quietly = TRUE)) {
# install.packages("library(corrplot)")
# }
library(corrplot)
Con base en los datos de ofertas de vivienda descargadas del portal Fincaraiz para apartamentos de estrato 4 con área construida menor a 200 m^2 (vivienda4.RDS) la inmobiliaria A&C requiere el apoyo de un científico de datos en la construcción de un modelo que lo oriente sobre los precios de inmuebles. Con este propósito el equipo de asesores a diseñado los siguientes pasos para obtener un modelo y así poder a futuro determinar los precios de los inmuebles a negociar.
Se obtiene el dataset y se realizan los filtros de solo obtener apartamentos y areas menores a 200 metros cuadrados
data(vivienda4)
df2 <- vivienda4
df2 <- df2[df2$tipo == "Apartamento" & df2$areaconst <= 200, ]
head(df2, 10)
## # A tibble: 10 × 5
## zona estrato preciom areaconst tipo
## <fct> <fct> <dbl> <dbl> <fct>
## 1 Zona Norte 4 232. 52 Apartamento
## 2 Zona Norte 4 255. 108 Apartamento
## 3 Zona Sur 4 258. 96 Apartamento
## 4 Zona Norte 4 250. 82 Apartamento
## 5 Zona Norte 4 247. 75 Apartamento
## 6 Zona Norte 4 222. 60 Apartamento
## 7 Zona Norte 4 227. 84 Apartamento
## 8 Zona Norte 4 255. 117 Apartamento
## 9 Zona Norte 4 232. 60 Apartamento
## 10 Zona Norte 4 237. 75 Apartamento
Se observa que existen 5 zonas, con la mayoría de los datos concentrados en la zona sur. Dado que las variables “estrato” y “tipo” son constantes, se procede a eliminarlas. Además, dado que no hay datos nulos, no se requiere ningún proceso de imputación.
summary(df2)
## zona estrato preciom areaconst
## Zona Centro : 7 3: 0 Min. :207.4 Min. : 40.00
## Zona Norte : 237 4:1363 1st Qu.:228.8 1st Qu.: 60.00
## Zona Oeste : 52 5: 0 Median :236.1 Median : 70.00
## Zona Oriente: 2 6: 0 Mean :237.7 Mean : 75.48
## Zona Sur :1065 3rd Qu.:243.6 3rd Qu.: 84.00
## Max. :305.2 Max. :200.00
## tipo
## Apartamento:1363
## Casa : 0
##
##
##
##
df3 <- df2[, !(names(df2) %in% c("estrato", "tipo"))]
cantidad_nulos <- colSums(is.na(df2))
print("Nulos")
## [1] "Nulos"
cantidad_nulos
## zona estrato preciom areaconst tipo
## 0 0 0 0 0
hist(df3$preciom, main = "Histograma de Precios", xlab = "Precio")
Las áreas de las viviendas van desde 40 metros cuadrados hasta un máximo de 200 metros cuadrados. con una mediana de 75 metros cuadrados y una media de 77metros cuadrados. En cuanto a la distribución de los datos se evidencia que es simétrica sesgada a la izquierda, pero con una mayor dispersión que los datos de la variable precios.
hist(vivienda4$areaconst, main = "Histograma de Área", xlab = "Área")
No se incluyen en el análisis las zonas Oriente y Centro debido a que cuentan con solo 2 y 7 datos, respectivamente. Por otro lado, se destaca que las zonas Norte, Oeste y Sur muestran un rango intercuartílico muy similar, oscilando entre 22 y 23.75.
df1 <- df3 %>%
filter(zona %in% c("Zona Norte", "Zona Oeste", "Zona Sur"))
ggplot(df1, aes(x = zona, y = areaconst)) +
geom_boxplot(fill = "pink") +
labs(x = "Zona",
y = "Area",
title = "Area de las viviendas por zona") +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5),
panel.background = element_rect(fill = "white")
)
iqr_data <- df1 %>%
group_by(zona) %>%
summarize(Q1 = quantile(areaconst, 0.25),
median = median(areaconst),
Q3 = quantile(areaconst, 0.75),
IQR = Q3 - Q1)
ggplot(iqr_data, aes(x = zona, y = Q1)) +
geom_text(aes(label = paste0("Q1: ", round(Q1, 2))), vjust = -0.5) +
geom_text(aes(y = median, label = paste0("Median: ", round(median, 2))), vjust = -0.5) +
geom_text(aes(y = Q3, label = paste0("Q3: ", round(Q3, 2))), vjust = -0.5) +
geom_text(aes(y = Q3 + IQR * 0.5, label = paste0("IQR: ", round(IQR, 2))), vjust = -0.5, color = "blue") +
labs(x = "Zona",
y = "Precio",
title = "Resumen estadístico del precio por zona") +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(hjust = 0.5),
panel.background = element_rect(fill = "white"))
iqr_data
## # A tibble: 3 × 5
## zona Q1 median Q3 IQR
## <fct> <dbl> <dbl> <dbl> <dbl>
## 1 Zona Norte 61 73 83 22
## 2 Zona Oeste 58.2 63 82 23.8
## 3 Zona Sur 60 70 83 23
El promedio del precio de las viviendas ronda los 238 millones de pesos en las tres zonas que tienen mayor representación. Esto sugiere que la ubicación geográfica no ejerce una influencia significativa en el precio de las viviendas.
df1 <- df3 %>%
filter(zona %in% c("Zona Norte", "Zona Oeste", "Zona Sur"))
# Calcular el precio promedio por zona
df_summary <- df1 %>%
group_by(zona) %>%
summarise(avg_price = mean(preciom, na.rm = TRUE))
# Crear el gráfico de barras
ggplot(df_summary, aes(x = zona, y = avg_price)) +
geom_bar(stat = "identity", fill = "skyblue", alpha = 0.7) +
labs(title = "Precio promedio por zona",
x = "Zona",
y = "Precio promedio") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
geom_text(aes(label = paste("$", round(avg_price, 2))), vjust = -0.5, color = "blue")
Se realiza el mismo analisis anterior pero entre la zona y el área y se eviencia que la dispersión es muy similar en todas las zonas, con la diferencia de que la mediana de la zona oeste es de 165m2, un poco mas baja que las de las zonas sur y norte que son 185m2 y 190m2 respectivamente.
df1 <- df3 %>%
filter(zona %in% c("Zona Norte", "Zona Oeste", "Zona Sur"))
ggplot(df1, aes(x = zona, y = preciom)) +
geom_boxplot(fill = "pink") +
labs(x = "Zona",
y = "Area",
title = "Area de las viviendas por zona") +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5),
panel.background = element_rect(fill = "white")
)
iqr_data <- df1 %>%
group_by(zona) %>%
summarize(Q1 = quantile(preciom, 0.25),
median = median(preciom),
Q3 = quantile(preciom, 0.75),
IQR = Q3 - Q1)
ggplot(iqr_data, aes(x = zona, y = Q1)) +
geom_text(aes(label = paste0("Q1: ", round(Q1, 2))), vjust = -0.5) +
geom_text(aes(y = median, label = paste0("Median: ", round(median, 2))), vjust = -0.5) +
geom_text(aes(y = Q3, label = paste0("Q3: ", round(Q3, 2))), vjust = -0.5) +
geom_text(aes(y = Q3 + IQR * 0.5, label = paste0("IQR: ", round(IQR, 2))), vjust = -0.5, color = "blue") +
labs(x = "Zona",
y = "Precio",
title = "Resumen estadístico del precio por zona") +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(hjust = 0.5),
panel.background = element_rect(fill = "white"))
iqr_data
## # A tibble: 3 × 5
## zona Q1 median Q3 IQR
## <fct> <dbl> <dbl> <dbl> <dbl>
## 1 Zona Norte 230. 237. 244. 13.3
## 2 Zona Oeste 228. 238. 247. 18.9
## 3 Zona Sur 229. 236. 243. 14.7
El coeficiente de correlación entre el precio y el área es de 0.84
(Correlación positiva fuerte), lo que refleja una correlación
significativa entre estas dos variables . Esto sugiere que a medida que
el área de la vivienda aumenta, es probable que también lo haga el
precio de manera proporcional. Sin embargo, es crucial recordar que la
correlación no implica causalidad. Aunque estas variables serán nuestras
respuestas y predictoras respectivamente para el desarrollo de la
práctica, debemos estar conscientes de que otros factores pueden influir
en los precios de las viviendas además del área.
correlation <- cor(df3$areaconst, df3$preciom)
correlation
## [1] 0.8463271
Dado que hemos identificado una correlación positiva fuerte entre el precio y el área construida en nuestra matriz de correlación, es crucial explorar esta relación más a fondo mediante un gráfico de dispersión. Al observar el gráfico, confirmamos una tendencia positiva y lineal entre ambas variables. Esta conclusión sugiere que el precio de una vivienda está influenciado de manera significativa por su tamaño. En resumen, este análisis proporciona una comprensión más clara de cómo el tamaño de una vivienda impacta su precio.
# Crea un gráfico de dispersión entre areaconst y preciom
plot(df3$areaconst, df3$preciom,
xlab = "Área Construida (m^2)",
ylab = "Precio (millones)",
main = "Relación entre Área Construida y Precio",
col = "blue",
pch = 16) # Define el tipo de punto
# Agrega una línea de regresión lineal
abline(lm(df3$preciom ~ df3$areaconst), col = "red")
# Estimar el modelo de regresión lineal simple
modelo <- lm(preciom ~ areaconst, data = df3)
# Mostrar el resumen del modelo
summary(modelo)
##
## Call:
## lm(formula = preciom ~ areaconst, data = df3)
##
## Residuals:
## Min 1Q Median 3Q Max
## -26.5139 -5.0886 -0.0031 4.6406 24.3309
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.001e+02 6.698e-01 298.67 <2e-16 ***
## areaconst 4.984e-01 8.503e-03 58.62 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 7.081 on 1361 degrees of freedom
## Multiple R-squared: 0.7163, Adjusted R-squared: 0.7161
## F-statistic: 3436 on 1 and 1361 DF, p-value: < 2.2e-16
β0 (200.1): representa el intercepto, es decir, el valor esperado del precio cuando el área (variable independiente) es cero. Sin embargo, en el contexto del modelo, esta interpretación puede no ser relevante, ya que es poco probable que el área de una propiedad sea cero en la realidad. Por lo tanto, una interpretación más adecuada es que β0 representa el precio base para el apartamento más pequeño imaginable (200.1 Millones), y a partir de este punto, los precios aumentan dependiendo del área y del coeficiente β1
β1 (0.4984) : Representa la pendienterepresenta, es decir, el cambio esperado en el precio por cada unidad de cambio en el área. En este caso, por cada unidad adicional en el área de la propiedad, el precio previsto aumenta en aproximadamente 498 mil pesos
En resumen, el modelo de regresión lineal simple sugiere que el área construida es un predictor significativo del precio de la vivienda en tu conjunto de datos, con un R^2 del 71.61%. Sin embargo, es importante recordar que este modelo puede no capturar completamente toda la variabilidad en los datos y que otros factores pueden influir en el precio de las viviendas.
intervalo_confianza <- confint(modelo)
cat("Intervalo de confianza del 95% para beta1:", intervalo_confianza[2, 1], "a", intervalo_confianza[2, 2], "\n")
## Intervalo de confianza del 95% para beta1: 0.4817357 a 0.515097
Los resultados muestran los intervalos de confianza del 95% para el coeficientes del modelo de regresión lineal:
Este intervalos indican el rango plausible dentro del cual se espera que se encuentre el valor real del coeficiente, con una confianza del 95%. Es decir, podemos estar razonablemente seguros de que el verdadero valor del coeficiente estará dentro de estos intervalos.
En este caso, el intervalo de confianza para el coeficiente de “areaconst” no incluye el valor cero. Esto sugiere que hay evidencia significativa para sugerir que el coeficiente de “area” es diferente de cero, lo que implica que existe una relación significativa entre la variable “area” y la variable de respuesta “precio”.
Ahora Realizamos una prueba de hipotesis T para comparar este resultado.
# Interpretar el intervalo de confianza
cat("Intervalo de confianza del 95% para beta1:", intervalo_confianza[2, 1], "a", intervalo_confianza[2, 2], "\n")
## Intervalo de confianza del 95% para beta1: 0.4817357 a 0.515097
# Realizar la prueba de hipótesis t
# Extraer el valor estimado del coeficiente beta1 y su error estándar
beta1_estimado <- coef(modelo)[2]
error_estandar_beta1 <- summary(modelo)$coef[2, "Std. Error"]
# Calcular el valor de la prueba t
valor_t <- beta1_estimado / error_estandar_beta1
# Determinar los grados de libertad
grados_libertad <- length(modelo$residuals) - length(coef(modelo))
# Definir el nivel de significancia
nivel_significancia <- 0.05
# Obtener el valor crítico de la distribución t
valor_critico_t <- qt(1 - nivel_significancia / 2, df = grados_libertad)
# Imprimir los resultados
cat("Valor de la prueba t:", valor_t, "\n")
## Valor de la prueba t: 58.61576
cat("Valor crítico t:", valor_critico_t, "\n")
## Valor crítico t: 1.961709
# Comparar el valor de la prueba t con el valor crítico t
if (abs(valor_t) > valor_critico_t) {
cat("Se rechaza la hipótesis nula. El coeficiente beta1 = área es significativamente diferente de cero.\n")
} else {
cat("No se rechaza la hipótesis nula. No hay suficiente evidencia para afirmar que el coeficiente beta1 = área es diferente de cero.\n")
}
## Se rechaza la hipótesis nula. El coeficiente beta1 = área es significativamente diferente de cero.
El intervalo de confianza del 95% para β1 es de 0.48 a 0.51
Para la prueba de hipótesis t:
El valor de la prueba t es 58.6.
El valor crítico t para un nivel de significancia del 5% es 1.96
El valor crititico t es el valor que separa las regiones de rechazo y no rechazo de la distribución t para una prueba de hipotesis t. En otras palabras, si la estadistica de purbea t calculada es mayor (en valor absoluto) que el valor critico t, entonces rechazamos la hipotesis nula.
Dado que el valor absoluto de la prueba t es mayor que el valor crítico t, se rechaza la hipótesis nula. Por lo tanto, concluimos que el coeficiente β1 (que representa el efecto del área en el precio) es significativamente diferente de cero. Esto sugiere que el área tiene un impacto significativo en el precio de la propiedad.
# Obtener el resumen del modelo
resumen_modelo <- summary(modelo)
# Extraer el valor de R-squared
r_cuadrado <- resumen_modelo$r.squared
# Imprimir el valor de R-squared
cat("Coeficiente de determinación R^2:", r_cuadrado, "\n")
## Coeficiente de determinación R^2: 0.7162696
#predict(modelo, data.frame(areaconst=110), interval = "prediction", level = 0.95)
El coeficiente de determinación R^2 es una métrica esencial en la evaluación de modelos de regresión, ya que proporciona una medida de la capacidad del modelo para explicar la variabilidad observada en los datos. En el análisis realizado, el valor R^2 obtenido es de aproximadamente 0.716. Esto indica que alrededor del 71.6% de la variabilidad en el precio de las propiedades puede ser explicada por el modelo de regresión lineal simple que hemos ajustado. En otras palabras, el área de las propiedades, considerada como única variable independiente en nuestro modelo, es capaz de explicar casi el 71.6% de la variación observada en los precios de las propiedades.
Este resultado sugiere una relación significativa entre el área de las propiedades y sus precios, lo que respalda la utilidad del modelo para explicar y predecir el comportamiento de los precios en función del área. Sin embargo, es importante tener en cuenta que R^2 por sí solo no proporciona una evaluación completa de la validez del modelo y, por lo tanto, debe ser considerado en conjunto con otras métricas y análisis adicionales para una comprensión completa de la relación entre las variables y la capacidad predictiva del modelo.
pre <- predict(modelo, data.frame(areaconst=110), interval = "prediction", level = 0.95)
pre
## fit lwr upr
## 1 254.8893 240.9814 268.7971
precio_estimado <- pre[1,1]
# Comparar con el precio real de 200 millones
precio_oferta <- 200
if (precio_oferta < precio_estimado) {
cat("La oferta es atractiva para un comprador.\n")
} else {
cat("La oferta no es atractiva para un comprador.\n")
}
## La oferta es atractiva para un comprador.
El precio estimado por el modelo para una vivienda de 110 metros cuadrados es, en promedio, de 254.9 millones de pesos. Por consiguiente, la oferta de esa misma vivienda por un precio de 200 millones de pesos resulta verdaderamente atractiva para un comprador (lo contrario para un vendedor), dado que podría inferirse que está con un descuento del 21.5%. No obstante, esta evaluación se fundamenta únicamente en el precio estimado por el modelo de Regresión Lineal Simple con la variable “área”. Es crucial considerar otros aspectos importantes, como la ubicación exacta del inmueble, sus características específicas, así como cualquier otra variable relevante que pueda influir en el valor de la propiedad.
Como se observó en el grafico de dispersión de precio vs área, se
observa que se sigue una relaciónlineal:
Adicionalmente, el análisis de los residuos versus los valores ajustados mostró que la dispersión de los residuos alrededor de la línea roja de referencia (línea cero) era aleatoria y cercana a esta línea. Además, la línea de referencia se mantuvo horizontal en todo el rango de valores ajustados. Estos hallazgos sugieren que se cumple la suposición de linealidad del modelo de regresión lineal.
plot(modelo, which = 1)
Dado que se observa una línea aproximadamente horizontal en el gráfico de dispersión de los residuos versus los valores ajustados, es un indicio positivo en cuanto al cumplimiento del supuesto de homocedasticidad en el modelo RLS. Este resultado sugiere que la varianza de los errores alrededor de la línea de regresión es aproximadamente constante a lo largo de los diferentes niveles de los valores ajustados. En términos prácticos, esto implica que las estimaciones de los parámetros del modelo son eficientes y las inferencias basadas en ellas son válidas.
Adicionalmente realizamos el test de Breusch-Pagan en donde obtenemos un valor de prueba (BP) de 0.83288 y un valor p asociado de 0.3614. Con un nivel de significancia del 0.05, como el valor p (0.3614) es mayor que este umbral, no se rechaza la hipótesis nula de homocedasticidad. Por lo tanto, no hay evidencia suficiente para afirmar que existe heterocedasticidad en el modelo de regresión lineal.
library(lmtest)
bptest(modelo)
##
## studentized Breusch-Pagan test
##
## data: modelo
## BP = 0.83288, df = 1, p-value = 0.3614
De acuerdo con la curva que se evidencia en el histograma y como los puntos en el gráfico se ajustan bien a la línea diagonal el grafico “Normal Q-Q Plot”, sugiere que los residuos siguen una distribución normal.
qqnorm(resid(modelo))
qqline(resid(modelo))
hist(resid(modelo), main = "Histograma de Residuos", xlab = "Residuos")
Adicionalmente se realiza el test de Shapiro-Wilk para la normalidad de los residuos del modelo, y obtenemos un valor de estadístico W de 0.99885 con un valor p asociado de 0.5419. Dado que el valor p (0.5419) es mayor que cualquier nivel de significancia comúnmente utilizado, no hay suficiente evidencia para rechazar la hipótesis nula de normalidad de los residuos. Por lo tanto, podemos asumir que los residuos del modelo siguen una distribución normal.
shapiro.test(resid(modelo))
##
## Shapiro-Wilk normality test
##
## data: resid(modelo)
## W = 0.99885, p-value = 0.5419
Al evaluar la linealidad, homocedasticidad y normalidad de los residuos, no encontramos evidencia significativa que sugiera una violación de estos supuestos. La inspección visual de los gráficos complementa estos hallazgos, mostrando una distribución uniforme de los residuos y una alineación cercana a la línea de referencia en las gráficas residuales. En consecuencia, podemos afirmar con confianza que la relación lineal entre las variables se mantiene sólida, sin necesidad de aplicar transformaciones adicionales al modelo. Este análisis fortalece nuestra confianza en la validez y fiabilidad de los resultados obtenidos a través del modelo de regresión lineal.
Estime varios modelos y compare los resultados obtenidos. En el mejor de los modelos, ¿se cumplen los supuestos sobre los errores?
Trabajaremos con cuatro modelos en total: el modelo original y tres modelos adicionales. Los modelos adicionales incluyen transformaciones logarítmicas, raíz cuadrada y exponencial de la variable de respuesta.
modelo_original = lm(df3$preciom~df3$areaconst)
modelo_log = lm(df3$preciom~log(df3$areaconst))
modelo_sqrt = lm(df3$preciom~sqrt(df3$areaconst))
modelo_exp = lm(df3$preciom~exp(df3$areaconst))
resumen_modelo_original <- summary(modelo_original)
resumen_modelo_log <- summary(modelo_log)
resumen_modelo_sqrt <- summary(modelo_sqrt)
resumen_modelo_exp <- summary(modelo_exp)
Modelos = c(" Original", "Logaritmo", "Raiz Cuadrada", "Exponencial")
R2_Modelos = c(resumen_modelo_original$r.squared, resumen_modelo_log$r.squared, resumen_modelo_sqrt$r.squared, resumen_modelo_exp$r.squared)
tabla = data.frame(Modelos, R2_Modelos)
print(tabla)
## Modelos R2_Modelos
## 1 Original 0.71626963
## 2 Logaritmo 0.68201588
## 3 Raiz Cuadrada 0.70614304
## 4 Exponencial 0.06322411
Como resultado, observamos que el modelo original presenta un coeficiente de determinación (R²) más alto en comparación con los otros modelos alternativos. El R² del modelo original es de aproximadamente 0.716, lo que indica que alrededor del 71.6% de la variabilidad en el precio de las viviendas puede ser explicada por el tamaño de construcción utilizando este modelo.
Además, es importante destacar que previamente se llevó a cabo la validación de los supuestos para este modelo original en el punto 7, donde concluimos que se cumplen los requisitos de linealidad, homocedasticidad y normalidad tanto mediante gráficos como pruebas de hipótesis.
La conclusión del análisis destaca una relación robusta entre el precio
y el área de los inmuebles, donde cada incremento en el área se traduce
en un aumento en el precio. Esta asociación se ratifica mediante el
análisis bivariado, respaldando la afirmación de que por cada metro
cuadrado adicional en el área, el precio de los inmuebles aumenta
alrededor de $480 mil pesos, según el modelo.
Es relevante subrayar que el modelo original cumple con los supuestos y proporciona resultados confiables, aunque se evaluaron otras transformaciones que no arrojaron diferencias significativas en los resultados.
Con el modelo actual, es factible realizar predicciones precisas sobre los precios de los apartamentos. Este enfoque basado en fundamentos matemáticos sólidos brindará a la inmobiliaria la capacidad de fijar precios con mayor precisión y respaldar sus decisiones con análisis estadísticos robustos.
Para futuras investigaciones, se sugiere la inclusión de más variables, como información demográfica y características específicas de las viviendas, con el fin de refinar aún más el modelo y obtener resultados más precisos y confiables basados en datos adicionales.