Situación:

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.

knitr::opts_chunk$set(echo = TRUE)
library(devtools)
devtools::install_github("dgonxalex80/paqueteMETODOS")
library(paqueteMETODOS)
data(vivienda)
# Cargo las librerías:

library(paqueteMODELOS)
library(dplyr)
library(stats)
library(naniar)
library(ggplot2)
library(mice)
library(corrplot)
library(ggsignif)
library(factoextra)
library(GGally)

# Cargo el dataset:
data("vivienda")

1. División de datos y Análisis Explorarorio Univariado:

Realice un filtro a la base de datos e incluya solo las ofertas de : base1: casas, de la zona norte de la ciudad. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta.

Para resolver esto, primero identificamos el número de viviendas por tipo, el número de viviendas por tipo y zona y dividimos el dataset por tipo de vivienda:

table (vivienda$tipo)
## 
## Apartamento        Casa 
##        5100        3219
table (vivienda$tipo, vivienda$zona)
##              
##               Zona Centro Zona Norte Zona Oeste Zona Oriente Zona Sur
##   Apartamento          24       1198       1029           62     2787
##   Casa                100        722        169          289     1939
casa <- subset(vivienda, vivienda$tipo == "Casa")
summary(casa)
##        id           zona               piso              estrato     
##  Min.   :   1   Length:3219        Length:3219        Min.   :3.000  
##  1st Qu.:1856   Class :character   Class :character   1st Qu.:3.000  
##  Median :4190   Mode  :character   Mode  :character   Median :5.000  
##  Mean   :3963                                         Mean   :4.485  
##  3rd Qu.:5862                                         3rd Qu.:5.000  
##  Max.   :8319                                         Max.   :6.000  
##                                                                      
##     preciom       areaconst       parqueaderos       banios      
##  Min.   :  77   Min.   :  30.0   Min.   : 1.00   Min.   : 0.000  
##  1st Qu.: 300   1st Qu.: 154.0   1st Qu.: 1.00   1st Qu.: 3.000  
##  Median : 430   Median : 240.0   Median : 2.00   Median : 4.000  
##  Mean   : 540   Mean   : 273.4   Mean   : 2.29   Mean   : 3.894  
##  3rd Qu.: 670   3rd Qu.: 350.0   3rd Qu.: 3.00   3rd Qu.: 5.000  
##  Max.   :1999   Max.   :1745.0   Max.   :10.00   Max.   :10.000  
##                                  NA's   :733                     
##   habitaciones       tipo              barrio             longitud     
##  Min.   : 0.00   Length:3219        Length:3219        Min.   :-76.59  
##  1st Qu.: 3.00   Class :character   Class :character   1st Qu.:-76.54  
##  Median : 4.00   Mode  :character   Mode  :character   Median :-76.53  
##  Mean   : 4.61                                         Mean   :-76.53  
##  3rd Qu.: 5.00                                         3rd Qu.:-76.52  
##  Max.   :10.00                                         Max.   :-76.46  
##                                                                        
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.383  
##  Median :3.413  
##  Mean   :3.415  
##  3rd Qu.:3.449  
##  Max.   :3.496  
## 

Se puede observar que el dataset viviendas contiene información de 3219 casas, 722 de ellas se ubican en la zona Norte. La única variable que tiene datos nulos es parqueadero, la manejaremos al dividir de nuevo el dataset solo para casas de la zona norte.

casasN <- subset (casa, casa$zona=="Zona Norte") 

summary(casasN)
##        id             zona               piso              estrato     
##  Min.   :  58.0   Length:722         Length:722         Min.   :3.000  
##  1st Qu.: 766.2   Class :character   Class :character   1st Qu.:3.000  
##  Median :2257.0   Mode  :character   Mode  :character   Median :4.000  
##  Mean   :2574.6                                         Mean   :4.202  
##  3rd Qu.:4225.0                                         3rd Qu.:5.000  
##  Max.   :8319.0                                         Max.   :6.000  
##                                                                        
##     preciom         areaconst       parqueaderos        banios      
##  Min.   :  89.0   Min.   :  30.0   Min.   : 1.000   Min.   : 0.000  
##  1st Qu.: 261.2   1st Qu.: 140.0   1st Qu.: 1.000   1st Qu.: 2.000  
##  Median : 390.0   Median : 240.0   Median : 2.000   Median : 3.000  
##  Mean   : 445.9   Mean   : 264.9   Mean   : 2.182   Mean   : 3.555  
##  3rd Qu.: 550.0   3rd Qu.: 336.8   3rd Qu.: 3.000   3rd Qu.: 4.000  
##  Max.   :1940.0   Max.   :1440.0   Max.   :10.000   Max.   :10.000  
##                                    NA's   :287                      
##   habitaciones        tipo              barrio             longitud     
##  Min.   : 0.000   Length:722         Length:722         Min.   :-76.59  
##  1st Qu.: 3.000   Class :character   Class :character   1st Qu.:-76.53  
##  Median : 4.000   Mode  :character   Mode  :character   Median :-76.52  
##  Mean   : 4.507                                         Mean   :-76.52  
##  3rd Qu.: 5.000                                         3rd Qu.:-76.50  
##  Max.   :10.000                                         Max.   :-76.47  
##                                                                         
##     latitud     
##  Min.   :3.333  
##  1st Qu.:3.452  
##  Median :3.468  
##  Mean   :3.460  
##  3rd Qu.:3.482  
##  Max.   :3.496  
## 

En la zona Norte, las casas pertenecen al estrato 3 al 6, el 25% de ellas en el estrato 5 y 6. Los precios varían entre 89 y 1949 millones y el área construída va desde 30 hasta 1440 metros cuadrados. Hay 287 parqueaderos con NA, asumimos que corresponden a casas con 0 apartamentos dado que el número mínimo de parqueaderos no comprende el cero, por lo tanto, imputamos los NA por 0:

grafico <- md.pattern(casasN, rotate.names = TRUE)

Ajustamos la variable parqueadero:

casasN$parqueaderos[is.na(casasN$parqueaderos)]<-0
summary(casasN$parqueaderos)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.000   0.000   1.000   1.314   2.000  10.000

La variable piso también tiene NA, por lo tanto identificamos estadísticos descriptivos inicialmente, sin embargo, parece que la está reconociendo como texto, por lo que primero la hacemos numérica:

casasN$piso <- as.numeric(as.character(casasN$piso))
str(casasN$piso)
##  num [1:722] 2 2 2 2 2 2 2 3 NA NA ...
summary(casasN$piso)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   1.000   2.000   2.000   1.994   2.000   7.000     372

Podemos observar que hay 372 datos NA. la media y la mediana están muy próximas, por lo que reemplazaremos los NA por 2.

casasN$piso[is.na(casasN$piso)]<-2
summary(casasN$piso)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   1.000   2.000   2.000   1.997   2.000   7.000

Los pisos van de 1 a 7, el 75% es de dos pisos. Llama la atención el valor máximo, podría ser un dato outlier.

Ahora confirmamos que ya no hay datos NA:

grafico2 <- md.pattern(casasN, rotate.names = TRUE)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

table(casasN$zona)
## 
## Zona Norte 
##        722
table(casasN$tipo)
## 
## Casa 
##  722

Dado que verificamos que todas las casas pertenecen a la zona norte y que el tipo es casa, eliminamos esta variable del dataset, dado que tampoco aportará al modelo posterior, así como la variable id.

casasN <- subset(casasN, select = -c(id, zona, tipo))
head(casasN)
par(mfrow = c(1, 2))
boxplot(casasN$preciom, main = "Precio de las casas", col = "#13B3C1")
boxplot(casasN$areaconst, main = "Área construida de las casas", col ="#FE3F75")

boxplot(casasN$estrato, main = "Estrato de las casas", col ="#66ADA4")
boxplot(casasN$banios, main = "Baños de las casas", col ="#FFFF00")

boxplot(casasN$habitaciones, main = "Habitaciones de las casas", col ="#808000")
boxplot(casasN$piso, main = "Pisos de las casas", col ="#fc4b08")

Observando los gráficos de cajas y bigotes identificamos las variables que tienen datos que podrían considerarse outlier dado que cuentan con puntos de datos que sobresalen de los bigotes: precio, área, baños, habitaciones y pisos.

Por otro lado, como ya conocemos, La “caja” representa el rango intercuartílico (IQR), que abarca desde el primer cuartil (Q1, el 25% de los datos) hasta el tercer cuartil (Q3, el 75% de los datos). La mediana es la línea media en la caja.

Verificamos la normalidad de los datos:

shapiro.test(casasN$preciom)
## 
##  Shapiro-Wilk normality test
## 
## data:  casasN$preciom
## W = 0.86297, p-value < 2.2e-16
shapiro.test(casasN$areaconst)
## 
##  Shapiro-Wilk normality test
## 
## data:  casasN$areaconst
## W = 0.86559, p-value < 2.2e-16
shapiro.test(casasN$estrato)
## 
##  Shapiro-Wilk normality test
## 
## data:  casasN$estrato
## W = 0.83838, p-value < 2.2e-16
shapiro.test(casasN$banios)
## 
##  Shapiro-Wilk normality test
## 
## data:  casasN$banios
## W = 0.93292, p-value < 2.2e-16
shapiro.test(casasN$habitaciones)
## 
##  Shapiro-Wilk normality test
## 
## data:  casasN$habitaciones
## W = 0.90995, p-value < 2.2e-16

Con los datos de la prueba de Shapiro para todas las variables, con valores p-value < 2.2e-16, no rechazamos la hipótesis nula y confirmamos que ninguna de las variables tiene una distribución normal.

2. Correlación entre variables:

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, número de baños, número de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.

El enunciado hace referencia a una correlación con zona, sin embargo, ya sabemos que todas las casas se encuentran en la zona norte, por lo cual no lo tendremos en cuenta.

Realizamos un mapa de calor de correlación:

library(plotly)
library(reshape2)

#Selecciono solo las variables que requiero:
casasN_numericas <- select(casasN, preciom, areaconst, estrato, banios, habitaciones)

# Calculo la matriz de correlación
correlaciones <- cor(casasN_numericas)

# Creo un gráfico de mapa de calor:
p <- ggplot(melt(correlaciones), aes(Var1, Var2, fill=value)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", 
                       midpoint = 0, limit = c(-1,1), space = "Lab", 
                       name="Correlación") +
  theme_minimal() + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  coord_fixed()

# Convierto el gráfico de ggplot2 a un gráfico interactivo de Plotly
ggplotly(p)

El gráfico interactivo permite identificar por color, los rojos más intensos son los que tienen la mayor correlación, los presenta en orden de mayor a menor. Al pasar el cursor sobre los cuadrados, se observa la medida de correlación, en el gráfico todas son positivas.

La correlación más fuerte se da entre precio y área construída con un valor de 0.73, indica que a mayor área construída, más cuesta una vivienda. En segundo lugar se encuentran las correlaciones moderadas, aquí está el estrato con un valor de 0.61, a mayor estrato, mayor es el precio de la vivienda y los baños con un valor de 0.52. Hay una correlación débil de 0.32 con el número de baños de la vivienda.

Otra correlació positiva moderada entre dos variables predictoras se observa entre habitaciones y baños (0.57), teniendo en cuenta que esta correlación es moderada, pensaría que el riesgo de multicolinealidad es bajo y no influiría demasiado en la interpretación precisa de cómo cada variable afecta el precio, se tendrá en cuenta los Factores de Inflación de la Varianza (VIF) cuando se genere el modelo.

La relación entre las demás variables (sin tener en cuenta el precio) es debil, la más débil de todas se da entre estrato y habitaciones (0.1)

Esto se puede visualizar también:

ggpairs(casasN_numericas[,1:5], title="Asociación entre las variables")

En la gráfica anterior se identifican los gráficos de dispersión que se relacionan con las correlaciones calculadas y descritas previamente, se presenta la correlación para cada pareja de variables. Como ya se evaluó la normalidad de las variables, también se puede confirmar en la gráfica de densidad que los datos no se distribuyen de manera normal.

3. Modelo de Regresión Lineal Múltiple:

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 R^2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).

Una casa puede tener cero baños y cero habitaciones, sin embargo, un área construída de 0 no es coherente y en este grupo de viviendas, no tenemos estrato 0, por lo cual centro estas dos variables para facilitar la interpretación. La mediana de estrato es estrato 4 y la del área construída de las viviendas es de 264 metros cuadrados.

# Centro las variables área y estrato:

areac <- casasN$areaconst - mean(casasN$areaconst)
estratoc <- casasN$estrato - mean(casasN$estrato)

# Corro los modelos probando cómo van cambiando los resultados a medida que agregamos variables:

modelo1 <- lm(preciom ~ areac + banios, data = casasN_numericas) #Pruebo un primer modelo solo con dos variables
modelo2 <- lm(preciom ~ areac + banios + estratoc, data = casasN_numericas) # Pruebo un segundo modelo adicionando una tercera variable
modelo3 <- lm(preciom ~ areac + banios + estratoc + habitaciones, data = casasN_numericas) # y pruebo el tercer modelo con todas las variables sugeridas.

#Imprimo los resultados de los modelos:

summary (modelo1)
## 
## Call:
## lm(formula = preciom ~ areac + banios, data = casasN_numericas)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1268.65   -88.10   -25.12    48.49   993.77 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 298.61047   18.29620  16.321   <2e-16 ***
## areac         0.99930    0.04386  22.786   <2e-16 ***
## banios       41.42861    4.81094   8.611   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 174.5 on 719 degrees of freedom
## Multiple R-squared:  0.5784, Adjusted R-squared:  0.5772 
## F-statistic: 493.1 on 2 and 719 DF,  p-value: < 2.2e-16
summary (modelo2)
## 
## Call:
## lm(formula = preciom ~ areac + banios + estratoc, data = casasN_numericas)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -958.78  -79.28  -18.28   49.58 1075.72 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 347.53561   17.14123  20.275  < 2e-16 ***
## areac         0.82806    0.04234  19.556  < 2e-16 ***
## banios       27.66782    4.52501   6.114 1.59e-09 ***
## estratoc     85.26855    6.99365  12.192  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 158.9 on 718 degrees of freedom
## Multiple R-squared:  0.6507, Adjusted R-squared:  0.6492 
## F-statistic: 445.8 on 3 and 718 DF,  p-value: < 2.2e-16
summary (modelo3)
## 
## Call:
## lm(formula = preciom ~ areac + banios + estratoc + habitaciones, 
##     data = casasN_numericas)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -961.17  -79.37  -17.71   49.14 1072.88 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  344.96060   19.19606  17.970   <2e-16 ***
## areac          0.82516    0.04346  18.986   <2e-16 ***
## banios        26.82962    5.32670   5.037    6e-07 ***
## estratoc      85.77820    7.20303  11.909   <2e-16 ***
## habitaciones   1.23258    4.12582   0.299    0.765    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 159 on 717 degrees of freedom
## Multiple R-squared:  0.6507, Adjusted R-squared:  0.6488 
## F-statistic:   334 on 4 and 717 DF,  p-value: < 2.2e-16

Con los datos obtenidos anateriormente, tenemos que el intercepto es el valor que representa el precio estimado cuando todas las variables independientes son 0. En los diferentes modelos se observa que cuando área es de 264 metros y baños son 0, el precio sería de 298.6 millones. Si área fuera 264 metros, baños 0 y estrato fueran 4, el precio sería de 347.53561 millones y cuando área fuera de 264 metros, baños 0, estrato 4 y habitaciones fueran 0, el precio sería de 344.96060 millones.

Modelo 1:

  • Si se mantiene constante el número de baños, por cada metro adicional construído, el precio aumentaría 0.9993. o redondeando, 0,1 millones

  • Manteniendo constante el área construída, por cada baño que se aumente, el precio aumentaría 41.4286 millones.

El valor p es menor de 0.05 e indica que el modelo en general es estadísticamente significativo. El R cuadrado ajustado de 5.77 significa que al rededor del 57,8% de la Variación en el precio es explicada por las variables área construída y baño.

Modelo 2:

  • Por cada metro adicional en el área de construcción, se espera que el precio de las casas aumente en promedio 0.8281 millones, manteniendo constantes las demás variables.

  • Con las demás variables constantes, por cada baño adicional, se espera que el precio aumente en promedio 27.6678 millones.

  • Por cada aumento de un estrato, se espera que el precio aumente en promedio 85.2685 millones, manteniendo constantes las demás variables.

Este segundo modelo, adicionando la variable estrato, sigue siendo estadísticamente significativo con un p <0.05. Este modelo explica el 65.1% de la variación en el precio por las variables área construída, baños y estrato.

Modelo 3:

  • Por cada metro adicional en el área de construcción, se espera que el precio aumente en promedio 0.8252 millones, manteniendo constantes las demás variables.

  • Por cada baño adicional, se espera que el precio aumente en promedio 26.8296 millones. manteniendo las demás variables constantes.

  • Por cada aumento de un estrato, se espera que el precio aumente en promedio 85.7782 millones, manteniendo constantes las demás variables.

  • Con todas las demás variables constantes, Por cada habitación adicional, se espera que el precio aumente en promedio 1.2326 millones.

Comparado con los dos modelos anteriores, en este modelo se adiciona la variable número de habitaciones y es estadísticamente significativo en general. Este modelo, igual que el anterior, a pesar de adicionar una variable nueva, sigue explicando el 65.1% de la variación en el precio por las variables área construída, baños, estrato y habitaciones.

Es decir, que la variable habitaciones no sumó en la explicación de la variación de los precios de las casas.

Dado lo anterior, seguiré considerando el modelo 2.

Intervalos de confianza para los coeficientes del modelo2:

intervalos_confianza <- confint(modelo2)
print(intervalos_confianza)
##                   2.5 %     97.5 %
## (Intercept) 313.8826886 381.188539
## areac         0.7449247   0.911186
## banios       18.7839797  36.551655
## estratoc     71.5381012  98.998995

Los intervalos muestran el rango dentro del cual se espera que se encuentren los verdaderos coeficientes del modelo el 95% de las veces (asumiendo que el 2.5% y el 97.5% representan los límites de un intervalo de confianza del 95%).

  • Si área fuera 264 metros, baños o y estrato fueran 4, el precio variaría entre 313.88268 y 381.18853 millones.

  • Por cada metro adicional en el área de construcción, se espera que el precio de las casas aumente entre 0.744 y 0.9111 millones, manteniendo constantes las demás variables.

  • Con las demás variables constantes, por cada baño adicional, se espera que el precio aumente entre 18.7839 y 36.5516 millones.

  • Por cada aumento de una unidad en el estrato, se espera que el precio aumente entre 71.5381 y 98.9989 millones, manteniendo constantes las demás variables.

Prueba de hipótesis para los coeficientes del modelo2:

prueba_hipotesis <- summary(modelo2)$coef[, c("Estimate", "Pr(>|t|)")]
print(prueba_hipotesis)
##                Estimate     Pr(>|t|)
## (Intercept) 347.5356139 1.300537e-72
## areac         0.8280554 1.346181e-68
## banios       27.6678172 1.590614e-09
## estratoc     85.2685481 3.282145e-31

El valor p asociado con cada coeficiente prueba la hipótesis nula de que el coeficiente es igual a cero (lo que implica que la variable no tiene efecto) contra la hipótesis alternativa de que el coeficiente no es igual a cero (indicando que la variable tiene un efecto significativo).

Los resultados indican que todos los predictores son estadísticamente significativos, es decir que tienen un efecto significativo sobre el precio de las viviendas. El área construída, los baños y el estrato son factores relevantes para considerar en la predicción del precio de las viviendas.

4. Validación de supuestos en los errores:

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).

  • Normalidad de los errores: Los errores son variables aleatorias normales.

  • Modelo completo: Los errores tienen media cero.

  • Homoscedasticidad: Los errores tienen varianza constante.

  • No autocorrelación de errores: Los errores son mutuamente independientes.

Normalidad de los errores:

Para validar la normalidad de los errores, se puede realizar de forma gráfica mediante un Q-Q plot:

library(plotly)

# residuos estandarizados:
residuos_est <- rstandard(modelo2)

# Cuantiles teóricos y los residuos ordenados para el gráfico Q-Q
qq_datos <- qqnorm(residuos_est, plot.it = FALSE)

# Calculo la línea teórica Obteniendo los coeficientes (intercepto y pendiente) de la regresión de los cuantiles teóricos sobre los residuos estandarizados
coeficientes <- coef(lm(qq_datos$y ~ qq_datos$x))

# línea teórica basada en los cuantiles teóricos:
linea_x <- qq_datos$x
linea_y <- coeficientes[1] + coeficientes[2] * linea_x

# Q-Q plot
qq_plot <- plot_ly() %>%
  add_trace(x = qq_datos$x, y = qq_datos$y, type = 'scatter', mode = 'markers', name = 'Residuos') %>%
  add_trace(x = linea_x, y = linea_y, type = 'scatter', mode = 'lines', name = 'Línea teórica')

qq_plot

Observando el gráfico Q-Q, se observa los puntos al inicio y al final no se ajustan a la línea recta diagonal, por lo que se concluye que los residuales del modelo no se ajustan a una distribución normal, sin embargo, es posible confirmarlo mediante una prueba estadística de Shapiro-Wilk:

residuos <- resid(modelo2)
shapiro_test <- shapiro.test(residuos)
print(shapiro_test)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuos
## W = 0.83689, p-value < 2.2e-16

Con el resultado de la prueba de Shapiro W = 0.83689, p-value < 2.2e-16, se confirma que los residuales no siguen una distribución normal en el modelo.

Este supuesto no se cumple

Modelo completo:

Para validar que los errores tengan una media de 0, se puede realizar un gráfico de residuos vs. valores ajustados. En este gráfico, si los residuos se distribuyen aleatoriamente alrededor de la línea horizontal en cero, sin mostrar patrones discernibles, es una buena indicación de que el supuesto se cumple.

# Calcular los valores ajustados y los residuos
valores_ajustados <- predict(modelo2)
residuos <- resid(modelo2)

# Crear el gráfico de residuos vs. valores ajustados
p <- plot_ly(x = valores_ajustados, y = residuos, mode = 'markers', type = 'scatter',
             marker = list(color = 'rgba(255, 182, 193, .9)'), 
             name = 'Residuos') %>%
  layout(title = "Residuos vs. Valores Ajustados",
         xaxis = list(title = "Valores Ajustados"),
         yaxis = list(title = "Residuos")) %>%
  add_trace(x = c(min(valores_ajustados), max(valores_ajustados)), 
            y = c(0, 0), mode = "lines", 
            line = list(color = "red"), 
            name = "Línea de referencia")

# Mostrar el gráfico
p

En el gráfico se observa que los resíduos se encuentran cercanos a la línea media de cero, sin embargo, con valores ajustados más grandes, la gráfica se hace más dispersa. Esto se confirmaría mediante verificación numérica calculando la media de los resíduos:

media_residuos <- mean(resid(modelo2))
print(media_residuos)
## [1] 3.107396e-15

Este resultado de 3.107396e-15 confirma que este modelo cumple con este supuesto y sugiere que no hay sesgo sistemático en los residuos, lo que es un indicador positivo de la adecuación del modelo.

Homoscedasticidad:

La homocedasticidad se refiere a la constancia de la varianza de los errores del modelo a lo largo de las predicciones, lo cual es crucial para la validez de los intervalos de confianza y las pruebas de hipótesis. Una forma común de verificar la homocedasticidad es a través de gráficos de residuales, donde se grafican los residuales (errores) en función de los valores ajustados (predicciones) o alguna otra variable. Un patrón aleatorio sin forma aparente sugiere homocedasticidad, mientras que un patrón sistemático (como una forma de embudo) indica heterocedasticidad.

Ya en el punto anterior vimos la gráfica, ahora podemos utilizar la prueba de Breusch-Pagan para evaluar si las varianzas de los errores del modelo son constantes a lo largo de los valores predichos.

library(lmtest)

bptest = bptest(modelo2)

print(bptest)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo2
## BP = 131.68, df = 3, p-value < 2.2e-16

el valor p es < 2.2e-16, significa que hay evidencia muy fuerte para rechazar la hipótesis nula de homocedasticidad. Se sugiere que los errores del modelo no tienen varianzas constantes, lo que indica la presencia de heterocedasticidad.

A diferencia de la prueba de Breusch-Pagan, la prueba de Goldfeld-Quandt se enfoca en comparar las varianzas de los errores entre dos subconjuntos de los datos, usualmente después de ordenar los datos respecto a una de las variables independientes.

  gq_test <- gqtest(modelo2, order.by = ~ preciom, data = casasN_numericas)
  print(gq_test)
## 
##  Goldfeld-Quandt test
## 
## data:  modelo2
## GQ = 14.611, df1 = 357, df2 = 357, p-value < 2.2e-16
## alternative hypothesis: variance increases from segment 1 to 2

La prueba de Goldfeld-Quandt, con un p-value < 2.2e-16, al igual que la prueba de Breusch-Pagan, indica la presencia de heterocedasticidad.

Este supuesto no se cumple.

La presencia de heterocedasticidad en un modelo de regresión lineal puede afectar la eficiencia de los estimadores de los coeficientes y hacer que las pruebas de hipótesis sobre estos coeficientes sean menos fiables.

No autocorrelación de errores:

La autocorrelación se refiere a la correlación de los residuos del modelo (errores) con ellos mismos a diferentes tiempos o con diferentes retrasos. La presencia de autocorrelación en los residuos de un modelo de regresión lineal viola uno de los supuestos clave de la regresión lineal, lo que puede llevar a inferencias ineficientes o sesgadas.

La prueba de Durbin-Watson evalúa la hipótesis nula de que no hay autocorrelación en los errores del modelo (específicamente, autocorrelación de primer orden). El valor del estadístico de Durbin-Watson varía entre 0 y 4, donde un valor cercano a 2 sugiere la ausencia de autocorrelación, un valor menor que 2 sugiere autocorrelación positiva, y un valor mayor que 2 sugiere autocorrelación negativa.

durbin <- dwtest(modelo2)
print(durbin)
## 
##  Durbin-Watson test
## 
## data:  modelo2
## DW = 1.6297, p-value = 2.65e-07
## alternative hypothesis: true autocorrelation is greater than 0

El valor del estadístico DW menor que 2, combinado con un p-valor <0.05, sugiere que hay autocorrelación positiva entre los errores del modelo. Los residuos (errores) de la predicción están correlacionados de manera positiva con los residuos de las predicciones anteriores.

Este supuesto no se cumple.

Conclusión de la validación de supuestos sobre los errores:

Teniendo en cuenta los resultados, se identifca que no se cumplen todos los supuestos del modelo, esto puede afectar la eficacia de las estimaciones de los coeficientes y hacer que estos sean menos confiables.

Para tratar el no cumplimiento de los errores se podría realizar:

  • Revisión del modelo para asegurarse que incluya todas las variables relevantes.

  • Revisar los datos e identificar si hay valores atípicos que puedan distorsionar los resultados.

  • Transformación de variables: Aplicar transformaciones a la variable dependiente (por ejemplo, logarítmica, raíz cuadrada o Box-Cox).

  • Si la relación entre las variables independientes y la dependiente no es lineal, considera usar modelos no lineales que puedan capturar mejor la relación.

5. Partición de los datos:

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.

library(caret)

set.seed(123)  # Establecer una semilla para reproducibilidad

particion <- createDataPartition(y = casasN_numericas$preciom, p = 0.70, list = FALSE)

# Dividir los datos usando los índices generados
datosEntrenamiento <- casasN_numericas[particion, ]
datosPrueba <- casasN_numericas[-particion, ]

# Estimar el modelo con el conjunto de entrenamiento
modelo2e <- lm(preciom ~ areaconst + banios + estrato, data = datosEntrenamiento)  

# Resumen del modelo
summary(modelo2e)
## 
## Call:
## lm(formula = preciom ~ areaconst + banios + estrato, data = datosEntrenamiento)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -778.08  -81.07  -18.72   46.62 1039.42 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -222.72082   31.17721  -7.144 3.21e-12 ***
## areaconst      0.91972    0.04973  18.493  < 2e-16 ***
## banios        26.89431    5.01393   5.364 1.24e-07 ***
## estrato       79.36252    8.35628   9.497  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 155.9 on 503 degrees of freedom
## Multiple R-squared:  0.6827, Adjusted R-squared:  0.6808 
## F-statistic: 360.8 on 3 and 503 DF,  p-value: < 2.2e-16
  • El Intercepto de -222.72082 Es el valor del precio que predice el modelo cuando todas las otras variables son 0. En el contexto de este modelo, podría no tener un significado práctico, ya que no es plausible tener un inmueble con 0 metros cuadrados, 0 baños y estrato 0. Traté de correr el modelo con las variables centradas, sin embargo, no me dejaba avanzar con las variables centradas debido a que me arrojaba un mensaje de alerta diciendo que la variable centrada no tenía la misma longitud de las demás y no lo corría.

  • Por cada metro cuadrado adicional en el área de construcción, se espera que el precio aumente en promedio 0.91972, manteniendo constantes las demás variables.

  • Por cada baño adicional, se espera que el precio aumente en promedio 26.89431, manteniendo constantes los demás factores.

  • Por cada aumento en el nivel de estrato, se espera que el precio aumente en promedio 79.36252 unidades de precio, manteniendo constantes los demás factores.

  • Con un p < 0.05 en todos los coeficientes, evidenciamos que son estadísticamente significativos, lo que indica que hay evidencia suficiente para afirmar que estos factores tienen un efecto sobre el precio.

  • EL R cuadrado nos indica que alrededor del 68.27% de la variabilidad en el precio puede ser explicada por el modelo. Este model de entrenamiento genera un mejor R cuadrado que el modelo inicial donde se explicaba el 65%.

  • el F-statistic de 360.8 y el valor p < 2.2e-16, indican que el modelo en general es estadísticamente significativo.

6. Predicciones:

Realice predicciones con el modelo anterior usando los datos de prueba (30%).

#Antes de hacer la predicción, verifico los resultados obtenidos con el modelo utilizando los datos de prueba

modelo2p <- lm(preciom ~ areaconst + banios + estrato, data = datosPrueba)  

summary(modelo2p)
## 
## Call:
## lm(formula = preciom ~ areaconst + banios + estrato, data = datosPrueba)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -685.84  -70.37  -18.58   55.53  926.41 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -234.2532    49.9390  -4.691 4.89e-06 ***
## areaconst      0.6115     0.0814   7.512 1.63e-12 ***
## banios        32.5423    10.0597   3.235  0.00141 ** 
## estrato       93.1241    12.8445   7.250 7.76e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 162.7 on 211 degrees of freedom
## Multiple R-squared:  0.5819, Adjusted R-squared:  0.576 
## F-statistic:  97.9 on 3 and 211 DF,  p-value: < 2.2e-16

En el modelo de prueba se encuentra:

  • El Intercepto de -234.2532 Es el valor del precio que predice el modelo cuando todas las otras variables son 0. Como vimos en el modelo de entrenamiento, esto no tiene un significado práctico, ya que no es plausible tener un inmueble con 0 metros cuadrados, 0 baños y estrato 0.

  • Por cada metro cuadrado adicional en el área de construcción, se espera que el precio aumente en promedio 0.6115, manteniendo constantes las demás variables.

  • Por cada baño adicional, se espera que el precio aumente en promedio 32.5423, manteniendo constantes los demás factores.

  • Por cada aumento en el estrato, se espera que el precio aumente en promedio 93.1241 unidades de precio, manteniendo constantes los demás factores.

  • Con un p < 0.05 en todos los coeficientes, evidenciamos que son estadísticamente significativos, lo que indica que hay evidencia suficiente para afirmar que estos factores tienen un efecto sobre el precio.

  • EL R cuadrado nos indica que alrededor del 58.2% de la variabilidad en el precio puede ser explicada por el modelo. comparado con el modelo de entrenamiento, este modelo de prueba explica menor variabilidad.

  • el F-statistic de 97.9 y el valor p < 2.2e-16, indican que el modelo en general es estadísticamente significativo.

Conclusión del modelo de entrenamiento y prueba:

  • Los interceptos y los coeficientes son diferentes en ambos modelos, esto tiene sentido en cuanto a que los dos datasets pueden tener distribuciones de datos diferentes.

  • Los resultados obtenidos con los datos de entrenamiento tienen un mejor ajuste evidenciado por un R cuadrado mayor que el obtenido en el modelo de prueba.

  • Ambos modelos tienen valor p < 0.05, sugiriendo que hay una relación significativa entre las variables predictoras área construída, baños y estrato con el precio de las casas de la zona norte.

Si queremos tener un modelo generalizable, deberíamos tener en cuenta la validación cruzada y el ajuste de hiperparámetros. No obstante, en la evaluación de supuestos realizada con el modelo original, identificamos que estos no se cumplían, por lo que los resultados podrían no ser confiables.

#Ahora realizo la predicción:

predicciones <- predict(modelo2p, datosPrueba)
head (predicciones)
##        1        2        3        4        5        6 
## 561.3616 366.2514 483.8353 208.0427 311.1185 216.1253

Para combinar los datos originales con los obtenidos en las predicciones:

resultados <- data.frame(Real = datosPrueba$preciom, Prediccion = predicciones)
head(resultados)

Los resultados anteriores nos muestran 6 ejemplos de los primeros datos con el valor real del conjunto de datos de prueba con el valor que predice el modelo para la misma observación basado en las variables incluídas (área construida, baños y estrato) y el modelo entrenado.

En la primera fila, el valor real del precio es 780, sin embaro,el modelo predijo un precio de aproximadamente 561.36. La diferencia entre estos valores sería el error de predicción para esa observación particular. Todas las filas tienen el error de predicción.

7. Cálculo de errores:

Calcule el error cuadrático medio, el error absoluto medio y el R^2, interprete.

Error cuadrático medio:

mse <- mean((resultados$Real - resultados$Prediccion)^2)
mse
## [1] 25982.4

El Error Cuadrático Medio (MSE) Mide el promedio de los cuadrados de los errores. Cuanto más bajo sea el MSE, mejor será el modelo. En este caso un error de 25982.este valor está en unidades al cuadrado, por lo que para hacerlo interpretable, se calcula la raíz de este error:

rmse <- sqrt(mse)
rmse
## [1] 161.1906

En promedio, las predicciones del modelo se desvían al rededor de 161.1906 millones del valor real, lo que a mi concepto, es un valor grande, es más que el precio mínimo de una sola vivienda de la zona.

Error absoluto medio

mae <- mean(abs(resultados$Real - resultados$Prediccion))
mae
## [1] 102.3915

El Error Absoluto Medio (MAE) Es el promedio de los valores absolutos de los errores. Proporciona una idea de la magnitud del error sin considerar su dirección. En este caso es de 102.3915, significa que en promedio, las predicciones del modelo se desvían de los valores reales en 102.3915 millones. Igual que en el cálculo anterior, 102 millones es un valor alto.

Coeficiente de Determinación R^2

ss_total <- sum((resultados$Real - mean(resultados$Real))^2)
ss_residual <- sum((resultados$Real - resultados$Prediccion)^2)
r_squared <- 1 - (ss_residual / ss_total)
r_squared
## [1] 0.5819231

El Coeficiente de Determinación R^2 mide la proporción de la variabilidad en la variable dependiente que es predecible a partir de las variables independientes.En este caso es de 0.581, significa que el modelo corrido con los datos e prueba tiene un nivel moderado de ajuste (menor que en el modelo original), es capaz de explicar más de la mitad de la variabilidad en los precios de las viviendas, pero aún queda una proporción significativa de la variabilidad que no se explica por el modelo.

En relación con la colinealidad, no aplicaría el cálculo, dado que entre las posibles variables predictoras iniciales con la correlación moderada se daba entre habitaciones y baños. Debido a que no tenemos las habitaciones en el modelo, no hay variables derivadas ni categóricas relacionadas y los errores son considerables, entonces no hacemos cálculos adicionales.