Problema

Con base en los datos de ofertas de vivienda descargadas del portal Fincaraiz para apartamento de estrato 4 con área construida menor a 200 m2 (vivienda4.RDS) la inmobiliaria A&C requiere el apoyo de un cientifico 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

  1. Realice un análisis exploratorio de las variables precio de vivienda (millones de pesos COP) y área de la vivienda (metros cuadrados) - incluir gráficos e indicadores apropiados interpretados.

Rta./

#Importamos los datos

library(devtools)
## Loading required package: usethis
devtools::install_github("dgonxalex80/paqueteMETODOS")
## Skipping install of 'paqueteMETODOS' from a github remote, the SHA1 (9696ffdc) has not changed since last install.
##   Use `force = TRUE` to force installation
library(paqueteMETODOS)
## Loading required package: cubature
## Loading required package: GGally
## Loading required package: ggplot2
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
## Loading required package: MASS
## Loading required package: summarytools
## Loading required package: psych
## 
## Attaching package: 'psych'
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
## Loading required package: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.3     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ lubridate 1.9.2     ✔ tibble    3.2.1
## ✔ purrr     1.0.1     ✔ tidyr     1.3.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ psych::%+%()    masks ggplot2::%+%()
## ✖ psych::alpha()  masks ggplot2::alpha()
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ✖ dplyr::select() masks MASS::select()
## ✖ tibble::view()  masks summarytools::view()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
data(vivienda4)

Analisis exploratorio

str(vivienda4) 
## spc_tbl_ [1,706 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ zona     : Factor w/ 5 levels "Zona Centro",..: 2 2 2 5 2 2 2 2 2 2 ...
##  $ estrato  : Factor w/ 4 levels "3","4","5","6": 2 2 2 2 2 2 2 2 2 2 ...
##  $ preciom  : num [1:1706] 220 600 320 290 220 305 220 162 225 370 ...
##  $ areaconst: num [1:1706] 52 160 108 96 82 117 75 60 84 117 ...
##  $ tipo     : Factor w/ 2 levels "Apartamento",..: 1 2 1 1 1 2 1 1 1 1 ...

El dataset nos muestra 1706 registros con 5 variables a saber : zona, estrato, preciom, areaconst, y tipo

summary(vivienda4)
##            zona      estrato     preciom        areaconst     
##  Zona Centro :   8   3:   0   Min.   : 78.0   Min.   : 40.00  
##  Zona Norte  : 288   4:1706   1st Qu.:160.0   1st Qu.: 60.00  
##  Zona Oeste  :  60   5:   0   Median :210.0   Median : 75.00  
##  Zona Oriente:   6   6:   0   Mean   :225.4   Mean   : 87.63  
##  Zona Sur    :1344            3rd Qu.:265.0   3rd Qu.: 98.00  
##                               Max.   :760.0   Max.   :200.00  
##           tipo     
##  Apartamento:1363  
##  Casa       : 343  
##                    
##                    
##                    
## 

La función nos ofrece resumen de resultados, indicando la siguiente información importante:

Ahora veamos algunos indicadores estadísticos:

vivienda4|> summarise(media = mean(preciom),
                      varianza = var(preciom),
                      desviación = sd(preciom),
                      Q1 = quantile(preciom, probs=0.25),
                      P90 = quantile(preciom, probs=0.90))
## # A tibble: 1 × 5
##   media varianza desviación    Q1   P90
##   <dbl>    <dbl>      <dbl> <dbl> <dbl>
## 1  225.    7376.       85.9   160   340

Podemos observar que el preciom medio es 225millones, con desviación estandar de 85.88 y un primer cuartil de 160m y un percentil 90 de 340m que nos indica que el 90% de las viviendas el precio será inferior a 340m.

vivienda4|> summarise(media = mean(areaconst),
                      varianza = var(areaconst),
                      desviación = sd(areaconst),
                      Q1 = quantile(areaconst, probs=0.25),
                      D4 = quantile(areaconst, probs=0.40),
                      P90 = quantile(areaconst, probs=0.90))
## # A tibble: 1 × 6
##   media varianza desviación    Q1    D4   P90
##   <dbl>    <dbl>      <dbl> <dbl> <dbl> <dbl>
## 1  87.6    1321.       36.3    60    70  144.

Podemos observar que el área constrsuida media es de 87.62metros, con desviación estandar de 36.34. Un primer cuartil de 60metros, un cuantil 0.40 de 70 metros y un percentil 90 de 144.5m que nos indica que el 90% de las viviendas el área construida esta por debajo de 144.5metros.

Ahora veamoslo en histogramas una distribución similar que puede significar correlación:

#Definamos primero variables que usaremos en adelante:
area = vivienda4$areaconst
precio = vivienda4$preciom

#Graficamos precio
hist(precio, main = "Precio vivienda Finca Raiz", xlab = "Valor en Millones", col = "green")

#Graficamos área construida
hist(area, main = "Área construida vivienda Finca Raiz", xlab = "Medida en Metros Cuadrados", col = "green")

  1. Realice un análisis exploratorio bivariado de datos, enfocado en la relación entre la variable respuesta (precio) en función de la variable predictora (area construida) - incluir gráficos e indicadores apropiados interpretados.

Rta./ Para esto usamos la librería Plot

plot(area,precio,xlab = "Área construida (en metros cuadrados)", ylab = "Precio (en millones)", main = "Análisis Exploratorio Bivariado")

Como podemos observar en este gráfico, la dispersión nos indica que hay una relación lineal positiva. Lo que podemos validar nuevamente utilizando la función de correlación:

cor(area,precio)
## [1] 0.7630166
  1. Estime el modelo de regresión lineal simple entre precio=f(area)+ε. Interprete los coeficientes del modelo β0, β1 en caso de ser correcto.

Rta./

model=lm(precio ~ area)
summary(model)
## 
## Call:
## lm(formula = precio ~ area)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -195.86  -31.95   -8.95   27.87  431.17 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   67.381      3.510   19.20   <2e-16 ***
## area           1.803      0.037   48.73   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 55.53 on 1704 degrees of freedom
## Multiple R-squared:  0.5822, Adjusted R-squared:  0.5819 
## F-statistic:  2374 on 1 and 1704 DF,  p-value: < 2.2e-16

Creemos un gráfico de dispersión y añadamos una línea de regresión lineal

plot(area, precio, xlab = "Área construida", ylab= "Precio", main = "Prueba de Regresión Lineal")

abline(model, col ="green")

Por el modelo creado, podemos establecer que el intercepto ó β0 es 67.3 y el β1 es 1.8. Lo anterior nos indica que el precio es de 67.3millones y que por cada metro construido, el precio aumentará 1.8 millones.

  1. Construir un intervalo de confianza (95%) para el coeficiente β1, interpretar y concluir si el coeficiente es igual a cero o no. Compare este resultado con una prueba de hipótesis t.

Rta./

par(mfrow=c(2,2))
plot(model)

confint(model, level = 0.95)
##                 2.5 %    97.5 %
## (Intercept) 60.496208 74.265055
## area         1.730404  1.875547

Usando la función confint del paquete stats pudimos construir el intervalo de confianza de 95% observando que la pendiente β1 se situa entre 1.73 y 1.87, es decir que a cada metro el precio del mismo aumenta entre 1.73 y 1.87. De igual forma, como tanto β0 y β1 difieren de cero, se rechaza la hipotesis nula y acepta la alterna.

  1. Calcule e interprete el indicador de bondad R2.

Rta./

model=lm(precio ~ area)
summary(model)
## 
## Call:
## lm(formula = precio ~ area)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -195.86  -31.95   -8.95   27.87  431.17 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   67.381      3.510   19.20   <2e-16 ***
## area           1.803      0.037   48.73   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 55.53 on 1704 degrees of freedom
## Multiple R-squared:  0.5822, Adjusted R-squared:  0.5819 
## F-statistic:  2374 on 1 and 1704 DF,  p-value: < 2.2e-16

Como ya vimos cuando creamos el modelo, encontramos que el coeficiente de determinación multiple es:

Multiple R-squared:  0.5822

y el coeficiente de determinación ajustado es:

Adjusted R-squared:  0.5819

Esto nos indica que el precio de los apartamentos se explica en un 58.22% por el área de construcción de cada uno. Este número tambien nos indica que existen otros factores que influyen en el precio final de cada apartamento.

  1. ¿Cuál sería el precio promedio estimado para un apartamento de 110 metros cuadrados? Considera entonces con este resultado que un apartamento en la misma zona con 110 metros cuadrados en un precio de 200 millones sería una atractiva esta oferta? ¿Qué consideraciones adicionales se deben tener?.

Rta./

metraje = 110  #Área deseada
datos_prediccion = data.frame(area = metraje)
precio = predict(model, newdata = datos_prediccion)
print(precio)
##        1 
## 265.7079

El precio que arroja la predicción es de 265millones para un apartamento de 110 metros cuadrados.

Considero que es una buena oferta, ya que por 200millones la predicción nos dice que le alcanzaría para solo 73-74 metros cuadrados.

De igual forma recordemos que el Multiple R-squared explica en un 58.22% el precio. Existen otros factores que pueden intervenir.

  1. Realice la validación de los supuestos del modelo por medio de gráficos apropiados, interpretarlos y sugerir posibles soluciones si se violan algunos de ellos. Utilice las pruebas de hipótesis para la validación de supuestos y compare los resultados con lo observado en los gráficos asociados.

Rta./

residuals = model$residuals
hist(residuals, main = "Histograma de residuos del modelo",col="green" )

qqnorm(residuals)
qqline(residuals,col="green")

Linealidad:

De acuerdo a estas gráficas, podemos presumir que hay una relación lineal entre los metros de área construida y el precio de la vivienda.

par(mfrow=c(2,2))
plot(model)

Normalidad:

Como no conocemos la media y la varianza del modelo, se usa el test de Lilliefors, que nos rechazan la hipotesis nula indicando que los datos no tienen una distribución normal.

install.packages("nortest") # Recordar instalar nortest
library(nortest)
lillie.test(residuals)
## 
##  Lilliefors (Kolmogorov-Smirnov) normality test
## 
## data:  residuals
## D = 0.077968, p-value < 2.2e-16

Autocorrelación:

Al realizar un test de Durbin-Watson podemos darnos cuenta que la correlación es positiva.

lmtest::dwtest(model)
## 
##  Durbin-Watson test
## 
## data:  model
## DW = 1.6713, p-value = 5.124e-12
## alternative hypothesis: true autocorrelation is greater than 0

Homocedasticidad:

res.estudentizados <- studres(model) #cálculo de residuos estudentizados
plot(model$fitted.values, res.estudentizados, ylab = "Residuos Estudentizados", xlab = "Valores Ajustados")
abline(h = 0, lty = 2)

Ahora ejecutemos la prueba de Breusch-Pagan

library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(lmtest)
bptest(model)
## 
##  studentized Breusch-Pagan test
## 
## data:  model
## BP = 152.8, df = 1, p-value < 2.2e-16

Siendo 152.8 nos indica que hay diferencia entre el modelo que asume homocedasticidad y el modelo que permite heterocedasticidad, y siendo p un valor muy bajo casi cero, podemos decir que no satisface la suposición de Homocedasticidad lo que puede significar que las varianzas de los errores no es constante y que toque aplicar transformaciones.

  1. De ser necesario realice una transformación apropiada para mejorar el ajuste y supuestos del modelo.

Rta./

Cómo vimos en el punto 7, si es necesario aplicar transformaciones para tratar la heterocedasticidad en los datos.

Lo haremos usando la librería MASS

model=lm(vivienda4$preciom ~ vivienda4$areaconst) # necesario aplicarse a la variable de respuesta original, sino fallara boxcox

library(MASS)
bc= boxcox(model)

plot(bc)

Ahora encontremos el valor óptimo de lambda

lambda=bc $x [which.max(bc$y)]
lambda
## [1] -0.1010101

Este valor bajo nos sugiere que no es una transformación simple. Podemos usarlo para aplicar la transformación de boxcox

model2 <- lm (((bc$ x ^ lambda-1) / lambda) ~ bc$y)
model2
## 
## Call:
## lm(formula = ((bc$x^lambda - 1)/lambda) ~ bc$y)
## 
## Coefficients:
## (Intercept)         bc$y  
##  -11.253062    -0.002625

Ahora veamos el resumen de nuestro nuevo modelo (model2)

summary(model2)
## 
## Call:
## lm(formula = ((bc$x^lambda - 1)/lambda) ~ bc$y)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.5535 -0.2499  0.2295  0.5074  0.5976 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -1.125e+01  1.503e+00  -7.485 1.33e-09 ***
## bc$y        -2.625e-03  3.609e-04  -7.274 2.80e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.7634 on 48 degrees of freedom
##   (50 observations deleted due to missingness)
## Multiple R-squared:  0.5243, Adjusted R-squared:  0.5144 
## F-statistic: 52.91 on 1 and 48 DF,  p-value: 2.8e-09

R2 disminuye de 58.2% a 52% pero p-value sigue siendo signficativo con un p-value <0.05

  1. De ser necesario compare el ajuste y supuestos del modelo inicial y el transformado.

    Rta./

  1. Estime varios modelos y compare los resultados obtenidos. En el mejor de los modelos, ¿se cumplen los supuestos sobre los errores?

    Rta./

  1. Con los resultados obtenidos construya un informe para los directivos de la inmobiliaria, indicando el modelo apropiado y sus principales características. A este informe se deben añadir los anexos como evidencia de la realización de los pasos anteriores.

    Rta./