abstract: | El presente documento está compuesto de diversos análisis al sector inmobiliario de la ciudad de Cali, teniendo en cuenta la base que proporcionaron por parte de AYC se establecieron etapas en el ciclo de vida de los datos para garantizar la calidad de los mismos e implementar lógicas estadísticas que nos permitan evidenciar comportamientos para identificar las tendencias y patrones en los datos, también se implementó una regresión simple con las validaciones de supuestos, transformaciones al modelo, pruebas de hipotesis y conslusiones sobre el desarrollo de la actividad. Resumiendo todo lo desarrollado en la asignatura. with_amsmath: true output: html_document —
El actual desarrollo económico de las grandes urbes en Colombia se ve reflejado en el sector inmobiliario. El presente informe toma como muestra apartamentos de estrato cuatro con el objetivo de desarrollar un modelo que oriente a la inmobiliaria AyC conforme a los precios y las variables a tener en cuenta al momento de realizar negociaciones con futuros clientes. Es importante resaltar que, el desarrollo del proyecto incluye todas las lógicas, procedimientos, implementaciones y conocimientos adquiridos en la asignatura de metodos y simulación estádistica; iniciando con estadística descriptica, detección e imputación de outliers, correlaciones entre variables (precio y área construida), modelo de regresión simple, pruebas de hipótesis, intervalos de confianza,validación de supuestos, transformaciones al modelo y conclusiones a la inmobiliaria AyC.
Para un correcto desarrollo del modelo solicitado por la inmobiliaria AyC, primero de debe entender la necesidad por parte del cliente, luego, la base de datos con sus variables, comportamientos y tipos de datos, posterior a esto, se deben aplicar lógicas y procedimientos para la identificación de datos faltantes y datos atípicos; con el objetivo de normalizar los datos previo al desarrollo del modelo de regresión.
Para iniciar con la estadística descriptiva, primero se realizó una segmentación de la base, teniendo en cuenta unicamente los registros asociados a tipos de inmueble apartamento. Por otra parte, se validó la presencia de datos faltantes y todos los registros estaban correctos.
Luego de la primera fase de limpieza, se procede a analizar el comportamiento y distribución de los registros conforme a los tipos de variables y según si son dependientes o independientes en el modelo que se desarrollará.
Se puede evidenciar que, el precio promedio de los apartamentos es de 237.68 millones de pesos y el promedio de área construida es de 75.48 metros cuadrados.
kable(promedio_por_tipo, caption = "Promedio de Precios y Área Construida", format = "latex", booktabs = TRUE) %>%
kable_styling(latex_options = c("hold_position"))
Así mismo, se puede apreciar que la zona sur tiene el mayor numero de inmuebles, seguido de la zona norte, la proporción de estas comparadas con las demás zonas de la base es mucho mayor.
kable(conteo_inmuebles, caption = "Inmuebles por Zona", format = "latex", booktabs = TRUE) %>%
kable_styling(latex_options = c("hold_position"))
En relación al precio promedio del inmueble por zona, el mayor valor promedio lo tiene la zona centro con 256,37 millones de pesos y un mayor área promedio de 107,71 metros cuadrados; lo que contrasta con el número de inmuebles presentes en esa zona y nos da indicios de las caracteristicas de los apartamentos en esta área de la ciudad. Por su parte, la zona zona sur tiene el menor valor promedio con 237,18 millones de pesos y la menor área construida en la ciudad 74.57 metros cuadrados.
# Crear las tablas y asegurarse de que la numeración sea correcta
kable(promedio_por_zona, caption = "Promedio de Precios y Área Construida por Zona", format = "latex", booktabs = TRUE) %>%
kable_styling(latex_options = c("hold_position"))
# Calcular la correlación solo por zona
correlation_results <- ejercicio %>%
group_by(zona) %>%
summarise(
correlation = cor(preciom, areaconst, use = "complete.obs"),
.groups = "drop" # Para evitar el mensaje de agrupamiento
)
Para el entendimiento y desarrollo del modelo, es necesaria la identificación de correlación entre las variables precio y área construida.Se puede evidenciar que, la correlación entre las variables es alta, lo que nos indica que entre mas grande sea la vivienda, mayor será su precio y nos da indicios de la viabilidad del modelo que se necesita desarrollar con base en el requerimiento de AyC inmobiliaria. En todos estos pasos hemos analizado el comportamiento de los datos a nivel descriptivo con el objetivo de conocer identificar comportamientos y plantear lógicas y procedimientos que garanticen el correcto desarrollo del modelo de regresión.
# Gráfico de dispersión por zona con ajustes de tamaño en los textos
ggplot(ejercicio, aes(x = areaconst, y = preciom, color = zona)) +
geom_point(alpha = 0.6) +
labs(x = "Área Construida",
y = "Precio por Metro Cuadrado",
caption = "Fig. I: Relación Precio m2 y Área Construida.") +
theme_minimal() +
theme(
plot.caption = element_text(hjust = 0.5, size = 6), # Centrar la caption
legend.text = element_text(size = 6), # Cambiar el tamaño de las letras en la leyenda
legend.title = element_text(size = 6), # Cambiar el tamaño del título de la leyenda (Zona)
axis.title.x = element_text(size = 7), # Cambiar el tamaño del título del eje X
axis.title.y = element_text(size = 7), # Cambiar el tamaño del título del eje Y
axis.text = element_text(size = 6) # Cambiar el tamaño de las etiquetas de los ejes
) +
# Agregar el índice de correlación centrado
annotate("text",
x = mean(ejercicio$areaconst, na.rm = TRUE), # Centrar en el eje x
y = max(ejercicio$preciom, na.rm = TRUE) - 0.1 * (max(ejercicio$preciom, na.rm = TRUE) - min(ejercicio$preciom, na.rm = TRUE)), # Ajustar el y
label = paste("Correlación:", round(mean(correlation_results$correlation), 4)),
size = 2, color = "black", hjust = 0.5) # Centrado horizontalmente
Es importante resaltar que, hasta el momento no se ha realizado la detección de outliers e imputación de los mismos, pero es necesaria esta validación previa a la imputación teniendo en cuenta que la base tiene pocas variables y esto impactará en la lógica a implementar para la imputación.
Las variables precio y área construida tienen una correlación alta, lo que indicaría el comportamiento mendionado anteriormente, sin embargo, es necesaria la identificación de outliers y la medición de correlación posterior a la imputación. Se puede evidenciar que a nivel de precios la zona norte y sur tienen mayor numero de datos atípicos, también se puede envidenciar, aunque en menor nivel, los outliers de la zona oeste. Por otra parte, en relación con el área construida se puede evidenciar que las zonas norte y sur tienen un mayor numero de atípicos, seguidos de la zona oeste.
# Función para detectar outliers utilizando el método IQR
detect_outliers <- function(x) {
q1 <- quantile(x, 0.25, na.rm = TRUE)
q3 <- quantile(x, 0.75, na.rm = TRUE)
iqr <- q3 - q1
lower_bound <- q1 - 1.5 * iqr
upper_bound <- q3 + 1.5 * iqr
return(x < lower_bound | x > upper_bound)
}
# Boxplot para 'preciom' antes de la imputación con tamaño reducido de texto
ggplot(ejercicio, aes(x = zona, y = preciom, fill = tipo)) +
geom_boxplot(outlier.colour = "red", outlier.size = 2) +
labs(caption = "Fig. II: Boxplot de Precio m2 por Zona.",
x = "Zona", # Etiqueta para el eje X
y = "Precio por Metro Cuadrado") + # Etiqueta para el eje Y
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 6), # Reducir tamaño de texto en los valores del eje X
axis.text.y = element_text(size = 6), # Reducir tamaño de texto en los valores del eje Y
axis.title.x = element_text(size = 6), # Reducir tamaño del título del eje X
axis.title.y = element_text(size = 6), # Reducir tamaño del título del eje Y
legend.title = element_text(size = 6), # Reducir tamaño del título de la leyenda
legend.text = element_text(size = 6), # Reducir tamaño del texto de la leyenda
plot.caption = element_text(hjust = 0.5, size = 6)) # Reducir tamaño de la caption
Es importante tener en cuenta que la identificación de atípicos se llevo a cabo con el uso del rango intercuartílico (IQR).Por otra parte, se debe resaltar que la base con la que se está trabajando no permite hacer una estimación precisa de outliers dado que tiene escasas variables para hacer la detección y correspondiente imputación; por consiguiente no se puede mapear a detalle variables necesarias como son: Antiguedad del inmueble, piso, barrio; entre otras.
# Boxplot para 'Áreaconst' antes de la imputación
# Boxplot para 'areaconst' antes de la imputación con tamaño reducido de texto
ggplot(ejercicio, aes(x = zona, y = areaconst, fill = tipo)) +
geom_boxplot(outlier.colour = "red", outlier.size = 2) +
labs(caption = "Fig. III: Boxplot de Área Construida por Zona.",
x = "Zona", # Etiqueta para el eje X
y = "Área Construida (m2)") + # Etiqueta para el eje Y
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 6), # Reducir tamaño de texto en los valores del eje X
axis.text.y = element_text(size = 6), # Reducir tamaño de texto en los valores del eje Y
axis.title.x = element_text(size = 6), # Reducir tamaño del título del eje X
axis.title.y = element_text(size = 6), # Reducir tamaño del título del eje Y
legend.title = element_text(size = 6), # Reducir tamaño del título de la leyenda
legend.text = element_text(size = 6), # Reducir tamaño del texto de la leyenda
plot.caption = element_text(hjust = 0.5, size = 6)) # Reducir tamaño de la caption
Posterior a la detección, se procede a imputar los outliers con la mediana agrupando por zonas. Se puede evidenciar el impacto de la imputación en el comportamiento de los datos en los boxplots, por otra parte, se identifica que el indice de correlación disminuyó a comparación del modelo sin imputación de datos atípicos.
# Función para imputar outliers por la mediana en función de zona y tipo
impute_outliers <- function(df, column) {
df <- df %>%
group_by(zona, tipo) %>%
mutate(
is_outlier = detect_outliers(get(column)),
median_value = median(get(column), na.rm = TRUE)
) %>%
mutate(
!!column := ifelse(is_outlier, median_value, get(column))
) %>%
select(-is_outlier, -median_value) # Eliminar columnas auxiliares
return(df)
}
# Imputar outliers en 'preciom' y 'areaconst'
ejercicio <- impute_outliers(ejercicio, "preciom")
ejercicio <- impute_outliers(ejercicio, "areaconst")
# Boxplot para 'preciom' después de la imputación
ggplot(ejercicio, aes(x = zona, y = preciom, fill = tipo)) +
geom_boxplot(outlier.colour = "cyan2", outlier.size = 2) +
labs(caption = "Fig. IV: Boxplot de Precio m2 por Zona.",
x = "Zona", # Etiqueta para el eje X
y = "Precio por Metro Cuadrado") + # Etiqueta para el eje Y
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 6),
axis.text.y = element_text(size = 6),
axis.title.x = element_text(size = 6),
axis.title.y = element_text(size = 6),
legend.title = element_text(size = 6),
legend.text = element_text(size = 6),
plot.caption = element_text(hjust = 0.5, size = 6))
# Boxplot para 'Áreaconst' después de la imputación
ggplot(ejercicio, aes(x = zona, y = areaconst, fill = tipo)) +
geom_boxplot(outlier.colour = "cyan2", outlier.size = 2) +
labs(caption = "Fig. V: Boxplot de Área Construida por Zona.",
x = "Zona", # Etiqueta para el eje X
y = "Área Construida (m2)") + # Etiqueta para el eje Y
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 6),
axis.text.y = element_text(size = 6),
axis.title.x = element_text(size = 6),
axis.title.y = element_text(size = 6),
legend.title = element_text(size = 6),
legend.text = element_text(size = 6),
plot.caption = element_text(hjust = 0.5, size = 6))
# Calcular la correlación solo por zona
correlation_results <- ejercicio %>%
group_by(zona) %>%
summarise(
correlation = cor(preciom, areaconst, use = "complete.obs"),
.groups = "drop" # Para evitar el mensaje de agrupamiento
)
Como se mencionaba antes de la imputación de outliers, la base enviada por la inmobiliaria AyC, no cumple con las variables necesarias para realizar una correcta detección de datos atípicos. El indice de correlación nos explica que los datos imputados tienen menor correlación entre las variables precio y área construida, comparandolo con la base sin imputar.
Teniendo en cuenta los outliers detectados en los boxplots, podemos inferir que aquellos que pertenecen a la variable precio pueden ser inmuebles nuevos y por eso su precio es mayor que otros del mismo estrato o zona. Por otra parte, para los atípicos detectados en área construida, pueden ser inmuebles antiguos de mayor área o que han sido modificados en el tiempo por sus antiguos propietarios. Pero una vez mas, se aclara que estas son inferencias que se hacen con base a los datos, pero que son necesarias mas variables para poder desarrollar correctamente con la base enviada.
Dicho lo anterior, se procede a utilizar la base original para la creación del modelo y desarrollo de la actividad.
# Gráfico de dispersión por zona
ggplot(ejercicio, aes(x = areaconst, y = preciom, color = zona)) +
geom_point(alpha = 0.6) +
labs(x = "Área Construida",
y = "Precio por Metro Cuadrado",
caption = "Fig. VI: Relación Precio m2 y Área Construida.") +
theme_minimal() +
theme(
plot.caption = element_text(hjust = 0.5, size = 6),
legend.text = element_text(size = 6),
legend.title = element_text(size = 6),
axis.title.x = element_text(size = 7),
axis.title.y = element_text(size = 7),
axis.text = element_text(size = 6)
) +
# Agregar el índice de correlación centrado
annotate("text",
x = mean(ejercicio$areaconst, na.rm = TRUE), # Centrar en el eje x
y = max(ejercicio$preciom, na.rm = TRUE) - 0.1 * (max(ejercicio$preciom, na.rm = TRUE) - min(ejercicio$preciom, na.rm = TRUE)), # Ajustar el y
label = paste("Correlación:", round(mean(correlation_results$correlation), 4)),
size = 2, color = "black", hjust = 0.5) # Centrado horizontalmente
ejercicio <- vivienda4
ejercicio <- ejercicio[ejercicio$tipo != "Casa", ]
Una vez realizo el análisis, interpretación y correlación entre variables; procedemos al desarrollo del modelo de regresión simple: \[ \text{precio} = f(\text{área}) + \varepsilon \]
# Crear el modelo de regresión lineal
modelo <- lm(preciom ~ areaconst, data = ejercicio)
# Extraer los resultados del modelo
resultados <- summary(modelo)
# Crear un data frame con los coeficientes y sus estadísticas
coeficientes <- as.data.frame(resultados$coefficients)
# Cambiar la notación científica a formato numérico
coeficientes <- coeficientes %>%
mutate(
Estimate = format(Estimate, scientific = FALSE, digits = 3),
`Std. Error` = format(`Std. Error`, scientific = FALSE, digits = 3),
`t value` = format(`t value`, scientific = FALSE, digits = 3),
`Pr(>|t|)` = format(`Pr(>|t|)`, scientific = FALSE, digits = 3)
)
# Calcular los residuos del modelo
residuos <- residuals(modelo)
shapiro_test <- shapiro.test(residuos)
anderson_test <- ad.test(residuos)
ks_test <- ks.test(residuos, "pnorm", mean = mean(residuos), sd = sd(residuos))
jb_test <- jarque.bera.test(residuos)
# Crear un data frame con los resultados
resultados_normalidad <- data.frame(
Prueba = c("Shapiro-Wilk", "Anderson-Darling", "Kolmogorov-Smirnov", "Jarque-Bera"),
Estadístico = c(round(shapiro_test$statistic, 3),
round(anderson_test$statistic, 3),
round(ks_test$statistic, 3),
round(jb_test$statistic, 3)),
p_value = c(round(shapiro_test$p.value, 3),
round(anderson_test$p.value, 3),
round(ks_test$p.value, 3),
round(jb_test$p.value, 3))
)
# Añadir R-squared, Adjusted R-squared y Residual Standard Error al data frame
rsquared <- data.frame(
Estimate = c(resultados$r.squared, resultados$adj.r.squared, resultados$sigma),
`Std. Error` = c(NA, NA, NA),
`t value` = c(NA, NA, NA),
`Pr(>|t|)` = c(NA, NA, NA),
row.names = c("Multi R-squared", "Adjus R-squared", "R Standard Error")
)
colnames(rsquared) <- colnames(coeficientes)
# Combinar coeficientes y R-squared en un solo data frame
coeficientes <- rbind(coeficientes, rsquared)
kable(coeficientes,
caption = "Resultados del Modelo de Regresión Lineal",
format = "latex",
booktabs = TRUE) %>%
kable_styling(latex_options = c("hold_position"))
Para \(\beta_0 = 200.063\) representa el precio cuando el área construida es igual a 0 metros cuadrados. En este caso, el intercepto expone en este ejemplo que el precio estimado de una vivienda con un área construida de 0 m² es 200.063 millones de pesos.
La ecuación del modelo es:
\[ y = 200.063 + 0.498 \cdot \text{areaconst} \]
Por otro lado, \(\beta_1\) indica que por cada metro cuadrado adicional de área construida, se espera que el precio de la vivienda aumente en 0.498 millones de pesos.
kable(resultados_normalidad, caption = "Resultados de las Pruebas de Normalidad", format = "latex", booktabs = TRUE) %>%
kable_styling(latex_options = c("hold_position"))
El modelo cumple con todos los supuestos importantes de la regresión lineal y tiene un R2 elevado. Esto es explica que el área construida es un predictor importante y que el modelo es robusto en terminos de ajuste a los datos y cumplimiento de los supuestos.
par(mfrow=c(2,2), mar=c(3, 3, 2, 1)) # mar = c(bottom, left, top, right)
cex_val <- 0.7
cex_axis_val <- 0.7
cex_lab_val <- 0.8
cex_main_val <- 0.9
plot(modelo, cex=cex_val, cex.axis=cex_axis_val, cex.lab=cex_lab_val, cex.main=cex_main_val)
El intervalo de confianza para la pendiente \(\beta_1\) se puede interpretar como : Por cada metro adicional de área construida, el precio del inmueble aumenta entre 0.4817357 y 0.515097 millones de pesos, con una confianza del 95%
resultado_kable <- kable(confint(modelo),
caption = "Intervalos de Confianza Coeficientes del Modelo",
format = "latex",
booktabs = TRUE)
resultado_kable
Para estimar el precio de un apartamento con una área de 110 m2, la ecuación lineal resultante de la regresión es: \[ \hat{y} = 200,063 + 0,498(110) = 254,843 \] Por lo anterior se concluye que bajo la ecuación lineal del modelo de regresión se estima que para un apartamento de 110 metros cuadrados el precio promedio es de 254,843 millones de pesos COP.
Para un \(y = \lambda x + \epsilon\) cercano a 1, lo que implica que los datos no requieren una transformación severa.
library(MASS)
##
## Adjuntando el paquete: 'MASS'
## The following object is masked from 'package:dplyr':
##
## select
par(cex = 0.6)
# Graficar boxcox
boxcox(lm(preciom ~ areaconst, data = ejercicio))
par(cex = 1)
modelo2 <- lm(log(preciom) ~ areaconst, data = ejercicio)
modelo3 <- lm(preciom ~ log(areaconst), data = ejercicio)
modelo4 <- lm(log(preciom) ~ log(areaconst), data = ejercicio)
Se implementan los modelos lin-lin, log-lin, lin-log, log-log.El primero es el mejor entre los 5 modelos porque tiene mayor R2, esto nos demuestra el resultado del boxcox, donde según la lógica al aproximarse a ser 1, no necesitaba transformación severa.
stargazer::stargazer(modelo,modelo2,modelo3,modelo4, type="text",df=FALSE)
##
## =======================================================================
## Dependent variable:
## ---------------------------------------------------
## preciom log(preciom) preciom log(preciom)
## (1) (2) (3) (4)
## -----------------------------------------------------------------------
## areaconst 0.498*** 0.002***
## (0.009) (0.00004)
##
## log(areaconst) 42.878*** 0.174***
## (0.794) (0.003)
##
## Constant 200.063*** 5.318*** 53.820*** 4.723***
## (0.670) (0.003) (3.409) (0.014)
##
## -----------------------------------------------------------------------
## Observations 1,363 1,363 1,363 1,363
## R2 0.716 0.696 0.682 0.674
## Adjusted R2 0.716 0.695 0.682 0.674
## Residual Std. Error 7.081 0.030 7.496 0.031
## F Statistic 3,435.808*** 3,110.029*** 2,919.088*** 2,814.311***
## =======================================================================
## Note: *p<0.1; **p<0.05; ***p<0.01
El análisis de mercado a la inmobiliaria AyC, evidenció que las zonas con los inmuebles mas costozos fueron la centro y oriente con promedio de precios de 256.37 millones y 240.39 millones respectivamente, el mayor numero de ofertas se encuentran en la zonas sur y norte con 1065 y 237. La zona con mayor promedio de área construida es la zona centro con 107.71 metros cuadrados.
El modelo de regresión lineal confirma una relación positiva entre el área construida y el precio de las viviendas. Por cada metro cuadrado adicional, el precio aumenta en promedio 0,498 millones de pesos, la medida del R2 es alta, lo que indica que es un modelo fiable para su uso en la predicción de precios de inmuebles, según el área en metros cuadrdos.
Por ultimo, el precio estimado para una vivienda de 110 metros cuadrados es de 254,843 millones de pesos COP.